『OpenCV3』滤波器边缘检测

一、原理简介

边缘检测原理 - Sobel, Laplace, Canny算子

X方向Sobel算子

-1-2-1
000
121

Y方向Sobel算子

-101
-202
-101

Laplace算子

111
1-81
111

Canny 边缘检测算子

高斯滤波器平滑图像

一阶差分偏导计算梯度值和方向

对梯度值不是极大值的地方进行抑制

用双阈值连接图上的联通点

通俗说一下,
1.用高斯滤波主要是去掉图像上的噪声。
2.计算一阶差分,OpenCV 源码中也是用 sobel 算子来算的。
3.算出来的梯度值,把不是极值的点,全部置0,去掉了大部分弱的边缘。所以图像边缘会变细。
4.双阈值 t1, t2, 是这样的,t1 <= t2
大于 t2 的点肯定是边缘
小于 t1 的点肯定不是边缘
在 t1, t2 之间的点,通过已确定的边缘点,发起8领域方向的搜索(广搜),图中可达的是边缘,不可达的点不是边缘。
最后得出 canny 边缘图。

二、代码演示

有关函数 convertScaleAbs,文档解释如下,不过这里不使用其放缩功能

1、Sobel 边缘检测算子

由于需要指定横向纵向,所以分两步进行,最后组合即可,

	cv::Mat image = cv::imread("test.jpg");
	cv::imshow("原图", image);
	cv::Mat gray;
	cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);

	cv::Mat contours;	
        cv::Mat sobelX, sobelY;
	cv::Sobel(
		image,
		sobelX,
		CV_16S,  // 图像depth,输入8U,输出16S防止外溢
		1, 0,   // xorder, yorder
		3,		// 内核尺寸
		1, 1	// 输出结果乘alpha加beta
	);
	cv::convertScaleAbs(sobelX, sobelX);
	cv::imshow("Sobel_X", sobelX);
	cv::Sobel(
		image,
		sobelY,
		CV_8U,
		0, 1,
		3,
		1, 1
	);
	cv::convertScaleAbs(sobelY, sobelY);
	cv::imshow("Sobel_Y", sobelY);
	cv::addWeighted(sobelX, 0.5, sobelY, 0.5, 0, contours);
	cv::imshow("Sobel", contours);    

 XY单方向输出如下,

两这合并如下,

2、Laplace 边缘检测算子

	// cv::Mat image = cv::imread("skin.jfif");
	cv::Mat image = cv::imread("test.jpg");
	cv::imshow("原图", image);
	cv::Mat gray;
	cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);

	cv::Mat contours;
        cv::GaussianBlur(gray, gray, cv::Size(5, 5), 1.5);
	cv::Laplacian(
		gray,
		contours,
		CV_16S,
		3,  // 内核尺寸
		1, 0 // 放缩因子
	);
	
	cv::convertScaleAbs(contours, contours);
	cv::imshow("Laplacian", contours);

3、Canny 边缘检测算子

	// cv::Mat image = cv::imread("skin.jfif");
	cv::Mat image = cv::imread("test.jpg");
	cv::imshow("原图", image);
	cv::Mat gray;
	cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);

	cv::Mat contours;
	cv::GaussianBlur(gray, gray, cv::Size(5, 5), 1.5);
	cv::Canny(
		gray,
		contours,
		10,  // 低阈值
		150   // 高阈值
	);
	cv::imshow("Canny", contours);

高低阈值参数的设定对于检测效果影响很大,一般来说低阈值检测出十分琐碎的边缘,且设置的越低检测出来的越多,而高阈值这决定了保留多少边缘,对于上图,我们将高阈值下调至50查看一下效果,会发现保留细节数目增加了

附录、函数总览

void edge() {
	// cv::Mat image = cv::imread("skin.jfif");
	cv::Mat image = cv::imread("test.jpg");
	cv::imshow("原图", image);
	cv::Mat gray;
	cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);

	cv::Mat contours;
	cv::GaussianBlur(gray, gray, cv::Size(5, 5), 1.5);
	cv::Canny(
		gray,
		contours,
		10,  // 低阈值
		150   // 高阈值
	);
	cv::imshow("Canny", contours);

	cv::Laplacian(
		gray,
		contours,
		CV_16S,
		3,  // 内核尺寸
		1
	);
	cv::Mat abs_dst;
	cv::convertScaleAbs(contours, contours);
	cv::imshow("Laplacian", contours);

	cv::Mat sobelX, sobelY;
	cv::Sobel(
		image,
		sobelX,
		CV_16S,  // 图像depth,输入8U,输出16S防止外溢
		1, 0,   // xorder, yorder
		3,		// 内核尺寸
		1, 1	// 输出结果乘alpha加beta
	);
	cv::convertScaleAbs(sobelX, sobelX);
	cv::imshow("Sobel_X", sobelX);
	cv::Sobel(
		image,
		sobelY,
		CV_8U,
		0, 1,
		3,
		1, 1
	);
	cv::convertScaleAbs(sobelY, sobelY);
	cv::imshow("Sobel_Y", sobelY);
	cv::addWeighted(sobelX, 0.5, sobelY, 0.5, 0, contours);
	cv::imshow("Sobel", contours);
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值