Opencv mat资料下载—提取码:x3t1
Canny算子–Canny函数
消除噪声:使用高斯平滑滤波器卷积降噪。
计算梯度幅值和方向:此处按照sobel滤波器的步骤来操作:(1)运用一对卷积阵列(分别作用于x和y方向),(2)计算梯度幅值和方向,梯度方向一般取0度、45度、90度、135度这4个可能的角度之一。
非极大值抑制:这一步排除非边缘像素,仅仅保留了一些细线条(候选边缘)
滞后阈值:滞后阈值需要两个阈值(高阈值和低阈值)
(1)若某一像素位置的幅值超过高阈值,该像素被保留为边缘像素。
(2)若某一像素位置的幅值小于低阈值,该像素被排除。
(3)若某一像素位置的幅值在两个阈值之间,该像素仅仅在连接到一个高于高阈值的像素时被保留。
void Canny(inputArray,outputArray,double threshold1,double threshold2,int apertureSize=3,bool L2gradient=false)
*第一个参数,输入图像,且需为单通道8位图像。
*第二个参数,输出的边缘图。
*第三个参数,第一个滞后性阈值。用于边缘连接。
*第四个参数,第二个滞后性阈值。用于控制强边缘的初始段,高低阈值比在2:1到3:1之间。
*第五个参数,表明应用sobel算子的孔径大小,默认值为3。
*第六个参数,bool类型L2gradient,一个计算图像梯度幅值的标识,默认值false。
Sobel算子–Sobel函数
void Sobel(inputArray,outputArray,int ddepth,int dx,int dy,int ksize=3,double scale=1,double delta=0,int borderType=BORDER_DEFAULT)
*第一个参数,输入图像。
*第二个参数,输出图像。
*第三个参数,输出图像深度。
*第四个参数,x方向上的差分阶数。
*第五个参数,y方向上的差分阶数。
*第六个参数,Sobel核的大小,默认值为3,必须为1、3、5、7。当为1时,往往使用3x1、1x3的内核,这种情况下,没有进行高斯平滑操作。
*第七个参数,计算导数值时可选的缩放因子,默认值1,表示默认情况下没用应用缩放。
*第八个参数,表示在结果存入输出图像之前可选的delta值,默认值0。
*第九个参数,边界模式。
补充说明:
(1)当内核大小为3时,Sobel内核可能产生比较明显的误差,为了解决这一问题,Opencv提供了Scharr函数,但该函数仅作用于大小为3的内核,该函数的运算与Sobel函数一样快,但结果却更加精确。
(2)因为Sobel算子结合了高斯平滑和分化,因此结果会具有更多的抗噪性。
Laplacian算子–Laplacian函数
Laplacian算子是n维欧几里德空间中的一个二阶微分算子,定义为梯度grad的散度div。由于Laplacian使用了图像梯度,它内部的代码其实是调用了Sobel算子的。让一幅图像减去它的Laplacian算子可以增强对比度!!!
void Laplacian(inputArray,outputArray,int ddepth,int ksize=1,double scale=1,double delta=0,int borderType=BORDER_DEFAULT)
*第一个参数,输入图像,且需为单通道8位图像。
*第二个参数,输出的边缘图。
*第三个参数,输出图像的图像深度。
*第四个参数,用于计算二阶导数的滤波器的孔径尺寸大小,大小必须为正奇数,默认值为1。
*第五个参数,计算拉普拉斯值的时候可选的比例因子,默认值为1。
*第六个参数,表示在结果存入目标图之前可选的delta值,默认值为0。
*第七个参数,边界模式。
Scharr滤波器–Scharr函数
在Opencv中主要是配合Sobel算子的运算而存在的。使用Scharr滤波器运算符计算x或y方向的图像差分。其实它的参数变量和Sobel基本上是一样的,除了没有ksize核的大小。
void Scharr(inputArray,outputArray,int ddepth,int dx,int dy,double scale=1,double delta=0,int borderType=BORDER_DEFAULT)
*第一个参数,输入图像。
*第二个参数,输出图像。
*第三个参数,输出图像深度。
*第四个参数,x方向上的差分阶数。
*第五个参数,y方向上的差分阶数。
*第六个参数,计算导数值时可选的缩放因子,默认值1,表示默认情况下没用应用缩放。
*第七个参数,表示在结果存入输出图像之前可选的delta值,默认值0。
*第八个参数,边界模式。
#include
#include
using namespace cv;
using namespace std;
//全局变量声明
Mat g_srcImage,g_dstImage,g_grayImage,g_grayImage1,g_grayImage2,g_tmpImage,g_tempImage,g_tmpImage1,g_tempImage1;
int g_nModeValue=1;//0为原图像,1为canny,2为sobel,3位Scharr,4为Laplacian,5为Laplacian增强对比度
int g_nCannyLowThreshold=1;//canny边缘检测低阈值
int g_nSobelKernelSize=1;//sobel算子内核大小
//全局函数声明
void on_ModeType(int ,void *);
void on_CannyType(int ,void *);
void on_SobelType(int ,void *);
void Process();
//主函数
int main()
{
system(“COLOR 2F”);//改变字体颜色
//载入源图像
g_srcImage=imread("/Users/new/Desktop/1.jpg");
if(!g_srcImage.data){printf(“读取源图像srcImage错误~!\n”);return false;}
//创建显示窗口
namedWindow("[Edge Detector]");
g_dstImage.create(g_srcImage.size(),g_srcImage.type());
//创建模式转换、canny参数,sobel参数滚动条
createTrackbar("Mode Switch: ", “[Edge Detector]”, &g_nModeValue,5, on_ModeType);
createTrackbar("Canny Parameters: ", “[Edge Detector]”,&g_nCannyLowThreshold ,120,on_CannyType);
createTrackbar(“Sobel/Laplacian Parameters”, “[Edge Detector]”, &g_nSobelKernelSize,3, on_SobelType);
//初始化回调函数
on_ModeType(0,0);
//轮询获取按键信息,按下ESC退出
while(1)
{
int key;
key=waitKey(9);
if((char)key == 27)
break;
}
return 0;
}
//定义回调函数
void Process()
{
switch(g_nModeValue)
{
case 0://源图像
g_srcImage.copyTo(g_dstImage);
break;
case 1://canny边缘检测算法
cvtColor(g_srcImage, g_grayImage, COLOR_RGB2GRAY);
blur(g_grayImage, g_tmpImage, Size(3,3));//先用均值滤波器进行平滑去噪
Canny(g_tmpImage, g_tmpImage, g_nCannyLowThreshold, g_nCannyLowThreshold3);
g_dstImage=Scalar::all(0);
g_srcImage.copyTo(g_dstImage, g_tmpImage);//将g_tmpImage作为掩码,来将原图像拷贝到输出图像中
break;
case 2://sobel边缘检测算法
Sobel(g_srcImage, g_tmpImage, CV_16S, 1, 0,(2g_nSobelKernelSize+1),1,1,BORDER_DEFAULT);//求x方向梯度
convertScaleAbs(g_tmpImage, g_tmpImage1);//计算绝对值,并将结果转换成8位
Sobel(g_srcImage, g_tempImage, CV_16S, 0, 1,(2g_nSobelKernelSize+1),1,1,BORDER_DEFAULT);//求y方向梯度
convertScaleAbs(g_tempImage, g_tempImage1);//计算绝对值,并将结果转换成8位
addWeighted(g_tmpImage1, 0.5, g_tempImage1, 0.5, 0, g_dstImage);
break;
case 3://Scharr函数
Scharr(g_srcImage, g_tmpImage, CV_16S, 1, 0,1,0,BORDER_DEFAULT);//求x方向梯度
convertScaleAbs(g_tmpImage, g_tmpImage1);//计算绝对值,并将结果转换成8位
Sobel(g_srcImage, g_tempImage, CV_16S, 0, 1,1,0,BORDER_DEFAULT);//求y方向梯度
convertScaleAbs(g_tempImage, g_tempImage1);//计算绝对值,并将结果转换成8位
addWeighted(g_tmpImage1, 0.5, g_tempImage1, 0.5, 0, g_dstImage);
break;
case 4://Laplacian边缘检测算法
GaussianBlur(g_srcImage, g_srcImage, Size(3,3), 0,0,BORDER_DEFAULT);//高斯滤波消除噪声
cvtColor(g_srcImage, g_grayImage1, COLOR_RGB2GRAY);
Laplacian(g_grayImage1, g_tmpImage, CV_16S,(g_nSobelKernelSize2+1),1,0,BORDER_DEFAULT);
convertScaleAbs(g_tmpImage, g_dstImage);
break;
case 5://利用原图像减去拉普拉斯图像增强对比度
GaussianBlur(g_srcImage, g_srcImage, Size(3,3), 0,0,BORDER_DEFAULT);//高斯滤波消除噪声
cvtColor(g_srcImage, g_grayImage2, COLOR_RGB2GRAY);
Laplacian(g_grayImage2, g_tmpImage, CV_16S,(g_nSobelKernelSize*2+1),1,0,BORDER_DEFAULT);
convertScaleAbs(g_tmpImage, g_tmpImage1);
g_dstImage=g_grayImage2-g_tmpImage1;
break;
}
imshow("[Edge Detector]",g_dstImage);
}
void on_ModeType(int ,void *)
{
Process();
}
void on_CannyType(int ,void *)
{
Process();
}
void on_SobelType(int ,void *)
{
Process();
}
原始图片:
Canny边缘检测:
Sobel边缘检测:
Scharr边缘检测:
Laplacian边缘检测:
Laplacian提升对比度效果图(原图像减去拉普拉斯图像):