GPUImage濾鏡實現(xiàn)分析(一)

本文主要記錄學(xué)習(xí)GPUImage濾鏡的算法。
To Do => 貼一個圖 展示所有濾鏡的分類

顏色調(diào)整濾鏡

  • GPUImageBrightnessFilter
    調(diào)整圖像的亮度:
    y = x + 255 * b

    其中x為調(diào)節(jié)前的像素值,y為調(diào)節(jié)后的像素值,b為調(diào)節(jié)參數(shù);即分別在R、G、B三通道上加上調(diào)節(jié)參數(shù)(歸一化后的值)即可。

    vec3 col = texture(iChannel0,uv).rgb;
    float brightness = 0.5;// brightness factor
    col += vec3(brightness);
    fragColor = vec4(col, 1.);
    

    brightness分別等于0.0、0.5、0.7 時:

  • GPUImageExposureFilter
    調(diào)整圖像的曝光度。根據(jù)維基百科給出的定義

    曝光值是一個以2為底的對數(shù)刻度系統(tǒng)。曝光值(EV)滿足公式:
    EV = log_{2}\frac{N^2}{t}

    2^{EV} = \frac{N^2}{t}

    其中N是光圈(f值);t是曝光時間(快門),單位秒。

    因為我們關(guān)心的是曝光值大小與圖像的關(guān)系,所以只看2^{EV}即可。這里GPUImage的作者認為圖像的呈現(xiàn)效果是與2^{EV}大小成線性關(guān)系的。

    // 曝光值設(shè)置成1.0
    const float exposure = 1.;
    vec2 uv = fragCoord/iResolution.xy;
    vec4 col = texture(iChannel0,uv);
    // 調(diào)整圖像的RGB
    col.rgb = col.rgb * pow(2.,exposure);
    fragColor = vec4(col.rgb,1.0);
    

    exposure分別等于0.0、1.0、1.5

  • GPUImageContrastFilter
    調(diào)節(jié)圖像的對比度。對比度,簡單來講就是反應(yīng)了一張圖像的亮區(qū)域和暗區(qū)域的層次感。更詳細的內(nèi)容請訪問對比度。對比度的算法公式:
    y = [x - 127.5 * (1 - b)] * k + 127.5 * (1 + b)
    其中x為調(diào)節(jié)前的像素值,y為調(diào)節(jié)后的像素值;b的取值范圍[-1,1],用于調(diào)節(jié)亮度;k用于調(diào)整對比度。特別地:當(dāng)b=0時, y = (x - 127.5) * k + 127.5,此時只調(diào)整對比度;當(dāng)k=1時, y = x + 255 * b,此時只調(diào)整亮度。

    vec3 col = texture(iChannel0,uv).rgb;
    float contrast = 0.2;
    col = (col.rgb - vec3(.5)) * contrast + vec3(.5);
    fragColor = vec4(col, 1.);
    

    contrast分別等于1.0、2.0、3.0 時:

  • GPUImageSaturationFilter
    調(diào)整圖像的飽和度。色彩調(diào)整之飽和度和亮度已經(jīng)介紹了飽和度相關(guān)的概念,此處不再贅述。

     float saturation = 2.2;
     vec3 col = texture(iChannel0,uv).rgb;
      // 根據(jù)公式計算同等亮度情況下飽和度最低的值 即Saturation=0 
     const vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721);
     float luminance = dot(col,luminanceWeighting);
     vec3 greyScaleColor = vec3(luminance);
     // 在飽和度最低的圖像和原圖之間進行差值
     fragColor = vec4(mix(greyScaleColor, col, saturation), 1.);
    

    當(dāng)saturation分別等于0.0、1.0、2.2時:

  • GPUImageGammaFilter
    伽馬線效果
    f(I) = I^γ

    // gamma值設(shè)置為2.2  一般取值范圍 0.0 ~ 3.0,默認1.0
    const float gamma = 2.2; 
    vec2 uv = fragCoord/iResolution.xy;
    vec4 col = texture(iChannel0,uv);
    // 分別對R、G、B進行g(shù)amma增長
    fragColor = vec4(pow(col.rgb,vec3(gamma)),col.a);
    

    當(dāng)gamma分別等于0.5、1.5、2.5時:

  • GPUImageColorInvertFilter
    反色效果

    vec4 col = texture(iChannel0,uv);
    // rgb取相反值
    fragColor = vec4(1.-col.rgb,col.a);
    
  • GPUImageSepiaFilter
    深褐色(懷舊效果)
    顏色轉(zhuǎn)換公式:
    Red = 0.393 * Red + 0.769 * Green + 0.189 * Blue;\\ Green = 0.349 * Red + 0.686 * Green + 0.168 * Blue;\\ Blue = 0.272 * Red + 0.534 * Green + 0.131 * Blue;

    vec2 uv = fragCoord/iResolution.xy;
    vec4 col = texture(iChannel0,uv);
    
    // common 
    const mat3 RGBToSepiaMatrix = mat3(
      0.393,0.769,0.189,
      0.349,0.686,0.168,
      0.272,0.534,0.131
    );
    // gpuimage使用的Matrix
    const mat3 RGBToSepiaMatrix = mat3(
        0.3588,0.7044,0.1368,
        0.2990,0.5870,0.1140,
        0.2392,0.4696,0.0912
    );
    const float sepiaIntensity = 1.;
    col.rgb = mix(col.rgb,col.rgb * RGBToSepiaMatrix,sepiaIntensity);
    fragColor = vec4(col.rgb,1.0);
    

    https://learnopengl.com/Advanced-Lighting/Gamma-Correction

  • GPUImageLevelsFilter

  • GPUImageGrayscaleFilter
    灰度濾鏡。獲取圖片的灰度圖方法有很多種,常見的有平均值法、心理學(xué)法、去飽和法、分解法、單一通道法
    平均值法:Gray = (Red + Green + Blue) / 3
    心理學(xué)法:Gray = (Red * 0.3 + Green * 0.59 + Blue * 0.11)
    和心理學(xué)類似的算法還有:Gray = (Red * 0.2126 + Green * 0.7152 + Blue * 0.0722)Gray = (Red * 0.299 + Green * 0.587 + Blue * 0.114)
    去飽和法: Gray = (max(Red, Green, Blue) + min(Red, Green, Blue) ) / 2
    分解法:Gray = max(Red, Green, Blue) 或 Gray = min(Red, Green, Blue)
    單一通道法:Gray = Red 或 Gray = Green 或 Gray = Blue
    GPUImage這里采用的是心理學(xué)法。

     const vec3 W = vec3(0.2125, 0.7154, 0.0721);
     vec4 col = texture(iChannel0,uv);
     // to gray 
     float gray = dot(col.rgb,W);
     fragColor = vec4(vec3(gray),1.0);
    

    注: dot(col.rgb,W) = col.r * W.x + col.g * W.y + col.b * W.z

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容