Android基于Shader的图像处理(1)-灰度和卷积

android-gpuimage里给出了很多滤镜效果,本质都是用shader处理图像。这里分析几个比较有特点的。
完整代码查看https://github.com/andev009/AndroidShaderDemo中的SharpRender 。

1、灰度图像

通过改变亮度将一副彩色图像变成灰色图像。根据sRGB规范,亮度被定义成红,绿,蓝的线性组合,sRGB中基于亮度值的权值向量为
vec3(0.2125, 0.7154, 0.0721),向量rgb与权值向量的点积就是亮度值。
灰度图像的rgb值都为亮度值。在图像处理的过程中,如果要先取得灰度图像,都是先这样处理。

void main()
{
    mediump vec3 textureColor = texture2D(u_TextureUnit0, v_TextureCoordinates).rgb;
    float luminance = dot(textureColor.rgb, W);
    gl_FragColor = vec4(vec3(luminance), 1.0);
}

Android基于Shader的图像处理(1)-灰度和卷积_第1张图片
gray.png

2、图像卷积(图像锐化)

卷积的作用很多,可以做锐化,模糊等。卷积最好的理解就是一个3X3矩阵和图像上的像素点点积,当然也可以定义5X5这些矩阵。卷积具体的概念就不解释了,重点看如何应用,这里分析图像锐化,gpuimage锐化(sharp filter)的3X3矩阵没有明确定义,不过分析下shader,可知矩阵如下:

float kernelValues[9]=float[9] (
                 0,  -2,  0,
                 -2,  9, -2,
                 0,  -2,  0
          );

知道了卷积矩阵后,还需要取得当前像素的上下左右像素的rgb值,这样才能和矩阵点积。要取得上下左右的像素rgb值,就要取得上下左右的像素的纹理坐标。纹理坐标在shader里的取值范围是[0 ,1],因此纹理坐标的长宽步长分别为:

widthFactor = 1.0f / width//width就是显示图像控件GLSurfaceView的宽度
heightFactor = 1.0f / height//height就是显示图像控件GLSurfaceView的高度

将widthFactor,和heightFactor传到vertex shader里,在vertex shader里u_imageWidthFactor,u_imageHeightFactor就是长宽步长。
这样就可以在vertex shader里取得上下左右的纹理坐标值:

v_TextureCoordinates = a_TextureCoordinates;//当前纹理坐标
mediump vec2 widthHeightStep = vec2(u_imageWidthFactor, u_imageHeightFactor);
mediump vec2 widthNegativeHeightStep = vec2(u_imageWidthFactor, -u_imageHeightFactor);
v_leftTextureCoordinate = a_TextureCoordinates - widthStep;
v_rightTextureCoordinate = a_TextureCoordinates + widthStep;
v_topTextureCoordinate = a_TextureCoordinates + heightStep;
v_bottomTextureCoordinate = a_TextureCoordinates - heightStep;

将上下左右纹理坐标传到fragment shader里,就能取得上下左右像素的rgb值了。

     mediump vec3 textureColor = texture2D(u_TextureUnit0, v_TextureCoordinates).rgb;//当前像素rgb
     mediump vec3 leftTextureColor = texture2D(u_TextureUnit0, v_leftTextureCoordinate).rgb;
     mediump vec3 rightTextureColor = texture2D(u_TextureUnit0, v_rightTextureCoordinate).rgb;
     mediump vec3 topTextureColor = texture2D(u_TextureUnit0, v_topTextureCoordinate).rgb;
     mediump vec3 bottomTextureColor = texture2D(u_TextureUnit0, v_bottomTextureCoordinate).rgb;

最后用卷积矩阵点积计算最终rgb值

mediump vec3 aroundColor = leftTextureColor * 2.0 + rightTextureColor * 2.0 +
                                 topTextureColor * 2.0 + bottomTextureColor * 2.0;
mediump vec3 finalColor = textureColor * 9.0 - aroundColor;
Android基于Shader的图像处理(1)-灰度和卷积_第2张图片
sharp.png

你可能感兴趣的:(Android基于Shader的图像处理(1)-灰度和卷积)