如今,在類似天天P圖、美圖秀秀等手機APP中,給指定照片或視頻中的人物更換頭發顏色已經是再正常不過的事情了。那么本文便介紹了該功能背后如AI頭發分割模塊、頭發換色、顏色增強與修正模塊等技術原理(附代碼)。
首先,為照片或視頻中人物換發色的算法流程如下圖所示:
AI頭發分割模塊
基于深度學習的目標分割算法已經比較成熟,比較常用的有FCN,SegNet,UNet,PspNet,DenseNet等等。這里我們使用Unet網絡來進行頭發分割,具體可以參考如下鏈接:點擊打開鏈接Unet頭發分割代碼如下:
defget_unet_256(input_shape=(256,256,3),num_classes=1):inputs=Input(shape=input_shape)#256down0=Conv2D(32,(3,3),padding='same')(inputs)down0=BatchNormalization()(down0)down0=Activation('relu')(down0)down0=Conv2D(32,(3,3),padding='same')(down0)down0=BatchNormalization()(down0)down0=Activation('relu')(down0)down0_pool=MaxPooling2D((2,2),strides=(2,2))(down0)#128down1=Conv2D(64,(3,3),padding='same')(down0_pool)down1=BatchNormalization()(down1)down1=Activation('relu')(down1)down1=Conv2D(64,(3,3),padding='same')(down1)down1=BatchNormalization()(down1)down1=Activation('relu')(down1)down1_pool=MaxPooling2D((2,2),strides=(2,2))(down1)#64down2=Conv2D(128,(3,3),padding='same')(down1_pool)down2=BatchNormalization()(down2)down2=Activation('relu')(down2)down2=Conv2D(128,(3,3),padding='same')(down2)down2=BatchNormalization()(down2)down2=Activation('relu')(down2)down2_pool=MaxPooling2D((2,2),strides=(2,2))(down2)#32down3=Conv2D(256,(3,3),padding='same')(down2_pool)down3=BatchNormalization()(down3)down3=Activation('relu')(down3)down3=Conv2D(256,(3,3),padding='same')(down3)down3=BatchNormalization()(down3)down3=Activation('relu')(down3)down3_pool=MaxPooling2D((2,2),strides=(2,2))(down3)#16down4=Conv2D(512,(3,3),padding='same')(down3_pool)down4=BatchNormalization()(down4)down4=Activation('relu')(down4)down4=Conv2D(512,(3,3),padding='same')(down4)down4=BatchNormalization()(down4)down4=Activation('relu')(down4)down4_pool=MaxPooling2D((2,2),strides=(2,2))(down4)#8center=Conv2D(1024,(3,3),padding='same')(down4_pool)center=BatchNormalization()(center)center=Activation('relu')(center)center=Conv2D(1024,(3,3),padding='same')(center)center=BatchNormalization()(center)center=Activation('relu')(center)#centerup4=UpSamepling2D((2,2))(center)up4=Concatenate([down4,up4],axis=3)up4=Conv2D(512,(3,3),padding='same')(up4)up4=BatchNormalization()(up4)up4=Activation('relu')(up4)up4=Conv2d(512,(3,3),padding='same')(up4)up4=BatchNormalization()(up4)up4=Activation('relu')(up4)#16up3=UpSamepling2D((2,2))(up4)up3=Concatenate([down4,up4],axis=3)up3=Conv2D(256,(3,3),padding='same')(up3)up3=BatchNormalization()(up3)up3=Activation('relu')(up3)up3=Conv2d(256,(3,3),padding='same')(up3)up3=BatchNormalization()(up3)up3=Activation('relu')(up3)#32up2=UpSamepling2D((2,2))(up3)up2=Concatenate([down4,up4],axis=3)up2=Conv2D(128,(3,3),padding='same')(up2)up2=BatchNormalization()(up2)up2=Activation('relu')(up2)up2=Conv2d(128,(3,3),padding='same')(up2)up2=BatchNormalization()(up2)up2=Activation('relu')(up2)#64up1=UpSamepling2D((2,2))(up2)up1=Concatenate([down4,up4],axis=3)up1=Conv2D(64,(3,3),padding='same')(up1)up1=BatchNormalization()(up1)up1=Activation('relu')(up1)up1=Conv2d(64,(3,3),padding='same')(up1)up1=BatchNormalization()(up1)up1=Activation('relu')(up1)#128up0=UpSamepling2D((2,2))(up1)up0=Concatenate([down4,up4],axis=3)up0=Conv2D(32,(3,3),padding='same')(up0)up0=BatchNormalization()(up0)up0=Activation('relu')(up0)up0=Conv2d(32,(3,3),padding='same')(up0)up0=BatchNormalization()(up0)up0=Activation('relu')(up0)#256classify=Con2D(num_classes,(1,1)),activation='sigmoid')(up0)model=Model(input=inputs,outputs=classify)#model.compile(optimizer=RMSprop(lr=0.0001),loss=bce_dice_loss,metrices=[dice_coeff])returnmodel
分割效果舉例如下:
使用的訓練和測試數據集合大家自己準備即可。
發色更換模塊
這個模塊看起來比較簡單,實際上卻并非如此。這個模塊要細分為:
①頭發顏色增強與修正模塊;
②顏色空間染色模塊;
③頭發細節增強;
發色增強與修正模塊
為什么要對頭發的顏色進行增強與修正? 先看下面一組圖,我們直接使用HSV顏色空間對純黑色的頭發進行染色,目標色是紫色,結果如下:
大家可以看到,針對上面這張原圖,頭發比較黑,在HSV顏色空間進行頭發換色之后,效果圖中很不明顯,只有輕微的顏色變化。
為什么會出現這種情況?原因如下:我們以RGB和HSV顏色空間為例,首先來看下HSV和RGB之間的轉換公式:
設 (r, g, b)分別是一個顏色的紅、綠和藍坐標,它們的值是在0到1之間的實數。設max等價于r, g和b中的最大者。設min等于這些值中的最小者。要找到在HSL空間中的 (h, s, l)值,這里的h ∈ [0, 360)度是角度的色相角,而s, l ∈ [0,1]是飽和度和亮度,計算為:
我們假設頭發為純黑色,R=G=B=0,那么按照HSV計算公式可以得到H = S = V = 0;
假設我們要把頭發顏色替換為紅色(r=255,g=0,b=0);
那么,我們先將紅色轉換為對應的hsv,然后保留原始黑色頭發的V,紅色頭發的hs,重新組合新的hsV,在轉換為RGB顏色空間,即為頭發換色之后的效果(hs是顏色屬性,v是明度屬性,保留原始黑色頭發的明度,替換顏色屬性以達到換色目的);
HSV轉換為RGB的公式如下:
對于黑色,我們計算的結果是H=S=V=0,由于V=0,因此,p=q=t=0,不管目標顏色的hs值是多少,rgb始終都是0,也就是黑色;
這樣,雖然我們使用了紅色,來替換黑色頭發,但是,結果卻依舊是黑色,結論也就是hsv/hsl顏色空間,無法對黑色換色。
下面,我們給出天天P圖和美妝相機對應紫色的換發色效果:
與之前HSV顏色空間的結果對比,我們明顯可以看到,天天P圖和美妝相機的效果要更濃,更好看,而且對近乎黑色的頭發進行了完美的換色;
由于上述原因,我們這里需要對圖像中的頭發區域進行一定的增強處理:提亮,輕微改變色調;
這一步通常可以在PS上進行提亮調色,然后使用LUT來處理;
經過提亮之后的上色效果如下圖所示:
可以看到,基本與美妝相機和天天P圖類似了。
HSV/HSL/YCbCr顏色空間換色
這一步比較簡單,保留明度分量不變,將其他顏色、色調分量替換為目標發色就可以了。
這里以HSV顏色空間為例:
假如我們要將頭發染發為一半青色,一般粉紅色,那么我們構建如下圖所示的顏色MAP:
對于頭發區域的每一個像素點P,我們將P的RGB轉換為HSV顏色空間,得到H/S/V;
根據P在原圖頭發區域的位置比例關系,我們在顏色MAP中找到對應位置的像素點D,將D的RGB轉換為HSV顏色空間,得到目標顏色的h/s/v;
根據目標顏色重組hsV,然后轉為RGB即可;
這一模塊代碼如下:
#h=[0,360],s=[0,1],v=[0,1]voidRGBToHSV(intR,intG,intB,float*h,float*s,float*v){floatmin,max;floatr=R/255.0f;floatg=G/255.0f;floatb=B/255.0f;min=MIN2(r,MIN2(g,b));max=MAX2(r,MAX2(g,b));if(max==min)*h=0;if(max==r&&g>=b)*h=60.0f*(g-b)/(max-min);if(max==r&&g
效果圖如下:
本文算法對比美妝相機效果如下:
頭發區域增強
這一步主要是為了突出頭發絲的細節,可以使用銳化算法,如Laplace銳化,USM銳化等等。上述過程基本是模擬美妝相機染發算法的過程,給大家參考一下,最后給出本文算法的一些效果舉例:
本文效果除了實現正常的單色染發,混合色染發之外,還實現了挑染,如最下方一組效果圖所示。
對于挑染的算法原理:
計算頭發紋理,根據頭發紋理選取需要挑染的頭發束,然后對這些頭發束與其他頭發分開染色即可,具體邏輯這里不再累贅,大家自行研究,這里給出解決思路供大家參考。
最后,本文算法理論上實時處理是沒有問題的,頭發分割已經可以實時處理,所以后面基本沒有什么耗時操作,使用opengl實現實時染發是沒有問題的。
-
AI
+關注
關注
87文章
31527瀏覽量
270339 -
深度學習
+關注
關注
73文章
5515瀏覽量
121553
原文標題:【AI超級美發師】深度學習算法打造染發特效(附代碼)
文章出處:【微信號:AI_era,微信公眾號:新智元】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論