卷积,使用filter2D创建自定义线性滤波器
- 卷积
一个特殊卷积所实现的功能是由其卷积核的形式决定的。这个核本质上是一个大小固定、由数值参数构成的数组,数组的参考点(anchor point,也叫锚点)通常位于数组的中心。
上图描述了一个以数组中心为参考点的3X3的卷积核,-4所在为锚点。若要计算图像上某个点的卷积值,则将卷积核的锚点定位到图像上的那个点,让核的其它元素覆盖图像中的相应的像素点。将图像上的点与卷积核对应相乘后再求和,并将这个结果放在图像上锚点的相对位置上。通过在图像上扫描卷积核,对图像的每个点重复此操作。
可以用以上公式来表示这个过程,其中定义图像为I(x,y),核为G(i,j),其中0<i<Mi-1和0<j<Mj-1,锚点位于相应核的(ai,aj)坐标上。
- filter2D函数
函数原型为:
void filter2D(InputArray src, OutputArray dst, int ddepth, InputArray kernel, Pointanchor=Point(-1,-1), double delta=0, int borderType=BORDER_DEFAULT )
使用这个函数可以将任何的线性变换应用到图像上,其中各参数的含义如下:
src:源图像
dst:目标图像
ddepth:dst的尝试,若为负值(如-1),则表示其深度与源图像相等。
kernel:用来遍历图像的核
anchor:核的锚点的相对位置,其中心点默认为(-1,-1)。
delta:在卷积的过程中,该值会加到每个像素上。默认情况下,这个值为0。
BORDER_DEFAULT:像素插值方法,这里为默认值,详细可以参照borderInterpolate()方法。
- filter2D例程:
int _tmain(int argc, _TCHAR* argv[]) { Mat src = imread("girl.jpg"); if (!src.data) { return -1; } imshow("src",src); Mat dst; int ddepth = -1; Mat kernel; int c = 0; int ind = 0; while(true) { if (c == 27) break; int kernel_size = 3 + 2 * (ind % 5); cout<<kernel_size<<endl; //Mat::ones将定义一个矩阵,里面的元素全部置1 kernel = Mat::ones(kernel_size,kernel_size,CV_32F)/(float)(kernel_size*kernel_size); filter2D(src,dst,ddepth,kernel); ind++; imshow("dst",dst); waitKey(0); } return 0; }
运行该程序,将显示了由归一化滤波器模糊之后的图像。每过1秒,滤波器核的大小(边长从3~11)会有所变化: