前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【从零学习OpenCV 4】Sobel算子

【从零学习OpenCV 4】Sobel算子

作者头像
小白学视觉
发布2020-02-12 15:34:52
9530
发布2020-02-12 15:34:52
举报

经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。

Sobel算子是通过离散微分方法求取图像边缘的边缘检测算子,其求取边缘的思想原理与我们前文介绍的思想一致,除此之外Sobel算子还结合了高斯平滑滤波的思想,将边缘检测滤波器尺寸由ksize * 1改进为ksize * ksize,提高了对平缓区域边缘的响应,相比前文的算法边缘检测效果更加明显。使用Sobel边缘检测算子提取图像边缘的过程大致可以分为以下三个步骤:

  • Step1:提取X方向的边缘, X 方向一阶Sobel边缘检测算子如(5.16)所示。
  • Step2:提取Y方向的边缘, Y 方向一阶Sobel边缘检测算子如(5.17)所示。
  • Step3:综合两个方向的边缘信息得到整幅图像的边缘。由两个方向的边缘得到整体的边缘有两种计算方式:第一种是求取两张图像对应像素的像素值的绝对值之和;第二种是求取两张图像对应像素的像素值的平方和的二次方根。这两种计算方式在式(5.18)给出。

OpenCV 4提供了对图像提取Sobel边缘的Sobel()函数,该函数的函数原型在代码清单5-24中给出。

代码语言:javascript
复制
代码清单5-24 Sobel()函数原型
1.	void cv::Sobel(InputArray  src,
2.	                  OutputArray  dst,
3.	                  int  ddepth,
4.	                  int  dx,
5.	                  int  dy,
6.	                  int  ksize = 3,
7.	                  double  scale = 1,
8.	                  double  delta = 0,
9.	                  int  borderType = BORDER_DEFAULT
10.	                  )
  • src:待提取边缘的图像,
  • dst:输出图像,与输入图像src具有相同的尺寸和通道数,数据类型由第三个参数ddepth控制。
  • ddepth:输出图像的数据类型(深度),根据输入图像的数据类型不同拥有不同的取值范围,具体的取值范围在表5-1给出,当赋值为-1时,输出图像的数据类型自动选择。
  • dx:X方向的差分阶数
  • dy:Y方向的差分阶数
  • ksize:Sobel边缘算子的尺寸,必须是1、3、5或者7。
  • scale:对导数计算结果进行缩放的缩放因子,默认系数为1,不进行缩放。
  • delta:偏值,在计算结果中加上偏值。
  • borderType:像素外推法选择标志,取值范围在表3-5中给出,默认参数为BORDER_DEFAULT,表示不包含边界值倒序填充。

该函数的使用方式与分离卷积函数sepFilter2D()相似,函数的前两个参数分别为输入图像和输出图像,第三个参数为输出图像的数据类型,这里需要注意由于提取边缘信息时有可能会出现负数,因此不要使用CV_8U数据类型的输出图像,与Sobel算子方向不一致的边缘梯度会在CV_8U数据类型中消失,使得图像边缘提取不准确。函数中第三个、第四个和第五个参数是控制图像边缘检测效果的关键参数,这三者存在的关系是任意一个方向的差分阶数都需要小于滤波器的尺寸,特殊情况是当ksize=1时,任意一个方向的阶数需要小于3。一般情况中,差分阶数的最大值为1时,滤波器尺寸选3;差分阶数的最大值为2时,滤波器尺寸选5;差分阶数最大值为3时,滤波器尺寸选7。当滤波器尺寸ksize=1时,程序中使用的滤波器尺寸不再是正方形,而是3×1或者1×3。最后三个参数为图像放缩因子、偏移量和图像外推填充方法的标志,多数情况下并不需要设置,只需要采用默认参数即可。

为了更好的理解Sobel()函数的使用方法,在代码清单5-25中给出了利用Sobel()函数提取图像边缘的示例程序,程序中分别提取X方向和Y方向的1阶边缘,并利用两个方向的边缘求取整幅图像的边缘,程序运行结果如图5-30所示。

代码语言:javascript
复制
代码清单5-25 mySobel.cpp图像Sobel边缘提取
1.	#include <opencv2\opencv.hpp>
2.	#include <iostream>
3.	
4.	using namespace cv;
5.	using namespace std;
6.	
7.	int main()
8.	{
9.		//读取图像,黑白图像边缘检测结果较为明显
10.		Mat img = imread("equalLena.png", IMREAD_ANYCOLOR);
11.		if (img.empty())
12.		{
13.			cout << "请确认图像文件名称是否正确" << endl;
14.			return -1;
15.		}
16.		Mat resultX, resultY, resultXY;
17.	
18.		//X方向一阶边缘
19.		Sobel(img, resultX, CV_16S, 2, 0, 1);
20.		convertScaleAbs(resultX, resultX);
21.	
22.		//Y方向一阶边缘
23.		Sobel(img, resultY, CV_16S, 0, 1, 3);
24.		convertScaleAbs(resultY, resultY);
25.	
26.		//整幅图像的一阶边缘
27.		resultXY = resultX + resultY;
28.	
29.		//显示图像
30.		imshow("resultX", resultX);
31.		imshow("resultY", resultY);
32.		imshow("resultXY", resultXY);
33.		waitKey(0);
34.		return 0;
35.	}

图5-30 mySobel.cpp程序Sobel边缘检测结果

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-01-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小白学视觉 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档