图像处理中的卷积运算一般都用来平滑图像、尖锐图像求边缘等等。主要看你选择什么样的核函数了。现在核函数很多,比如高斯平滑核函数,sobel核函数,canny核函数等等。这里举一个sobel核函数的例子来求图像的梯度。
Sobel自动求边缘图(梯度图)在opencv里有特定的函数,具体参照opencv文档(需要自己设定阈值)。这里主要讲怎么用已知的sobel算子(核函数)去平滑当前图像。
C++:void filter2D(InputArraysrc, OutputArray dst, int ddepth, InputArray kernel, Point anchor=Point(-1,-1), doubledelta=0,intborderType=BORDER_DEFAULT)
这里要注意的是kerne,写的是单通道浮点型矩阵。
Sobel核函数:
按图一为例,kernel内核为:
Mat kernelY=Mat::zeros(3,3,CV_32FC1);
????????kernelY.at<float>(0,0)=1;
????????kernelY.at<float>(0,1)=2;
????????kernelY.at<float>(0,2)=1;
????????kernelY.at<float>(1,0)=0;
????????kernelY.at<float>(1,1)=0;
????????kernelY.at<float>(1,2)=0;
????????kernelY.at<float>(2,0)=-1;
????????kernelY.at<float>(2,1)=-2;
????????kernelY.at<float>(2,2)=-1;
注意类型。我一开始写成CV_8U和uchar类型,filter2D卷积后就全是白色的。。
然后就直接调用函数:
filter2D(src,sobelY,-1,kernelY,Point(-1,-1),0.0,BORDER_DEFAULT);
?
sobel函数是x,y方向的卷积的叠加,即:
Sx和sy是两种内核卷积后的图像矩阵。M是最后的sobel梯度图。
如果要直接用sobel函数,可以写成:
Sobel(src,edge1,-1,1,0,3,1.0,0.0,4);//两个方向
Sobel(src,edge2,-1,0,1,3,1.0,0.0,4);
edge=abs(edge1)+abs(edge2); //也可以采用标准的平方根形式叠加
两种方式最后得出的边缘图比较类似,个人感觉filter直接平滑的噪声更少。当然也可以认为检测出的‘边缘点‘(噪声点)个更少
(sobel) (filter)