思路:
1.?面部皺紋紋理。變老后的皺紋并不是實時繪制眶蕉,而是需要先準(zhǔn)備一系列皺紋紋理,然后將皺紋紋理和正常面部紋理融合唧躲。
?2.由于檢測的人臉姿態(tài)多變造挽,有的頭正頸直,有的歪頭弄痹,有的仰頭饭入,而皺紋紋理都是頭正頸直的,所以還需要對皺紋紋理做合適的變形肛真,而非旋轉(zhuǎn)谐丢,旋轉(zhuǎn)的話匹配精度不夠。本文采用的是移動最小二乘法圖像變形(mls)算法蚓让。
?3.由于涉及到mls變形算法乾忱,所以需要控制點。本文采用的是提取人77個特征點历极,由于標(biāo)準(zhǔn)77個特征點主要分布在臉頰窄瘟、眉毛、眼睛趟卸、鼻子蹄葱、嘴巴,為了保證變形更精準(zhǔn)衰腌,所以又計算增補了部分額頭控制點新蟆,共計77個特征點作為變形控制點。
步驟:
1.準(zhǔn)備幾張面部皺紋的圖右蕊,并標(biāo)注人臉特征點
面部皺紋圖人臉關(guān)鍵點琼稻,一共81個點
public static final float[] OLD_FACE = {62.0f, 296.0f, 62.0f, 362.0f, 76.0f, 430.0f, 97.0f, 505.0f, 133.0f...........};
人臉關(guān)鍵點位置分布圖
人臉關(guān)鍵點采集
人臉關(guān)鍵點識別一般可以采用Dlib或者?Stasm?+?OpenCV,
使用Dlib的話可以參照face_landmark_detection?來獲取人臉68個關(guān)鍵點,不依賴于OpenCV饶囚,但是需要61M的模型文件帕翻,同時也沒有額頭部分的標(biāo)注。
使用Stasm可以參考示例minimal?使用它可以獲取77個人臉關(guān)鍵點,?只需要OpenCV的幾個xml的模型文件萝风, 體積比dlib的模型小嘀掸,比較適合移動端設(shè)備使用,所以我選擇了這個规惰。
SeetaFace2也是一個可行的方案睬塌,可以參考SeetaFace2?可以實現(xiàn)人臉81個關(guān)鍵點識別,不依賴于OpenCV,效果也不錯揩晴,不過相比于Stasm勋陪,SeetaFace2不會標(biāo)注人額頭上的關(guān)鍵點。
最小二乘法
最小二乘法(又稱最小平方法)是一種數(shù)學(xué)優(yōu)化技術(shù)硫兰。它通過最小化誤差的平方和尋找數(shù)據(jù)的最佳函數(shù)匹配诅愚。利用最小二乘法可以簡便地求得未知的數(shù)據(jù),并使得這些求得的數(shù)據(jù)與實際數(shù)據(jù)之間誤差的平方和為最小劫映。最小二乘法還可用于曲線擬合违孝。其他一些優(yōu)化問題也可通過最小化能量或最大化熵用最小二乘法來表達(dá)。
在圖像處理領(lǐng)域paper:《Image Deformation Using Moving Least Squares》利用移動最小二乘的原理實現(xiàn)了圖像的相關(guān)變形泳赋,而且這篇paper的引用率非常高雌桑,可以說是圖像變形算法的經(jīng)典算法,Siggraph上面的paper祖今。
變老實現(xiàn)
1.???通過OpenCV+Stasm獲取原始圖像人臉關(guān)鍵點數(shù)據(jù)
2.?將圖片切割成若干個網(wǎng)格筹燕,得到原始網(wǎng)格點
3.最小二乘法,得到變形后的網(wǎng)格點
最小二乘法衅鹿,輸入:
原始網(wǎng)格點:將圖像切割成areaW * areaH?的網(wǎng)格區(qū)域
控制點:就是上面提供的81個人臉關(guān)鍵點。
目標(biāo)控制點:原始圖通過stasm得到的的人臉關(guān)鍵點过咬。
輸出:變形后的網(wǎng)格點
4.現(xiàn)在我們已經(jīng)有了原始網(wǎng)格點大渤、變形后的網(wǎng)格點,接下來就計算頂點紋理坐標(biāo)和繪制索引掸绞,使用VBO繪制圖元泵三,繪制出經(jīng)過變形的老人皺紋圖,然后與原始圖融合衔掸,得到最終變老效果烫幕。
4.1計算頂點數(shù)據(jù)
4.2計算繪制索引
4.3創(chuàng)建FloatBuffer和ShortBuffer,供后面使用
5.融合敞映,變老shader
可以看到有兩個2d?紋理
inputImageTexture:代表原圖紋理
inputImageTexture2?:代表變形后的皺紋紋理
這一步就是對兩層進(jìn)行融合計算较曼,內(nèi)建函數(shù)mix混合,intensity代表皺紋透明度
mediump vec4 outputColor = vec4(base.rgb * (overlay.a * (base.rgb / base.a) + (2.0 * overlay.rgb * (1.0 - (base.rgb / base.a)))) + overlay.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlay.a), base.a);\n"
6振愿、VBO繪制
5.最終效果