深度學習AI美顏系列---美圖秀秀AI美圖之跨次元相機特效算法解析
最近在做類似美圖秀秀AI美圖裏的跨次元相機特效算法,美圖跨次元相機特效舉例如下:
原圖 美圖秀秀跨次元相機效果
Fig. 1美圖秀秀跨次元相機特效舉例
跨次元相機特效是美圖秀秀在2017年開發的一個全新的關於自拍的玩法,能夠讓自己的照片變成手繪美女,做到“照片一秒轉手繪”,效果舉例如上圖所示。最初上線6種風格特效,分別爲“天使之戀、十里桃花、童話萌主、櫻之少女、人魚眼淚、暗夜女爵”。
美圖秀秀跨次元相機特效是一個深度學習和傳統算法相結合的算法組合,並非單一的深度學習算法或者傳統算法可以實現的。
這裏本人將其劃分爲兩個分析過程:表面分析、內在技術分析;
1,表面分析
①跨次元相機到目前爲止,經歷了快兩年的時間,這麼長的更新時間,目前來看,依舊火爆,而且市面上依舊沒有其他類似效果的競爭對手;
②到目前爲止,處理單張照片依舊耗時較長,一般在2-3s左右;
③這項功能對照片上傳大小有較強要求,需要用戶上傳圖像大小不能小於某一尺寸,同時,需要正臉半身照片,五官無遮擋;
上述三點可以看出美圖該算法複雜度較高,不易優化,或者無法實時處理,更無法應用到相機界面,同時,無法較好的處理小臉非半身照片case;
2,內在技術分析
從Fig.1的效果對比來看,本人對其總結如下幾點:
①人像照片做了背景替換,使用到了人像分割技術;
②人像區域中,僅僅頭髮區域進行了頭髮絲特效處理和頭髮區域特效處理,該過程比較複雜,據官方聲明,使用到了機器學習或者DL技術判斷頭髮紋理走勢,在紋理走勢下繪製髮絲效果,目前具體技術尚不可知;
③人像美妝,在圖中可以看到,眉毛、眼影、瞳孔和脣彩等都發生了變化,因此,使用了人像美妝技術;
④人像美顏,在圖中對比可以發現,效果圖中眼睛變大,人臉變小,五官立體感增強,因此,該算法使用了大眼瘦臉、立體五官等臉部微調技術;
⑤人像整體畫面的亮度對比度發生了明顯的變化,因此,個人猜測,該算法具有自動亮度對比度調節功能;
⑥原圖和效果圖中,人像表面增加了特有的貼紙效果,因此,該算法使用了靜態貼紙技術;
⑦頭髮絲繪製算法,美圖跨次元中的頭髮絲繪製效果,可謂時轉手繪的點睛之筆;
基於上述猜測,本人對應實現該算法,效果舉例如下:
原圖 本人跨次元相機算法效果
Fig.2 本人算法效果
在本人算法中沒有使用靜態貼紙,這個可以隨意添加,整體上實現了類似的效果,但是頭髮絲繪製部分還沒有美圖秀秀的夢幻,沒有它更接近手繪風格;
整體而言,這個特效算法允許用戶自定義背景,前景貼紙,頭髮絲繪製顏色以及面部妝容和人臉變形等內容,但由於算法的複雜度,僅僅適合服務器端運行,可以實現對應微信小程序或H5調用,目前本人算法耗時在1S以下,略優於美圖秀秀。
關於算法的具體實現,本文不做詳細展示,所用到的算法及代碼鏈接如下:
②人像染髮
④人像摳圖
⑥顏色濾鏡
⑦頭髮柔順
關於頭髮柔順方面,本人博客中之前並未介紹過,這裏給出一個參考鏈接,該鏈接來自大佬Imageshop: https://www.cnblogs.com/Imageshop/p/10797177.html
使用的時LIC線積分算法來處理頭髮區域的,線積分的示意圖如下:
Fig.3 LIC算法示意圖
代碼如下:
/// make white noise as the LIC input texture ///
void MakeWhiteNoise(int Width, int Height, unsigned char* pNoise)
{
srand(100000);
for (int j = 0; j < Height; j++)
for (int X = 0; X < Width; X++)
{
int r = rand();
r = ((r & 0xff) + ((r & 0xff00) >> 8)) & 0xff;
pNoise[j * Width + X] = (unsigned char)r;
}
}
//LIC
void FastFlowImagingLIC_Appr(int Width, int Height, float* pVectr, unsigned char* pNoise, unsigned char* pImage, float krnlen)
2 {
3 float Step = 0.333333f; // 每次前進0.33333像素的流線距離
4 int LoopAmount = int(krnlen / Step); // 流線是左右對稱的
5 if (LoopAmount <= 0) LoopAmount = 1;
6 int Weight = LoopAmount * 2;
7 for (int Y = 0; Y < Height; Y++)
8 {
9 unsigned char *LinePD = pImage + Y * Width;
10 float *LinePV = pVectr + Y * Width * 2;
11 for (int X = 0; X < Width; X++, LinePV += 2)
12 {
13 float PosX_P = X + 0.5f, PosY_P = Y + 0.5f, PosX_N = X + 0.5f, PosY_N = Y + 0.5f;
14 float VectorX = LinePV[0] * 0.333333f, VectorY = LinePV[1] * 0.333333f;
15 int Sum = 0;
16 for (int Z = 0; Z < LoopAmount; Z++)
17 {
18 PosX_P += VectorX; PosY_P += VectorY; // X和Y都是歸一化的,所以*0.333333f後流線距離也就是0.25了
19 PosX_N -= VectorX; PosY_N -= VectorY;
20 int Index_P = IM_ClampI(PosY_P, 0, Height - 1) * Width + IM_ClampI(PosX_P, 0, Width - 1);
21 int Index_N = IM_ClampI(PosY_N, 0, Height - 1) * Width + IM_ClampI(PosX_N, 0, Width - 1);
22 Sum += pNoise[Index_P] + pNoise[Index_N];
23 }
24 LinePD[X] = (unsigned char)(Sum / Weight);
25 }
26 }
27 }
在Imageshop的鏈接中有詳細的講解,對應效果如圖所示:
Fig.4 線積分特效效果舉例
上述就是整個算法過程的分析,在實際開發中,這個特效綜合了十餘種複雜的算法技術,囊括了美顏美妝以及圖像分割等等內容,算法知識上需要大家對各個方面都有全面的認識,介於商業信息問題,本文僅作技術上的分析,不做詳細代碼展示,掌握了算法之後,相信大家代碼不是問題!
這裏感謝Imageshop大佬的分享!