【OpenCV 4开发详解】边缘检测原理
本文首发于“小白学视觉”微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究!
经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。 |
图像的边缘指的是图像中像素灰度值突然发生变化的区域,如果将图像的每一行像素和每一列像素都描述成一个关于灰度值的函数,那么图像的边缘对应在灰度值函数中是函数值突然变大的区域。函数值的变化趋势可以用函数的导数描述。当函数值突然变大时,导数也必然会变大,而函数值变化较为平缓区域,导数值也比较小,因此可以通过寻找导数值较大的区域去寻找函数中突然变化的区域,进而确定图像中的边缘位置。图5-27给出一张含有边缘的图像,图像每一行的像素灰度值变化可以用图中下方的曲线表示。
图5-27 图像每行像素灰度值变化趋势
通过像素灰度值曲线可以看出图像边缘位于曲线变化最陡峭的区域,对灰度值曲线求取一阶导数可以得到图5-28中所示的曲线,通过曲线可以看出曲线的最大值区域就是图像中的边缘。
图5-28 每一行灰度值函数的导数
由于图像是离散的信号,我们可以用临近的两个像素差值来表示像素灰度值函数的导数,求导形式可以用式(5.12)来表示。
df(x,y)dx=f(x,y)−f(x−1,y)(5.12)\frac{{df(x,y)}}{{dx}} = f(x,y) - f(x - 1,y) \tag{5.12}dxdf(x,y)=f(x,y)−f(x−1,y)(5.12)
这种对X轴方向求导方式对应于滤波器为[1−1]\begin{bmatrix}1&-1\end{bmatrix}[1−1] ,同样对Y轴方向求导对应的滤波器为[1−1]T\begin{bmatrix}1&-1\end{bmatrix}^T[1−1]T 。但是这种求导方式的计算结果最接近于两个像素中间位置的梯度,而两个临近的像素中间不再有任何的像素,因此如果想表示某个像素处的梯度,最接近的方式是求取前一个像素和后一个像素的差值,因此需要将式(5.12)修改为如所示。
df(x,y)dx=f(x+1,y)−f(x−1,y)2(5.13)\frac{{df(x,y)}}{{dx}} = \frac{{f(x + 1,y) - f(x - 1,y)}}{2}\tag{5.13}dxdf(x,y)=2f(x+1,y)−f(x−1,y)(5.13)
改进的求导方式对应的滤波器在X方向和Y方向分别为[0.50−0.5]\begin{bmatrix}0.5&0&-0.5\end{bmatrix}[0.50−0.5] 和[0.50−0.5]T\begin{bmatrix}0.5&0&-0.5\end{bmatrix}^T[0.50−0.5]T。根据这种方式也可以用式(5.14)所示的滤波器计算45°方向的梯度,寻找不同方向的边缘。
XY=∣100−1∣YX=∣01−10∣(5.14)\begin{matrix} {{\rm{XY = }}\left| {\begin{matrix} 1&0\\ 0&{ - 1} \end{matrix}} \right|}&{{\rm{YX}}} \end{matrix} = \left| {\begin{matrix} 0&1\\ { - 1}&0 \end{matrix}} \right| \tag{5.14}XY=∣∣∣∣100−1∣∣∣∣YX=∣∣∣∣0−110∣∣∣∣(5.14)
图像的边缘有可能是由高像素值变为低像素值,也有可能是由低像素值变成高像素值,通过式(5.13)和式(5.14)得到的正数值表示需要像素值突然由低变高,得到的负数值表示像素值由高到低,这两种都是图像的边缘,因此为了在图像中同时表示出这两种边缘信息,需要将计算的结果求取绝对值。OpenCV 4中提供了convertScaleAbs()函数用计算矩阵中所有数据的绝对值,该函数的函数原型在代码清单5-22中给出。
代码清单5-22 convertScaleAbs()函数函数原型
1. void cv::convertScaleAbs(InputArray src,
2. OutputArray dst,
3. double alpha = 1,
4. double beta = 0
5. )
- src:输入矩阵。
- dst:计算绝对值后输入矩阵。
- alpha:缩放因子,默认参数为只求取绝对值不进行缩放。
- beta:在原始数据上添加的偏值,默认参数表示不增加偏值。
该函数可以求取矩阵中所有数据的绝对值。函数前两个参数分别为输入、输出矩阵,两个参数可以是相同的变量。函数第三个和第四个参数为对绝对值的缩放和原始数据上的偏移。函数的计算原理如式(5.15)所示。
dst(I)=∣src(I)∗alpha+beta∣(5.15){\rm{dst}}(I) = \left| {{\rm{src(}}I{\rm{)*alpha + beta}}} \right| \tag{5.15}dst(I)=∣src(I)∗alpha+beta∣(5.15)
图像的边缘包含X方向的边缘和Y方向的边缘,因此分别求取两个方向的边缘后,对两个方向的边缘求取并集就是整幅图像的边缘,即将图像两个方向边缘结果相加得到整幅图像的边缘信息。为了验证这种滤波方式对于图像边缘提取的效果,在代码清单5-23中给出了利用filter2D()函数实现图像边缘检测的算法,检测的结果在图5-29中给出。需要说明的是,由于求取边缘的结果可能会有复数,不在原始图像的CV_8U的数据类型内,因此滤波后的图像数据类型不要用“-1”,而应该改为CV_16S。
代码清单5-23 myEdge.cpp图像边缘检测
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 kernel1 = (Mat_<float>(1, 2) << 1, -1); //X方向边缘检测滤波器
11. Mat kernel2 = (Mat_<float>(1, 3) << 1, 0, -1); //X方向边缘检测滤波器
12. Mat kernel3 = (Mat_<float>(3, 1) << 1, 0, -1); //X方向边缘检测滤波器
13. Mat kernelXY = (Mat_<float>(2, 2) << 1, 0, 0, -1); //由左上到右下方向边缘检测滤波器
14. Mat kernelYX = (Mat_<float>(2, 2) << 0, -1, 1, 0); //由右上到左下方向边缘检测滤波器
15.
16. //读取图像,黑白图像边缘检测结果较为明显
17. Mat img = imread("equalLena.png", IMREAD_ANYCOLOR);
18. if (img.empty())
19. {20. cout << "请确认图像文件名称是否正确" << endl;
21. return -1;
22. }
23. Mat result1, result2, result3, result4, result5, result6;
24.
25. //检测图像边缘
26. //以[1 -1]检测水平方向边缘
27. filter2D(img, result1, CV_16S, kernel1);
28. convertScaleAbs(result1, result1);
29.
30. //以[1 0 -1]检测水平方向边缘
31. filter2D(img, result2, CV_16S, kernel2);
32. convertScaleAbs(result2, result2);
33.
34. //以[1 0 -1]'检测由垂直方向边缘
35. filter2D(img, result3, CV_16S, kernel3);
36. convertScaleAbs(result3, result3);
37.
38. //整幅图像的边缘
39. result6 = result2 + result3;
40. //检测由左上到右下方向边缘
41. filter2D(img, result4, CV_16S, kernelXY);
42. convertScaleAbs(result4, result4);
43.
44. //检测由右上到左下方向边缘
45. filter2D(img, result5, CV_16S, kernelYX);
46. convertScaleAbs(result5, result5);
47.
48. //显示边缘检测结果
49. imshow("result1", result1);
50. imshow("result2", result2);
51. imshow("result3", result3);
52. imshow("result4", result4);
53. imshow("result5", result5);
54. imshow("result6", result6);
55. waitKey(0);
56. return 0;
57. }
图5-29 myEdge.cpp程序中边缘检测结果
OpenCV 4开发详解 |
往期推荐 |
---|
【OpenCV 4开发详解】保存和读取XML和YMAL文件 |
【OpenCV 4开发详解】颜色模型与转换 |
【OpenCV 4开发详解】多通道分离与合并 |
【OpenCV 4开发详解】图像像素统计 |
【OpenCV 4开发详解】两图像间的像素操作 |
【OpenCV 4开发详解】图像二值化 |
【OpenCV 4开发详解】图像LUT查找表 |
【OpenCV 4开发详解】图像连接 |
【OpenCV 4开发详解】图像仿射变换 |
【OpenCV 4开发详解】图像透视变换 |
【OpenCV 4开发详解】图像极坐标变换 |
【OpenCV 4开发详解】图像上绘制几何图形 |
【OpenCV 4开发详解】图像金字塔 |
【OpenCV 4开发详解】窗口交互操作 |
【OpenCV 4开发详解】图像直方图绘制 |
【OpenCV 4开发详解】直方图操作 |
【OpenCV 4开发详解】直方图应用 |
【OpenCV 4开发详解】图像模板匹配 |
【OpenCV 4开发详解】图像卷积 |
【OpenCV 4开发详解】图像噪声的种类与生成 |
【OpenCV 4开发详解】均值滤波 |
【OpenCV 4开发详解】方框滤波 |
【OpenCV 4开发详解】高斯滤波 |
【OpenCV 4开发详解】可分离滤波 |
【OpenCV 4开发详解】中值滤波 |
经过几个月的努力,市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》将春节后由人民邮电出版社发行。如果小伙伴觉得内容有帮助,希望到时候多多支持! |
关注小白的小伙伴可以提前看到书中的内容,我们创建了学习交流群,欢迎各位小伙伴添加小白微信加入交流群,添加小白时请备注“学习OpenCV 4”。 |
【OpenCV 4开发详解】边缘检测原理相关推荐
- 【OpenCV 4开发详解】分割图像——分水岭法
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】深度神经网络应用实例
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】图像修复
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】分割图像——Mean-Shift分割算法
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】分割图像——Grabcut图像分割
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】漫水填充法
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】点集拟合
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】轮廓外接多边形
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】轮廓面积与长度
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
最新文章
- 2022-2028年中国橡胶带行业市场运营格局及未来前景分析报告
- 文献阅读|Dynamic-SLAM
- linux笔记本上安装了双显卡驱动(intel+nvidia)
- Chrome反压缩JS代码:Pretty Print显示可读代码
- FlexChart: 针对AJAX的Flash绘图应用
- mysql 二进制转字符串_MySql字符转义 | 学步园
- postgreSql 常用操作总结
- python的return语句求两数之和_程序题(python解)
- ajax 同步加载数据
- 鸿蒙OS应用开发_基础篇_编写第一个HarmonyOs应用_体会HarmonyOs的一次开发多端部署_以及分布式任务调度_IDE安装_了解应用组件以及应用布局---HarmonyOs开发工作笔记001
- 计算机基础(六):内存申请方式
- https端口号_Wireshark使用以及https
- 《30天自制操作系统》03_day_学习笔记
- 关于Multi-bin实现的一些翻译
- 如何学习渗透测试:初学者教程
- 专题讲座3 数论+博弈论 学习心得
- Jodd-Java的瑞士军刀 demo
- android本地化,Android本地化
- linux作业控制 信号,bash中的作业控制机制
- ASIL-汽车安全完整性等级介绍