经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。 |
---|
Sobel算子是通过离散微分方法求取图像边缘的边缘检测算子,其求取边缘的思想原理与我们前文介绍的思想一致,除此之外Sobel算子还结合了高斯平滑滤波的思想,将边缘检测滤波器尺寸由ksize * 1改进为ksize * ksize,提高了对平缓区域边缘的响应,相比前文的算法边缘检测效果更加明显。使用Sobel边缘检测算子提取图像边缘的过程大致可以分为以下三个步骤:
OpenCV 4提供了对图像提取Sobel边缘的Sobel()函数,该函数的函数原型在代码清单5-24中给出。
代码清单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. )
该函数的使用方式与分离卷积函数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所示。
代码清单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边缘检测结果