上一章完成了對圖片的磨皮處理,經過簡單算法流程優化,可以達到很快的速度,但是不能用于實時美顏。
經實驗,若采用只處理Y信號的方案,半徑極限大約是5-10,超過10則明顯感受到卡頓,但對于1920X1080的預覽分辨率來說,取10為半徑很難得到理想效果。
即使將分辨率降低到1280X720也差強人意。所以很難簡單的直接應用在移動端實時處理上。
另一方面,人物的正常膚,色應該是偏紅,所以則會導致人物圖像的紅色通道偏亮,使紅色通道保留的細節成分較少,相比之下,綠色通道保留更多細節,所以,一般情況下我們也可以只采用過濾綠色通道來實現實時磨皮。下面對思路簡單介紹:
1.取出綠色通道,對綠色通道進行模糊處理,例如高斯模糊,得到模糊后的值sampleColor:
在頂點著色器中創建長度為20~25的數組,作為片段著色器需要取數據的點
varying vec2 blurCoordinates[20];
blurCoordinates[0] = inputTextureCoordinate.xy + singleStepOffset * vec2(0.0, -10.0);
....
blurCoordinates[19] = inputTextureCoordinate.xy + singleStepOffset * vec2(4.0, -4.0);</span>
在片段著色器依次取出這些點的綠色通道值,乘以權重,最后除以總權重,得到模糊后的綠色通道值
2.用原圖綠色通道值減去sampleColor,加上0.5(即128),1+2兩個步驟即PS中的高反差保留:
vec3 centralColor = texture2D(inputImageTexture, textureCoordinate).rgb;
float highpass = centralColor.g - sampleColor + 0.5;
3.對上述結果值進行3-5次強光處理(見第七章的“疊加”混合模式),此步驟可以使得噪聲更加突出:
if(color <= 0.5){
color = color * color * 2.0;
}else{
color = 1.0 - ((1.0 - color)*(1.0 - color) * 2.0);
}
經過1-3之后的圖:
4.計算原圖的灰度值,公式為0.299*R + 0.587*G + 0.114*B:
const highp vec3 W = vec3(0.299,0.587,0.114);
float lumance = dot(centralColor, W);
得到灰度圖像:
5.將灰度值作為閾值,用來排除非皮膚部分,根據灰度值計算,將原圖與1-3后的結果圖合成:
float alpha = pow(lumance, 0.333333);
vec3 smoothColor = centralColor + (centralColor-vec3(highpass))*alpha*0.1;</span>
原圖rgb值與高反差后的結果相比,噪聲越大,兩者相減后的結果越大,在原結果基礎上加上一定值,來提高亮度,消除噪聲。
pow函數中第二個參數可調(1/3~1),值越小,alpha越大,磨皮效果越明顯,修改該值可作為美顏程度
6.對混合后結果增加亮度:
7.以灰度值作為透明度將原圖與混合后結果進行濾色、柔光等混合,并調節飽和度:
原圖與結果圖:
上面用圖片來舉例子,剩下的就是打開攝像頭切換到前置自己看效果了~
代碼地址:https://github.com/wuhaoyu1990/MagicCamera
MagicCamera/MagicFilter/res/raw/目錄下
beautify_fragment.glsl 與 beautify_vertex.glsl————————————————