【图像处理】GPUImage的Gaussian Blur

一、高斯模糊

先来看看一般高斯模糊的原理,二维高斯公式是

使用该公式计算出的高斯核看起来是这样的

【图像处理】GPUImage的Gaussian Blur_第1张图片

假设我们计算kernel大小3x3的高斯模糊,取sigma = 1.5,根据二维高斯函数,就可以计算出这个3x3的权重矩阵。

【图像处理】GPUImage的Gaussian Blur_第2张图片

现在计算某个点的像素值,需要取得它周围其它8个点的像素值,

 

【图像处理】GPUImage的Gaussian Blur_第3张图片

每个点乘以对应的权重,就得到

【图像处理】GPUImage的Gaussian Blur_第4张图片

将这9个点的值加起来,就是中心点的高斯模糊值了。

二、GPUImage的快速高斯模糊

但是原始的高斯模糊每个像素都需要做rxr(r是kernel的大小)次乘法再做rxr-1次加法才能得到该像素点的值,不仅是计算量大,而且读取内存的次数也非常大。

其实,二维的高斯模糊可以等价于两个一维高斯的乘积,

 

 

GPUImage的Gaussian Blur计算9x9大小的高斯模糊,就采用了这样一种快速的方法,分别计算水平方向和垂直方向的高斯模糊。

【图像处理】GPUImage的Gaussian Blur_第5张图片

先计算水平方向,在vertex shader中获得中心点和中心点左右各4个点的坐标,假设中心点坐标是(x0,y0),blurStep =(0,1),那其他8个点的坐标分别是(x0-4,y0),(x0-3,y0),(x0-2,y0),(x0-1,y0),(x0+1,y0),(x0+2,y0),(x0+3,y0),(x0+4,y0),

void main()
{
     
gl_Position = position;    
textureCoordinate = inputTextureCoordinate.xy;     
// Calculate the positions for the blur     
int multiplier = 0;     
vec2 blurStep;     
vec2 singleStepOffset = vec2(texelHeightOffset, texelWidthOffset);
     
for (int i = 0; i < GAUSSIAN_SAMPLES; i++)
{        
 multiplier = (i - ((GAUSSIAN_SAMPLES - 1) / 2));
         
// Blur in x (horizontal)         
blurStep = float(multiplier) * singleStepOffset;         
blurCoordinates[i] = inputTextureCoordinate.xy + blurStep;     
}
}

 

 

然后再fragment shader中计算这9个点的加权和,

 

 

void main(){     
lowp vec3 sum = vec3(0.0);     
lowp vec4 fragColor=texture2D(inputImageTexture,textureCoordinate);     
sum += texture2D(inputImageTexture, blurCoordinates[0]).rgb * 0.05;     
sum += texture2D(inputImageTexture, blurCoordinates[1]).rgb * 0.09;     
sum += texture2D(inputImageTexture, blurCoordinates[2]).rgb * 0.12;     
sum += texture2D(inputImageTexture, blurCoordinates[3]).rgb * 0.15;     
sum += texture2D(inputImageTexture, blurCoordinates[4]).rgb * 0.18;     
sum += texture2D(inputImageTexture, blurCoordinates[5]).rgb * 0.15;     
sum += texture2D(inputImageTexture, blurCoordinates[6]).rgb * 0.12;     
sum += texture2D(inputImageTexture, blurCoordinates[7]).rgb * 0.09;     
sum += texture2D(inputImageTexture, blurCoordinates[8]).rgb * 0.05;
gl_FragColor = vec4(sum,fragColor.a);}

计算垂直方向的高斯模糊也是使用这两个shader,不同的是计算水平方向时,texelHeightOffset = 0, texelWidthOffset = 1,计算垂直方向时则正好相反。

在实际取点的时候,并不一定是取相邻点,有一个mBlursize参数可以控制取点的间隔,mBlursize = 1就是取相邻点,mBlursize = 2就是每隔一点取,依次类推。

三、计算量分析

下面来分析一下这个快速高斯的计算量优势,

假设我们需要计算一个MxM大小图像的高斯模糊,高斯模糊的大小是rxr,那么每个像素点需要进行r^2次乘法和(r^2-1)次加法操作。

而这种快速方法仅需要2*r次乘法和2*(r-1)次加法操作。

一个像素点就可以减少r^2-*r次乘法和r^2-2*r+1次加法,对于整幅图像这个数据再乘以M^2,如果是彩色图像,再乘以3,这样减少的计算量是非常可观的,并且如果需要计算的高斯模糊半径越来,减少的计算量越多。

 

 

 

 

 

 

 

你可能感兴趣的:(OpenGL,计算机视觉)