影视处理

相机滤镜N:卷积内核实现滤镜效果

2020-02-13  本文已影响0人  古风子

上一个章节,我们通过改变着色器中RGB的颜色值,实现了灰色滤镜;本章节讲解另外一张滤镜开发的基本形式

章节目录:

1 滤镜实现方式
 2 卷积内核基础介绍
 3 着色器实现
       3.1 正常滤镜效果
       3.2 浮雕效果

1 滤镜实现方式

相机滤镜,本系列讲解的主要通过opengles实现

opengles又主要分为通过卷积内核对图像进行处理和通过调整RGB通过对图像进行处理,接下里会一 一讲解这两种方式

2 卷积内核基础介绍

相机中的滤镜开发的类型之一是:基于卷积计算开发的,因此本小节计算的原理进行简要的介绍。卷积是一种很常见的数字图像处理操作,其可以用来过滤一幅图像。实现过滤的方法是计算源图像与卷积内核之间的积,所谓卷积内核是指一个nxn的矩阵,n一般为奇数。进行卷积计算时将卷积内核对待处理图像的每个像素都应用一次,具体的计算思路如图下图所示:

卷积内核

图中可以看出,卷积计算将需要处理的图片中的每个像素计的计算方法如下

由以上公式可知,如果卷积内核的为以下值时,处理前后,像素对应的颜色值时不变的:

0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f

通过改变卷积内核各个位置的值,我们可以实现各种滤镜效果

3 着色器实现

根据以上理论知识,我们来实现下基于OPENGL 2.0 的顶点作色器和片元作色器实现

顶点作色器,image3x3TextureSampling_vertext.glsl

attribute vec4 a_position;//应用层传递的顶点坐标
attribute vec2 a_texcoord;//纹理坐标

uniform highp float texelWidth; //从应用层传递的纹理坐标左右偏移量;取值范围,单位像素的0~5倍距离
uniform highp float texelHeight; //从应用层传递的纹理坐标上下偏移量;取值范围,单位像素的0~5倍距离

varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;

varying vec2 topTextureCoordinate;
varying vec2 topLeftTextureCoordinate;
varying vec2 topRightTextureCoordinate;

varying vec2 bottomTextureCoordinate;
varying vec2 bottomLeftTextureCoordinate;
varying vec2 bottomRightTextureCoordinate;

void main()
{
    gl_Position = a_position;

    vec2 widthStep = vec2(texelWidth, 0.0);
    vec2 heightStep = vec2(0.0, texelHeight);
    vec2 widthHeightStep = vec2(texelWidth, texelHeight);
    vec2 widthNegativeHeightStep = vec2(texelWidth, -texelHeight);

    //当前要处理的纹理的像素坐标
    textureCoordinate = a_texcoord.xy;//当前要处理的像素坐标
    //当前要处理的像素的周围八个像素的坐标
    leftTextureCoordinate = a_texcoord.xy - widthStep;//
    rightTextureCoordinate = a_texcoord.xy + widthStep;

    topTextureCoordinate = a_texcoord.xy - heightStep;
    topLeftTextureCoordinate = a_texcoord.xy - widthHeightStep;
    topRightTextureCoordinate = a_texcoord.xy + widthNegativeHeightStep;

    bottomTextureCoordinate = a_texcoord.xy + heightStep;
    bottomLeftTextureCoordinate = a_texcoord.xy - widthNegativeHeightStep;
    bottomRightTextureCoordinate = a_texcoord.xy + widthHeightStep;
}

texelWidth和texelHeight是指当前要处理的像素,距离它周围的八个像素x和y方向的跨度,计算方式如下:

//lineSize 取值范围0~5,默认为1
//width,height表示要处理的图片或者帧数据的宽和高
texelWidth = lineSize / width;
texelHeight = lineSize / height;

片元着色器,image3x3TextureSampling_fragment.glsl

precision mediump float;
uniform sampler2D tex_sampler_0;//应用层传递的纹理内容
uniform mediump mat3 convolutionMatrix;//3*3的卷积内核


//从顶点着色器传递过来的各个像素纹理坐标
varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;

varying vec2 topTextureCoordinate;
varying vec2 topLeftTextureCoordinate;
varying vec2 topRightTextureCoordinate;

varying vec2 bottomTextureCoordinate;
varying vec2 bottomLeftTextureCoordinate;
varying vec2 bottomRightTextureCoordinate;

void main()
{

    //求卷积内核各个值对应的各个像素的值
    mediump vec4 bottomColor = texture2D(tex_sampler_0, bottomTextureCoordinate);
    mediump vec4 bottomLeftColor = texture2D(tex_sampler_0, bottomLeftTextureCoordinate);
    mediump vec4 bottomRightColor = texture2D(tex_sampler_0, bottomRightTextureCoordinate);
    mediump vec4 centerColor = texture2D(tex_sampler_0, textureCoordinate);
    mediump vec4 leftColor = texture2D(tex_sampler_0, leftTextureCoordinate);
    mediump vec4 rightColor = texture2D(tex_sampler_0, rightTextureCoordinate);
    mediump vec4 topColor = texture2D(tex_sampler_0, topTextureCoordinate);
    mediump vec4 topRightColor = texture2D(tex_sampler_0, topRightTextureCoordinate);
    mediump vec4 topLeftColor = texture2D(tex_sampler_0, topLeftTextureCoordinate);

    //乘积加权求和,得出当前片元的颜色
    mediump vec4 resultColor = topLeftColor * convolutionMatrix[0][0] + topColor * convolutionMatrix[0][1] + topRightColor * convolutionMatrix[0][2];
    resultColor += leftColor * convolutionMatrix[1][0] + centerColor * convolutionMatrix[1][1] + rightColor * convolutionMatrix[1][2];
    resultColor += bottomLeftColor * convolutionMatrix[2][0] + bottomColor * convolutionMatrix[2][1] + bottomRightColor * convolutionMatrix[2][2];

    gl_FragColor = resultColor;
}

convolutionMatrix表示应用层传递的卷积内核矩阵信息

通过传入不同的convolutionMatrix值,我们实现不同的滤镜效果

3.1 正常滤镜效果

有以上可知,正常效果的卷积内核为:

0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f

通过前面的计算公式,可以计算出,原象素和目标像素的值没有变化

3.2 浮雕效果

浮雕效果,卷积内核

 float intensity =2.0f;//
{
intensity * (-2.0f),     -intensity,     0.0f,
-intensity,               1.0f,          intensity,
0.0f,                     intensity,      intensity * 2.0f,
}

浮雕效果图

浮雕效果

接下来的文章,会论述其他通过卷积内核实现的滤镜效果

上一篇下一篇

猜你喜欢

热点阅读