边缘检测Canny算子、Sobel算子、Laplace算子、Scharr滤波器
一、 Canny算子
1.1 Canny()函数各参数详解
void Canny(InputArray image,OutputArray edges,double threshold1,doublethreshold2,int apertureSize = 3,boolL2gradient =false)
Ø 第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像。
Ø 第二个参数,OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和类型。
Ø 第三个参数,double类型的threshold1,第一个滞后性阈值。
Ø 第四个参数,double类型的threshold2,第二个滞后性阈值。
Ø 第五个参数,int类型的apertureSize,表示应用Sobel算子的孔径大小,其有默认值3。
Ø 第六个参数,bool类型的L2gradient,一个计算图像梯度幅值的标识,有默认值false。
需要注意的是,这个函数阈值1和阈值2两者的小者用于边缘连接,而大者用来控制强边缘的初始段,推荐的高低阈值比在2:1到3:1之间。
1.2调用示例
Mat
ScrImage = imread("E:\\1TJQ\\Opencv\\Images\\image1.jpg");
Canny(ScrImgae,OutImage1, 150, 50, 3); //Canny边缘检测算法
imshow("Canny边缘检测算法", OutImage1);
二、 Sobel算子
2.1 Sobel ()函数各参数详解
void Sobel(InputArray src,OutputArray dst,int ddepth,int dx,int dy, int ksize = 3,double scale =1, double delta = 0,int borderType = BORDER_DEFAULT)
Ø 第一个参数,InputArray 类型的src,为输入图像,填Mat类型即可。
Ø 第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
Ø 第三个参数,int类型的ddepth,输出图像的深度,支持如下src.depth()和ddepth的组合:
若src.depth()= CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F
若src.depth()= CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F
若src.depth()= CV_32F, 取ddepth =-1/CV_32F/CV_64F
若src.depth()= CV_64F, 取ddepth = -1/CV_64F
Ø 第四个参数,int类型dx,x 方向上的差分阶数。
Ø 第五个参数,int类型dy,y方向上的差分阶数。
Ø 第六个参数,int类型ksize,有默认值3,表示Sobel核的大小;必须取1,3,5或7。
Ø 第七个参数,double类型的scale,计算导数值时可选的缩放因子,默认值是1,表示默认情况下是没有应用缩放的。我们可以在文档中查阅getDerivKernels的相关介绍,来得到这个参数的更多信息。
Ø 第八个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
Ø 第九个参数, int类型的borderType,我们的老朋友了(万年是最后一个参数),边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate处得到更详细的信息。
一般情况下,都是用ksize xksize内核来计算导数的。然而,有一种特殊情况——当ksize为1时,往往会使用3 x 1或者1 x 3的内核。且这种情况下,并没有进行高斯平滑操作。
1.2调用示例
Mat
ScrImage = imread("E:\\1TJQ\\Opencv\\Images\\image1.jpg");
Sobel(ScrImgae, OutImage3, CV_16S, 1, 0,3);//Sobel边缘检测算法X方向
//计算绝对值,并将结果转换成8位
CV_16S, 0, 1, 3);//Sobel边缘检测算法Y方向
convertScaleAbs(OutImage3,OutImage5);
//将Sobel边缘检测算法X方向和Y方向加起来注意:要分别对X方向和Y方向进行操作,效果才好。不能一起操作
"Sobel边缘检测算法X",OutImage4);
"Sobel边缘检测算法Y",OutImage5);
imshow("Sobel边缘检测算法X+Y", OutImage6);
三、 Laplacian算子
2.1 Laplacian ()函数各参数详解
voidLaplacian(InputArray src,OutputArray dst,int ddepth,int ksize = 1,double scale =1,double delta = 0, intborderType =BORDER_DEFAULT)
Ø 第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像。
Ø 第二个参数,OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和通道数。
Ø 第三个参数,int类型的ddept,目标图像的深度。
Ø 第四个参数,int类型的ksize,用于计算二阶导数的滤波器的孔径尺寸,大小必须为正奇数,且有默认值1。
Ø 第五个参数,double类型的scale,计算拉普拉斯值的时候可选的比例因子,有默认值1。
Ø 第六个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
Ø 第七个参数, int类型的borderType,边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate()处得到更详细的信息。
Laplacian( )函数其实主要是利用sobel算子的运算。它通过加上sobel算子运算出的图像x方向和y方向上的导数,来得到我们载入图像的拉普拉斯变换结果。
1.2调用示例
Mat
ScrImage = imread("E:\\1TJQ\\Opencv\\Images\\image1.jpg");
Laplacian(ScrImgae, OutImage7, CV_16S, 3); //Lapacian边缘检测算法,基于Sobel边缘检测算法为基础
//计算绝对值,并将结果转换成8位
imshow("Laplacian边缘检测算法", OutImage7);
四、 Scharr滤波器
2.1 Scharr ()函数各参数详解
void Scharr(InputArray src,OutputArray dst,int ddepth,int dx,int dy, double scale = 1,double delta =0, intborderType =BORDER_DEFAULT)
Ø 第一个参数,InputArray 类型的src,为输入图像,填Mat类型即可。
Ø 第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
Ø 第三个参数,int类型的ddepth,输出图像的深度,支持如下src.depth()和ddepth的组合:
若src.depth() = CV_8U, 取ddepth=-1/CV_16S/CV_32F/CV_64F
若src.depth() = CV_16U/CV_16S, 取ddepth=-1/CV_32F/CV_64F
若src.depth() = CV_32F, 取ddepth=-1/CV_32F/CV_64F
若src.depth() = CV_64F, 取ddepth = -1/CV_64F
Ø 第四个参数,int类型dx,x方向上的差分阶数。
Ø 第五个参数,int类型dy,y方向上的差分阶数。
Ø 第六个参数,double类型的scale,计算导数值时可选的缩放因子,默认值是1,表示默认情况下是没有应用缩放的。我们可以在文档中查阅getDerivKernels的相关介绍,来得到这个参数的更多信息。
Ø 第七个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
Ø 第八个参数, int类型的borderType,我们的老朋友了(万年是最后一个参数),边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate处得到更详细的信息。
如下两者等价:
Scharr(src, dst, ddepth, dx, dy, scale, delta,borderType);
Sobel(src, dst, ddepth, dx, dy, CV_SCHARR, scale,delta, borderType);
1.2调用示例
Mat
ScrImage = imread("E:\\1TJQ\\Opencv\\Images\\image1.jpg");
Scharr(ScrImgae, OutImage1, CV_16S, 1, 0);//Scharr边缘检测算法X方向,跟Sobel功能一样
CV_16S, 0, 1);//Scharr边缘检测算法Y方向,跟Sobel功能一样
//将Sobel边缘检测算法X方向和Y方向加起来
//计算绝对值,并将结果转换成8位
"Scharr边缘检测算法X+Y", OutImage);
三、完整程序示例
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <vector>
#include <cstdio>
using namespacestd;
using namespacecv;
int
{
Mat
"E:\\1TJQ\\Opencv\\Images\\image1.jpg");//读入图像 \\image1.jpg brownbug.jpg
"【原图】", ScrImage);
//将源图像复制
//cvtColor(ScrImage, ScrImgaeCopy1, CV_RGB2GRAY); //将源图像转换为灰度图像
//imshow("【原图灰度图】", ScrImgaeCopy1);
//GaussianBlur(ScrImage, ScrImgaeCopy1, Size(3, 3),0, 0);//高斯滤波
//bilateralFilter(ScrImage, ScrImgaeCopy1, -1, 21,21);//双边滤波
/*blur(ScrImage, ScrImgaeCopy1, Size(3, 3)); //均值滤波
Canny(ScrImgaeCopy1,OutImage1, 150, 50, 3); //Canny边缘检测算法
Canny(ScrImage,OutImage2, 150, 50, 3); //Canny边缘检测算法
OutImage =OutImage1 - OutImage2;*/
//Sobel(ScrImage, OutImage3, CV_16S, 1, 1, 3); //Sobel边缘检测算法
//convertScaleAbs(OutImage3, OutImage7); //将像素值转换到uchar8类型
CV_16S, 1, 0, 3);//Sobel边缘检测算法X方向
convertScaleAbs(OutImage3,OutImage4);
CV_16S, 0, 1, 3);//Sobel边缘检测算法Y方向
convertScaleAbs(OutImage3,OutImage5);
//将Sobel边缘检测算法X方向和Y方向加起来注意:要分别对X方向和Y方向进行操作,效果才好。不能一起操作
CV_16S, 3); //Lapacian边缘检测算法,基于Sobel边缘检测算法为基础
//计算绝对值,并将结果转换成8位
CV_16S, 1, 0); //Scharr边缘检测算法X方向,跟Sobel功能一样
CV_16S, 0, 1); //Scharr边缘检测算法Y方向,跟Sobel功能一样
//将Sobel边缘检测算法X方向和Y方向加起来
//计算绝对值,并将结果转换成8位
/*imshow("Canny边缘检测算法+均值滤波", OutImage1);
imshow("Canny边缘检测算法-均值滤波", OutImage2);
imshow("不加均值滤波差异", OutImage);*/
"Sobel边缘检测算法X",OutImage4);
"Sobel边缘检测算法Y",OutImage5);
"Sobel边缘检测算法X+Y",OutImage6);
"Laplacian边缘检测算法", OutImage7);
"Scharr边缘检测算法X+Y", OutImage);
waitKey(0);
return NULL;
}