【OpenCV 4开发详解】分割图像——Mean-Shift分割算法
本文最初发布于 "小白学视觉" 微信公众号, 值得您的关注.
本文的作者是小白, 文章版权归人民邮电出版社拥有版权.
严禁转载此文章内容, 请确保未经授权不得复制或使用.
| 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。 |
|---|
Mean-Shift算法也被称作均值漂移法,在图像分割领域是一种依据颜色空间分布进行处理的方法。该算法生成的结果是一个经过调色后的"分色"图像,在视觉上呈现出渐变色调,并且图像中的纹理趋于平缓。
在Mean-Shift算法中使用5D向量(x,y,b,g,r)来表示每一个像元点,在其中x和y代表该像元在图像中的位置坐标,在此基上b、g和r分别代表该像元的颜色通道值(蓝绿红三色)。算法从峰值区域开始逐步移动滑动窗口以实现分类目标,在此过程中窗体大小由半径范围以及色彩阈值共同决定。窗体内的像元会被评估是否属于同一类别,并根据评估结果更新窗体内所有像元的一致色彩值。通过不断迭代窗体的位置与尺寸最终达到基于像元色彩特性的图像分割效果由于分割后的同类像元具有相同的色彩值因此输出结果呈现渐变色调平缓的空间分布特征
OpenCV 4版本包含用于分割图像的Mean-Shift算法的pyrMeanShiftFiltering()函数;其具体定义可在代码清单8-23中找到。
代码清单8-23 pyrMeanShiftFiltering()函数原型
1. void cv::pyrMeanShiftFiltering(InputArray src,
2. OutputArray dst,
3. double sp,
4. double sr,
5. int maxLevel = 1,
6. TermCriteria termcrit =
7. TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 5, 1)
8. )
- src: 源图应为三通道CU_8U彩色图像.
- dst: 目标图为与输入相同尺寸及数据类型的输出.
- sp: 滑动窗口半径.
- sr: 滑动窗口颜色宽度.
- maxLevel: 分割金字塔的最大缩放层.
- termcrit: 迭代算法终止条件.
该函数通过分析彩色图像各像素的空间分布来完成图像分割。处理后的输出图像其颜色分布更为均匀和平滑。经过该函数处理后得到的图像在纹理特征上更为简化,并且仅在边缘检测结果与当前阈值存在显著差异时会重新进行局部分类操作以提高区域边界清晰度。所有输入均需满足相同的尺寸要求,并且必须为CV_8U格式的三通道彩色平面图。其中第二个参数对应输入待分割图像的第一个通道平面图数据地址,默认值设为0表示直接在整个原始图中执行均值平移分割操作;第三个参数则用于定义滑动窗口的空间扩展速度;第四个参数指定滑动窗口的颜色变化幅度;第五个参数则决定了金字塔构建时所采用的最大层次深度;最后一个TermCriteria参数则决定了算法迭代终止条件并返回最终结果信息。
代码清单8-24 TermCriteria()函数原型
1. cv::TermCriteria::TermCriteria(int type,
2. int maxCount,
3. double epsilon
4. )
- 类型标志:表8-6列出了可供选择的终止条件类型及其含义。
- 最大值:指代算法的最大迭代次数或处理元素数量。
- 精度要求:表示算法在收敛时所设定的精度标准或参数变化范围。
此函数可表述迭代算法的终止条件;主要可分为满足迭代次数与满足计算精度两种情况。此函数的第一个参数即终止条件类型的标识符;其可选参数列于表8-6之中;这些标志间可相互组合运用;值得注意的是因该参数属于TermCriteria类成员因此,在引用时应在变量前添加前缀表明其所属类别。此函数的第二个参数代表最大迭代次数值;当epsilon等于TermCriteria::COUNT值时生效;而第三个相关参数则指示了程序应达成的具体运算精度要求;当epsilon等于TermCriteria::EPS值时此类运算才会启动执行。
表8-6 TermCriteria()函数中终止条件的类型标志可选参数及含义
| 标志参数 | 简记 | 含义 |
|---|---|---|
| TermCriteria::COUNT | 1 | 迭代次数达到设定值才停止迭代 |
| TermCriteria::MAX_ITER | 1 | 同上 |
| TermCriteria::EPS | 2 | 当计算的精度满足要求时停止迭代 |
为了深入解析pyrMeanShiftFiltering()函数的应用及其在图像分割中的表现,在代码清单8-25中提供了基于该函数实现图像分割的详细示例程序。该程序通过连续两次处理输入图像,并从最终的分割结果中提取Canny边缘特征。随后对比分析了原始与处理后图像之间的边缘变化情况:经多次迭代处理后所得图像边缘数量显著减少;同时所得图像分割区域边界更加整齐且平滑。具体实验结果如图8-15至图8-17所示
代码清单8-25 myPyrMeanShiftFiltering.cpp利用均值漂移法分割图像
1. #include <opencv2/opencv.hpp>
2. #include <iostream>
3.
4. using namespace cv;
5. using namespace std;
6.
7. int main()
8. {
9. Mat img = imread("coin.png");
10. if (!img.data)
11. {
12. cout << "请确认图像文件名称是否正确" << endl;
13. return -1;
14. }
15.
16. //分割处理
17. Mat result1, result2;
18. TermCriteria T10 = TermCriteria(TermCriteria::COUNT|TermCriteria::EPS, 10, 0.1);
19. pyrMeanShiftFiltering(img, result1, 20, 40, 2, T10); //第一次分割
20. pyrMeanShiftFiltering(result1, result2, 20, 40, 2, T10); //第一次分割的解雇再次分割
21.
22. //显示分割结果
23. imshow("img", img);
24. imshow("result1", result1);
25. imshow("result2", result2);
26.
27. //对图像提取Canny边缘
28. Mat imgCanny,result1Canny,result2Canny;
29. Canny(img, imgCanny, 150, 300);
30. Canny(result1, result1Canny, 150, 300);
31. Canny(result2, result2Canny, 150, 300);
32.
33. //显示边缘检测结果
34. imshow("imgCanny", imgCanny);
35. imshow("result1Canny", result1Canny);
36. imshow("result2Canny", result2Canny);
37. waitKey(0);
38. return 0;
39. }

图8-15 myPyrMeanShiftFiltering.cpp程序中原图及Canny边缘

图8-16 myPyrMeanShiftFiltering.cpp程序中处理一次图像及Canny边缘

图8-17 myPyrMeanShiftFiltering.cpp程序中处理两次图像及Canny边缘
| OpenCV 4开发详解 |
|---|
| 经过几个月的努力,市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》将春节后由人民邮电出版社发行。如果小伙伴觉得内容有帮助,希望到时候多多支持! |
|---|
| 关注小白的小伙伴可以提前看到书中的内容,我们创建了学习交流群,欢迎各位小伙伴添加小白微信加入交流群,添加小白时请备注“学习OpenCV 4”。 |
|---|


