当前位置: 首页 > news >正文

9.10Mean-Shift分割算法

基本概念

Mean-Shift 分割算法是一种非参数的特征空间点集的迭代查找算法,主要用于估计概率密度函数的模式。在计算机视觉中,它常用于颜色图像分割和目标跟踪。它通过迭代地移动每个数据点到其邻域内密度最大的地方,从而找到数据点的模式(即聚类中心)。OpenCV 提供了 pyrMeanShiftFiltering 函数来实现 Mean-Shift 分割算法。

在OpenCV中,Mean Shift算法通常用于目标跟踪,但它也可以用来进行图像分割。下面将详细解释如何使用C++在OpenCV中实现Mean Shift分割算法。
要使用OpenCV实现Mean Shift分割,可以按照以下步骤操作:

1.读取图像:
使用cv::imread()函数来读取图像。
2.创建ROI(Region of Interest):
用户需要手动选择一个感兴趣区域(ROI),这个区域通常是想要分割的目标所在的矩形框。
3.计算直方图:
对选定的ROI创建一个颜色直方图,这通常是通过将图像转换到HSV颜色空间并计算H(色调)通道上的直方图完成的。这是因为HSV颜色空间更接近人类对颜色的感知方式。
4.创建掩模:
创建一个掩模以标记感兴趣的区域,该掩模将在后续步骤中用于掩蔽图像。
5.创建追踪框:
基于用户选择的ROI,创建一个追踪框。
6.Mean Shift迭代:
使用cv::camshift()函数执行Mean Shift迭代。这个函数会返回一个新的追踪框位置以及旋转角度。
7.绘制结果:
在原图像上绘制追踪框,并显示结果。

1. Mean-Shift 分割算法原理

Mean-Shift 算法的核心思想是通过不断更新每个像素的颜色值,使其逐渐向邻域内的颜色均值靠拢,直到收敛。具体步骤如下:

1. 初始化:选择一个初始窗口(通常是整个图像)。

2. 计算均值:在当前窗口内计算所有像素的颜色均值。

3. 移动窗口:将窗口中心移动到计算出的颜色均值位置。

4. 重复:重复步骤 2 和 3,直到窗口中心不再移动或变化小于某个阈值。

5. 分割:将收敛后的颜色值作为该区域的代表颜色,从而实现图像分割。

2. OpenCV 中的 Mean-Shift 分割算法

OpenCV 提供了 pyrMeanShiftFiltering 函数来实现 Mean-Shift 分割算法。以下是详细的示例代码和解释。

函数原型

void pyrMeanShiftFiltering(InputArray src, OutputArray dst, double sp, double sr, int maxLevel=1, TermCriteria termcrit=TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 5, 1));•src:输入的 8 位三通道图像。
•dst:输出的图像,与输入图像具有相同的尺寸和类型。
•sp:空间窗口半径(以像素为单位),控制空间平滑程度。
•sr:色彩窗口半径(以像素为单位),控制色彩平滑程度。
•maxLevel:最大金字塔层数,通常设置为 1。
•termcrit:终止条件,包括最大迭代次数和最小变化量。

示例代码1

以下是一个完整的示例代码,展示了如何使用 OpenCV 在 C++ 中实现 Mean-Shift 分割算法:

#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int main() 
{// 读取图像Mat src = imread("B.png");if (src.empty()) {cout << "Error: Image not found or unable to read the image." << endl;return -1;}// 设置 Mean-Shift 参数double spatialRadius = 20;  // 空间窗口半径double colorRadius = 20;    // 色彩窗口半径int maxLevel = 1;           // 最大金字塔层数TermCriteria termcrit(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1);  // 终止条件// 创建输出图像Mat dst;// 进行 Mean-Shift 分割pyrMeanShiftFiltering(src, dst, spatialRadius, colorRadius, maxLevel, termcrit);// 显示结果namedWindow("Original Image", WINDOW_NORMAL);imshow("Original Image", src);namedWindow("Mean-Shift Segmentation", WINDOW_NORMAL);imshow("Mean-Shift Segmentation", dst);waitKey(0);return 0;
}详细解释
1. 读取图像:
•使用 imread 函数读取彩色图像。
2. 设置 Mean-Shift 参数:
•spatialRadius:空间窗口半径,控制空间平滑程度。较大的值会导致更多的平滑。
•colorRadius:色彩窗口半径,控制色彩平滑程度。较大的值会导致更多的颜色平滑。
•maxLevel:最大金字塔层数,通常设置为 1。
•termcrit:终止条件,包括最大迭代次数和最小变化量。这里设置为最多 5 次迭代,且变化量小于 1 时停止。
3. 创建输出图像:
•创建一个与输入图像相同尺寸和类型的输出图像 dst。
4. 进行 Mean-Shift 分割:
•使用 pyrMeanShiftFiltering 函数进行 Mean-Shift 分割,结果存储在 dst 中。
5. 显示结果:
•使用 imshow 函数分别显示原始图像和分割后的图像。
•使用 waitKey(0) 等待用户按键关闭窗口。注意事项
•参数调整:spatialRadius 和 colorRadius 是关键参数,根据实际需求进行调整。较大的值会导致更多的平滑,较小的值则保留更多细节。
•性能优化:如果需要处理大量图像,可以考虑优化代码,例如使用多线程处理。
•预处理:在某些情况下,对图像进行预处理(如高斯模糊)可以提高分割效果。

