上篇介绍了openCV自带的滤波函数库,中篇介绍了基于中值滤波的改进滤波算法:自适应中值滤波。这一篇将介绍OpenCV的卷积操作函数:void cvFilter2D( const CvArr* src, CvArr* dst,const CvMat* kernel,CvPoint anchor=cvPoint(-1,-1));
其中:src表示输入图像;dst表示输出图像;kernel表示卷积核,为单通道浮点矩阵, 如果想要应用不同的核于不同的通道,需要先用 cvSplit 函数分解图像到单个色彩通道上,然后单独处理;anchor为核的锚点,表示一个被滤波的点在核内的位置((-1,-1)点表示核的中心点)。
这是C语言版本的,卷积函数还有C++版本的,其函数形式为:CV_EXPORTS_W void filter2D( InputArray src, OutputArray dst, int ddepth, InputArray kernel, Point anchor=Point(-1,-1), double delta=0, int borderType=BORDER_DEFAULT );
其中:
InputArray src表示输入图像;OutputArray dst表示 输出图像,和输入图像具有相同的尺寸和通道数量;int ddepth表示 目标图像深度,如果没写将生成与原图像深度相同的图像,当ddepth输入值为-1时,目标图像和原图像深度保持一致;InputArray kernel表示 卷积核,是一个单通道浮点型矩阵。如果想在图像不同的通道使用不同的kernel,需要先使用split()函数将多通道图像分离成单通道图像;Point anchor表示 内核的锚点,其默认值为(-1,-1)说明位于kernel的中心位置;double delta表示 在储存目标图像前可选的添加到像素的值,默认值为0;int borderType表示 像素向外逼近的方法,默认值BORDER_DEFAULT,即对全部边界进行计算。
下面使用C++版本的库函数filter2D
来依次进行图像的模糊、去噪、锐化和边缘检测等操作。
在此,先简单介绍一下图像处理中的卷积概念。
图像处理中的卷积概念与数字信号处理中的卷积概念不同,它更趋向于相对求和,对卷积模板中所有的点进行累加求和。如下图所示:
卷积模板中的矩阵元素为:
(A) [ 4 0 0 0 0 0 0 0 − 4 ] \left[ \begin{matrix} 4 & 0 & 0 \\ 0 & 0 & 0 \\ 0 & 0 & -4 \end{matrix} \right] \tag{A} ⎣⎡40000000−4⎦⎤(A)
原图像中要进行卷积操作的矩阵元素为:
(B) [ 0 0 0 0 1 1 0 1 2 ] \left[ \begin{matrix} 0 & 0 & 0 \\ 0 & 1 & 1 \\ 0 & 1 & 2 \end{matrix} \right] \tag{B} ⎣⎡000011012⎦⎤(B)
对A、B中的各元素依次对应相乘最后求和即得到了卷积后的像素点的值,该值替换原图像中的位置由锚点决定 Point anchor=Point(-1,-1) ,其中(-1,-1)表示在卷积核的中心位置。依次逐个点遍历全图即可得到最终的卷积滤波后的图像。
1、图像模糊
先以卷积核为
(A) [ 0 0 0 0 1 0 0 0 0 ] \left[ \begin{matrix} 0 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 0 \end{matrix} \right] \tag{A} ⎣⎡000010000⎦⎤(A)
来说明,
如上图所示,滤波前后图像无变化,因为卷积核中除中心位置外,其他位置都为0,卷积后的结果就是中心处的像素点,也就相当于并没有对图像滤波。
均值滤波
均值滤波卷积核为:
(B) [ 1 / 9 1 / 9 1 / 9 1 / 9 1 / 9 1 / 9