图像处理算法——卷积
2016-06-06 17:34
363 查看
本文索引:
一 什么是卷积
二 相关算子
三 卷积算子
四 边缘效应
五 常用的卷积核及其用途
六 一个例子使用卷积实现模糊效果
卷积核(算子)是用来做图像处理时的矩阵,图像处理时也称为掩膜,是与原图像做运算的参数。卷积核通常是一个四方形的网格结构(例如3*3的矩阵或像素区域),该区域上每个方格都有一个权重值。
使用卷积进行计算时,需要将卷积核的中心放置在要计算的像素上,一次计算核中每个元素和其覆盖的图像像素值的乘积并求和,得到的结构就是该位置的新像素值。
以下两个算子中演示了具体的卷积计算过程。
即
,其中h称为相关核(Kernel).
步骤:
1)滑动核,使其中心位于输入图像g的(i,j)像素上
2)利用上式求和,得到输出图像的(i,j)像素值
3)充分上面操纵,直到求出输出图像的所有像素值
【例】
原始像素矩阵为:
⎡⎣⎢⎢⎢⎢⎢⎢17234101124561218171319258142021215162239⎤⎦⎥⎥⎥⎥⎥⎥
卷积模板h为:
⎡⎣⎢834159672⎤⎦⎥
计算输出图像的(2,4)元素=1*8+8*1+15*6+7*3+14*5+16*7+13*4+20*9+22*2=585
如图所示:
即
步骤:
- 1)将核围绕中心旋转180度
- 2)滑动核,使其中心位于输入图像g的(i,j)像素上
- 3)利用上式求和,得到输出图像的(i,j)像素值
- 4)充分上面操纵,直到求出输出图像的所有像素值
例:计算输出图像的(2,4)元素=1*2+8*9+15*4+7*7+14*5+16*3+13*6+20*1+22*8=575
如图所示:
常用的策略包括:
- 1)使用常数填充:imfilter默认用0填充,这会造成处理后的图像边缘是黑色的。
- 2)复制边缘像素:I3 = imfilter(I,h,’replicate’);
⎡⎣⎢1/101/101/101/102/101/101/101/101/10⎤⎦⎥
⎡⎣⎢1/162/161/162/164/162/161/162/161/16⎤⎦⎥
2)高斯滤波器(常用于计算高斯模糊后的效果)
高斯模糊的卷积核也是一个正方形的滤波核,其中每个元素通过以下公式计算得出:
G(x,y)=12πσ2⋅ex2+y22σ2
该公式中σ是标准方差(一般取值为1),x和y分别对应了当前位置到卷积核中心的整数距离。通过这个公式,就可以计算出高斯核中每个位置对应的值。为了保证滤波后的图像不会变暗,需要对高斯核中的权重进行归一化。
3)边缘检测(常用于计算图像边缘或者说梯度值)
⎡⎣⎢−10−1040−10−1⎤⎦⎥
以下为compute shader中关于卷积处理的代码:
效果如图所示:
图中可以明显的看到左右两边有明显的黑色线条,原图中是没有这样的黑色的,产生这种效果的原因是本文中之前提到过的边缘效应。下面我将修改一部分代码去除边缘效应带来的影响,这里使用的是相邻像素的值方法。
代码如下:
效果如图所示:
可以看到,图中左边的黑色线条已经被滤除,右边也可以采用类似的方法来剔除。实际使用中,也可以根据情况使用纯色来做剔除,这样可以节省部分效率,如下图中我使用的是纯白色来剔除边缘效应。
一 什么是卷积
二 相关算子
三 卷积算子
四 边缘效应
五 常用的卷积核及其用途
六 一个例子使用卷积实现模糊效果
一、 什么是卷积?
在图像处理中,卷积操作指的是使用一个卷积核对图像中的每个像素进行一系列操作。卷积核(算子)是用来做图像处理时的矩阵,图像处理时也称为掩膜,是与原图像做运算的参数。卷积核通常是一个四方形的网格结构(例如3*3的矩阵或像素区域),该区域上每个方格都有一个权重值。
使用卷积进行计算时,需要将卷积核的中心放置在要计算的像素上,一次计算核中每个元素和其覆盖的图像像素值的乘积并求和,得到的结构就是该位置的新像素值。
以下两个算子中演示了具体的卷积计算过程。
二、 相关算子
定义:即
,其中h称为相关核(Kernel).
步骤:
1)滑动核,使其中心位于输入图像g的(i,j)像素上
2)利用上式求和,得到输出图像的(i,j)像素值
3)充分上面操纵,直到求出输出图像的所有像素值
【例】
原始像素矩阵为:
⎡⎣⎢⎢⎢⎢⎢⎢17234101124561218171319258142021215162239⎤⎦⎥⎥⎥⎥⎥⎥
卷积模板h为:
⎡⎣⎢834159672⎤⎦⎥
计算输出图像的(2,4)元素=1*8+8*1+15*6+7*3+14*5+16*7+13*4+20*9+22*2=585
如图所示:
三、 卷积算子
定义:即
步骤:
- 1)将核围绕中心旋转180度
- 2)滑动核,使其中心位于输入图像g的(i,j)像素上
- 3)利用上式求和,得到输出图像的(i,j)像素值
- 4)充分上面操纵,直到求出输出图像的所有像素值
例:计算输出图像的(2,4)元素=1*2+8*9+15*4+7*7+14*5+16*3+13*6+20*1+22*8=575
如图所示:
四、 边缘效应
当对图像边缘的进行滤波时,核的一部分会位于图像边缘外面。常用的策略包括:
- 1)使用常数填充:imfilter默认用0填充,这会造成处理后的图像边缘是黑色的。
- 2)复制边缘像素:I3 = imfilter(I,h,’replicate’);
五、 常用的卷积核及其用途
1)低通滤波器(常用于计算模糊后的效果)⎡⎣⎢1/91/91/91/91/91/91/91/91/9⎤⎦⎥⎡⎣⎢1/101/101/101/102/101/101/101/101/10⎤⎦⎥
⎡⎣⎢1/162/161/162/164/162/161/162/161/16⎤⎦⎥
2)高斯滤波器(常用于计算高斯模糊后的效果)
高斯模糊的卷积核也是一个正方形的滤波核,其中每个元素通过以下公式计算得出:
G(x,y)=12πσ2⋅ex2+y22σ2
该公式中σ是标准方差(一般取值为1),x和y分别对应了当前位置到卷积核中心的整数距离。通过这个公式,就可以计算出高斯核中每个位置对应的值。为了保证滤波后的图像不会变暗,需要对高斯核中的权重进行归一化。
3)边缘检测(常用于计算图像边缘或者说梯度值)
⎡⎣⎢−10−1040−10−1⎤⎦⎥
六、 一个例子——使用卷积实现模糊效果
我们将对下面这张图进行模糊处理:以下为compute shader中关于卷积处理的代码:
[numthreads(32,32,1)] void Dim_Main (uint3 id : SV_DispatchThreadID) { float sumR = 0; float sumG = 0; float sumB = 0; float sumA = 0; for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { sumR += texBuffer[(id.x+i)*texWidth[0]+(id.y+j)].r * convolutionTempBuffer[(i+1)*3+(j+1)]; sumG += texBuffer[(id.x+i)*texWidth[0]+(id.y+j)].g * convolutionTempBuffer[(i+1)*3+(j+1)]; sumB += texBuffer[(id.x+i)*texWidth[0]+(id.y+j)].b * convolutionTempBuffer[(i+1)*3+(j+1)]; sumA += texBuffer[(id.x+i)*texWidth[0]+(id.y+j)].a * convolutionTempBuffer[(i+1)*3+(j+1)]; } } texBuffer[id.x*texWidth[0]+id.y].r = sumR; texBuffer[id.x*texWidth[0]+id.y].g = sumG; texBuffer[id.x*texWidth[0]+id.y].b = sumB; texBuffer[id.x*texWidth[0]+id.y].a = sumA; Result[id.xy] = float4(sumR, sumG, sumB, sumA); }
效果如图所示:
图中可以明显的看到左右两边有明显的黑色线条,原图中是没有这样的黑色的,产生这种效果的原因是本文中之前提到过的边缘效应。下面我将修改一部分代码去除边缘效应带来的影响,这里使用的是相邻像素的值方法。
代码如下:
[numthreads(32,32,1)] void Dim_Main (uint3 id : SV_DispatchThreadID) { float sumR = 0; float sumG = 0; float sumB = 0; float sumA = 0; for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if((id.x+i)*texWidth[0]+(id.y+j)>texWidth[0]*texWidth[0]-1) { sumR += texBuffer[(id.x+i)*texWidth[0]+(id.y+j)-texWidth[0]].r * convolutionTempBuffer[(i+1)*3+(j+1)]; sumG += texBuffer[(id.x+i)*texWidth[0]+(id.y+j)-texWidth[0]].g * convolutionTempBuffer[(i+1)*3+(j+1)]; sumB += texBuffer[(id.x+i)*texWidth[0]+(id.y+j)-texWidth[0]].b * convolutionTempBuffer[(i+1)*3+(j+1)]; sumA += texBuffer[(id.x+i)*texWidth[0]+(id.y+j)-texWidth[0]].a * convolutionTempBuffer[(i+1)*3+(j+1)]; } sumR += texBuffer[(id.x+i)*texWidth[0]+(id.y+j)].r * convolutionTempBuffer[(i+1)*3+(j+1)]; sumG += texBuffer[(id.x+i)*texWidth[0]+(id.y+j)].g * convolutionTempBuffer[(i+1)*3+(j+1)]; sumB += texBuffer[(id.x+i)*texWidth[0]+(id.y+j)].b * convolutionTempBuffer[(i+1)*3+(j+1)]; sumA += texBuffer[(id.x+i)*texWidth[0]+(id.y+j)].a * convolutionTempBuffer[(i+1)*3+(j+1)]; } } texBuffer[id.x*texWidth[0]+id.y].r = sumR; texBuffer[id.x*texWidth[0]+id.y].g = sumG; texBuffer[id.x*texWidth[0]+id.y].b = sumB; texBuffer[id.x*texWidth[0]+id.y].a = sumA; Result[id.xy] = float4(sumR, sumG, sumB, sumA); }
效果如图所示:
可以看到,图中左边的黑色线条已经被滤除,右边也可以采用类似的方法来剔除。实际使用中,也可以根据情况使用纯色来做剔除,这样可以节省部分效率,如下图中我使用的是纯白色来剔除边缘效应。
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析
- C++实现汉诺塔算法经典实例