1. 程式人生 > >Android OpenGL ES濾鏡開發之美顏效果

Android OpenGL ES濾鏡開發之美顏效果

前言

其實之前我就是已經把美顏效果啥的都做完了,但是就一直懶得記錄,今天來記錄一下,之前記錄的就是大眼睛還有貼紙的效果。以前的時候不愛寫部落格,總覺得很麻煩,現在發現寫部落格是用來總結複習很好的一個途徑,很多時候寫效果或者做些什麼,就基本就是做完就完事兒了,也不去總結一下或者拿來複習一下,所以有的時候自己寫過的東西,自己就不記得了。
寫這個美顏效果,也參考了很多的資料,在文章的最後會把參考的文獻列出來,供大家參考研究。

實現

  1. 高斯模糊
    也叫做高斯平滑,主要是用來降低影象早生以及降低細節層次,是的影象看起來更加的平滑。
    在片雲著色器中,取當前資料周邊的20個點的顏色通道的值,進行相加然後得出平均值,這就是模糊後的取樣點的顏色。
      vec2 singleStepOffset =
    vec2(1.0/float(width),1.0/float(height)); blurCoordinates[0] = aCoord.xy + singleStepOffset * vec2(0.0, -10.0); blurCoordinates[1] = aCoord.xy + singleStepOffset * vec2(0.0, 10.0); blurCoordinates[2] = aCoord.xy + singleStepOffset * vec2(-10.0, 0.0); blurCoordinates[3] = aCoord.xy + singleStepOffset * vec2(10.0, 0.0
    ); blurCoordinates[4] = aCoord.xy + singleStepOffset * vec2(5.0, -8.0); blurCoordinates[5] = aCoord.xy + singleStepOffset * vec2(5.0, 8.0); blurCoordinates[6] = aCoord.xy + singleStepOffset * vec2(-5.0, 8.0); blurCoordinates[7] = aCoord.xy + singleStepOffset * vec2(-5.0, -8.0); blurCoordinates[8] = aCoord.
    xy + singleStepOffset * vec2(8.0, -5.0); blurCoordinates[9] = aCoord.xy + singleStepOffset * vec2(8.0, 5.0); blurCoordinates[10] = aCoord.xy + singleStepOffset * vec2(-8.0, 5.0); blurCoordinates[11] = aCoord.xy + singleStepOffset * vec2(-8.0, -5.0); blurCoordinates[12] = aCoord.xy + singleStepOffset * vec2(0.0, -6.0); blurCoordinates[13] = aCoord.xy + singleStepOffset * vec2(0.0, 6.0); blurCoordinates[14] = aCoord.xy + singleStepOffset * vec2(6.0, 0.0); blurCoordinates[15] = aCoord.xy + singleStepOffset * vec2(-6.0, 0.0); blurCoordinates[16] = aCoord.xy + singleStepOffset * vec2(-4.0, -4.0); blurCoordinates[17] = aCoord.xy + singleStepOffset * vec2(-4.0, 4.0); blurCoordinates[18] = aCoord.xy + singleStepOffset * vec2(4.0, -4.0); blurCoordinates[19] = aCoord.xy + singleStepOffset * vec2(4.0, 4.0); //計算平均值 vec4 currentColor = texture2D(vTexture,aCoord); vec3 rgb = currentColor.rgb; //計算座標的顏色值總和 for(int i=0 ; i < 20 ; i++){ rgb += texture2D(vTexture,blurCoordinates[i].xy).rgb; } //平均值 vec4 blur = vec4(rgb * 1.0 /21.0,currentColor.a);
  2. 高反差保留
    在經過高斯模糊之後的影象,也會把需要突出的五管等也模糊掉,這顯然不符合我們的要求,所以這裡需要高反差保留。高反差保留有兩個公式,這裡我只用簡單的這一種公式:高反差保留 = 原圖 - 高斯模糊圖,然後將原圖和高反差保留圖進行疊加,可以得到銳化的影象。
     //高反差保留演算法
     // 原圖 - 高斯模糊圖
     vec4 highPassColor = currentColor - blur;
    
    出來的效果圖是這樣
  3. 強光處理
    經過高反差以後,影象比較暗淡,所以這裡進行一個強光操作
   // 強光處理 color = 2 * color1 * color2
    //  24.0 強光程度
    //clamp  獲取三個引數中處於中間的那個
    highPassColor.r = clamp(2.0 * highPassColor.r * highPassColor.r * 24.0,0.0,1.0);
    highPassColor.g = clamp(2.0 * highPassColor.g * highPassColor.g * 24.0,0.0,1.0);
    highPassColor.b = clamp(2.0 * highPassColor.b * highPassColor.b * 24.0,0.0,1.0);
   //過濾疤痕
    vec4 highPassBlur = vec4(highPassColor.rgb,1.0);

效果圖:

  1. 融合
   // 融合 -> 磨皮
    //藍色通道
    float b = min(currentColor.b,blur.b);
    float value = clamp((b - 0.2) * 5.0,0.0,1.0);
    //RGB 的最大值
    float maxChannelColor = max(max(highPassBlur.r,highPassColor.g),highPassBlur.b);
    
    //磨皮程度
    float intensity = 1.0;
    float currentIntensity = (1.0 - maxChannelColor / (maxChannelColor + 0.2)) * value *intensity;
    
    //混合
    //OpenGL 內建函式 線性融合
    // 公式 x * (1-a) + y.a
    vec3 r = mix(currentColor.rgb,blur.rgb,currentIntensity);

    gl_FragColor = vec4(r,1.0) 

效果圖:
在這裡插入圖片描述

這裡效果可能比較模糊,因為我的手機的後置攝像頭有點問題,但是我不太像本人出境,所以就emmm…湊合看一下效果吧,總體來說這個效果還是OK的。

參考資料

  1. https://blog.csdn.net/oShunz/article/details/50536031
  2. https://www.jianshu.com/p/a76a1201ae53
  3. https://blog.csdn.net/matrix_space/article/details/22426633
  4. https://www.jianshu.com/p/bb702124d2ad