运行结果1

示例代码2(有待完善)

下面是一个简单的示例代码:
#include <opencv2/opencv.hpp>
#include <iostream>int main(int argc, char** argv)
{// Load an imagecv::Mat image = cv::imread("path_to_image.jpg", cv::IMREAD_COLOR);if (!image.data) {std::cout << "Could not open or find the image" << std::endl;return -1;}// Select ROIcv::Rect trackWindow;int x, y, w, h;std::cout << "Select the tracking window and press space to continue." << std::endl;cv::selectROI("Image", image, trackWindow);x = trackWindow.x; y = trackWindow.y; w = trackWindow.width; h = trackWindow.height;// Create HSV histogram for the selected ROIcv::Mat hsv_image;cv::cvtColor(image, hsv_image, cv::COLOR_BGR2HSV);cv::Mat roi_hist;cv::calcHist(std::vector<cv::Mat>{hsv_image}, // Input images{0},                              // Channels (Hue in this case)cv::Mat(),                        // No maskroi_hist,                         // Output histogram{256},                            // Bins{0, 256});                        // Range// Normalize the histogramcv::normalize(roi_hist, roi_hist, 0, 255, cv::NORM_MINMAX);// Create termination criteriacv::TermCriteria term_crit(cv::TermCriteria::COUNT | cv::TermCriteria::EPS, 10, 1);// Perform camshiftcv::Rect new_window;cv::Point2f pt;while(true) {cv::Mat hsv_back_projected;cv::calcBackProject(std::vector<cv::Mat>{hsv_image}, // Input images{0},                              // Channelsroi_hist,                         // Histogramhsv_back_projected,               // Output back projection{256},                            // Range255);                             // Scale// Perform camshift on the back projected imagenew_window = cv::camShift(hsv_back_projected, trackWindow, term_crit).box;// Draw it on imagecv::rectangle(image, new_window.tl(), new_window.br(), cv::Scalar(0,0,255), 2, 8, 0);cv::imshow("Image", image);// Exit if ESC pressedint c = cv::waitKey(10);if (c == 27) break;}return 0;
}

运行结果2


http://www.mrgr.cn/news/45228.html

相关文章:

  • 脑机接口技术的未来与现状:Neuralink、机械手臂与视觉假体的突破
  • Java中Cglib动态代理介绍、应用场景和示例代码
  • 思科防火墙:ASA中Object-group在ACL中的应用
  • 安装VS2022, 安装ipp, VS2022配置ipp
  • 【星汇极客】STM32 HAL库各种模块开发之DHT11模块
  • LeetCode题练习与总结:窥视迭代器--284
  • Docker:容器化技术的革命力量
  • 【Docker从入门到进阶】01.介绍 02.基础使用
  • 大数据毕业设计选题推荐-白酒销售数据分析-Python数据可视化-Hive-Hadoop-Spark
  • <<迷雾>> 第10章 用机器做一连串的加法(1)--使用两排开关分别给出被加数和加数 示例电路
  • C++重载(Overloading)、重写(Overriding)、重定义(Hiding)的对比与区别
  • 14_Linux中参数和变量查看方法
  • 【汇编语言】寄存器(CPU工作原理)(四)—— “段地址x16 + 偏移地址 = 物理地址”的本质含义以及段的概念和小结
  • Android Studio Ladybug | 2024.2.1 更新,快来看看吧
  • 【Linux报错】“-bash: cd: too many arguments“
  • 每日新闻掌握【2024年9月25日 星期三】
  • 数据结构--堆的深度解析
  • 8-传感器和数据
  • 按图搜索1688商品(拍立淘) :API接口编程
  • 【qt】QQ仿真项目2