经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。 |
---|
虽然Sobel算子可以有效的提取图像边缘,但是对图像中较弱的边缘提取效果较差。因此为了能够有效的提取出较弱的边缘,需要将像素值间的差距增大,因此引入Scharr算子。Scharr算子是对Sobel算子差异性的增强,因此两者之间的在检测图像边缘的原理和使用方式上相同。Scharr算子的边缘检测滤波的尺寸为3×3,因此也有称其为Scharr滤波器。可以通过将滤波器中的权重系数放大来增大像素值间的差异,Scharr算子就是采用的这种思想,其在X方向和Y方向的边缘检测算子如(5.19)中所示。
OpenCV 4提供了对图像提取Scharr边缘的Scahrr ()函数,该函数的函数原型在代码清单5-26中给出。
代码5-26 Scharr()函数原型1. void cv::Scharr(InputArray src,2. OutputArray dst,3. int ddepth,4. int dx,5. int dy,6. double scale = 1,7. double delta = 0,8. int borderType = BORDER_DEFAULT
9. )
该函数利用Scharr算子提取图像中的边缘信息,与Soble()函数相同,函数的前两个参数分别为输入图像和输出图像,第三个参数为输出图像的数据类型,这里需要注意由于提取边缘信息时有可能会出现负数,因此不要使用CV_8U数据类型的输出图像,与Scarr算子方向不一致的边缘梯度会在CV_8U数据类型中消失,使得图像边缘提取不准确。函数第四个和五个参数是提取X方向边缘还是Y方向边缘的标志,该函数要求这两个参数只能有一个参数为1,并且不能同时为0,否则函数将无法提取图像边缘,该函数默认的滤波器尺寸为3×3,并且无法修改。最后三个参数为图像放缩因子、偏移量和图像外推填充方法的标志,多数情况下并不需要设置,只需要采用默认参数即可。
为了更好的理解Scahrr ()函数的使用方法,在代码清单5-27中给出了利用Scharr ()函数提取图像边缘的示例程序,程序中分别提取X方向和Y方向的边缘,并利用两个方向的边缘求取整幅图像的边缘,程序运行结果如图5-31所示,通过结果可以看出Scharr算子可以比Sobel算子提取到更微弱的边缘。
代码清单5-27 myScharr.cpp图像Scharr边缘提取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_ANYDEPTH);11. if (img.empty())12. {13. cout << "请确认图像文件名称是否正确" << endl;14. return -1;15. }16. Mat resultX, resultY, resultXY;17. 18. //X方向一阶边缘19. Scharr(img, resultX, CV_16S, 1, 0);20. convertScaleAbs(resultX, resultX);21. 22. //Y方向一阶边缘23. Scharr(img, resultY, CV_16S, 0, 1);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-31 myScharr.cpp程序Scharr边缘检测结果