9.10Mean-Shift分割算法

news2024/10/8 11:21:27

基本概念

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 image
    cv::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 ROI
    cv::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 ROI
    cv::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 mask
                 roi_hist,                         // Output histogram
                 {256},                            // Bins
                 {0, 256});                        // Range

    // Normalize the histogram
    cv::normalize(roi_hist, roi_hist, 0, 255, cv::NORM_MINMAX);

    // Create termination criteria
    cv::TermCriteria term_crit(cv::TermCriteria::COUNT | cv::TermCriteria::EPS, 10, 1);

    // Perform camshift
    cv::Rect new_window;
    cv::Point2f pt;
    while(true) {
        cv::Mat hsv_back_projected;
        cv::calcBackProject(std::vector<cv::Mat>{hsv_image}, // Input images
                            {0},                              // Channels
                            roi_hist,                         // Histogram
                            hsv_back_projected,               // Output back projection
                            {256},                            // Range
                            255);                             // Scale

        // Perform camshift on the back projected image
        new_window = cv::camShift(hsv_back_projected, trackWindow, term_crit).box;

        // Draw it on image
        cv::rectangle(image, new_window.tl(), new_window.br(), cv::Scalar(0,0,255), 2, 8, 0);
        cv::imshow("Image", image);

        // Exit if ESC pressed
        int c = cv::waitKey(10);
        if (c == 27) break;
    }

    return 0;
}

运行结果2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2196222.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于单片机的非接触智能测温系统设计

本设计主要由单片机STC8A8K64S4A12、OLED显示屏、非接触式测温模块MLX9061、无线通讯模块ESP8266以及声光报警模块等构成。系统通过非接触式测温模块MLX9061测量当前人员温度&#xff0c;温度通过OLED显示屏进行实时显示&#xff0c;当被测温度高于阈值&#xff0c;声光报警模块…

力扣16~20题

题16&#xff08;中等&#xff09;&#xff1a; 思路&#xff1a; 双指针法&#xff0c;和15题差不多&#xff0c;就是要排除了&#xff0c;如果total<target则排除了更小的&#xff08;left右移&#xff09;&#xff0c;如果total>target则排除了更大的&#xff08;rig…

java语言基础案例-cnblog

java语言基础案例 象棋口诀 输出 package nb;public class XiangQi {public static void main(String[] args) {char a 马;char b 象;char c 卒;System.out.println(a"走日"b"走田""小"c"一去不复还");} }输出汇款单 package nb…

在java中使用redis

Redis Java使⽤ 引入依赖 Java 操作redis的客⼾端有很多.其中最知名的是jedis. 创建maven项⽬,把jedis的依赖拷⻉到pom.xml中 <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency><groupId>redis.clients</groupId><…

机房空调远程控制-Thingsboard MQTT 接口说明

一、 概述 为实现节能环保需求&#xff0c;拓扑未来公司推出轻量级&#xff0c;使用简单的远程空调控制解决方案。该方案集成了现场环境温湿度采集功能&#xff0c;设备管理功能&#xff0c;远程控制功能。支持本地自动控制模式和远程控制模式&#xff0c;自动模式下&#xff…

Chromium 如何查找已经定义好的mojom函数实现c++

进程通信定义通常都是用.mojom文件或者idl文件格式 以content\common\frame.mojom里面的BeginNavigation函数为例。 一、如何查找BeginNavigation函数定义&#xff0c;在vscode里面直接搜索BeginNavigation&#xff0c;过滤条件 *.idl,*.mojom,*.cc 效果&#xff1a; 这样…

YoloV9改进策略:BackBone改进|CAFormer在YoloV9中的创新应用,显著提升目标检测性能

摘要 在目标检测领域,模型性能的提升一直是研究者和开发者们关注的重点。近期,我们尝试将CAFormer模块引入YoloV9模型中,以替换其原有的主干网络,这一创新性的改进带来了显著的性能提升。 CAFormer,作为MetaFormer框架下的一个变体,结合了深度可分离卷积和普通自注意力…

Python网络爬虫从入门到实战

目录 引言 一、网络爬虫的概念 二、 网络爬虫的基本工作流程 &#xff08;一&#xff09;过程&#xff1a; &#xff08;二&#xff09;安装requests模块和beautifulsoup4模块 &#xff08;三&#xff09;requests库的使用 1、requests库的基本介绍 2、导入requests库的…

新手教学系列——curl_cffi异步Session使用注意事项

在现代编程中,网络请求是应用程序交互的重要组成部分,尤其在爬虫和数据采集领域,异步请求的能力显得尤为关键。curl_cffi作为一个强大的库,使得Python开发者可以使用C语言的curl库高效地进行异步HTTP请求。本文将带您深入探索curl_cffi异步Session的使用注意事项,帮助您避…

详解正确创建好SpringBoot项目后但是找不到Maven的问题

目录 问题 解决步骤&#xff1a; 找到File->Project Structure... 设置SDK 设置SDKs 问题 刚刚在使用IDEA专业版创建好SpringBoot项目后&#xff0c;发现上方导航栏的运行按钮是灰色的&#xff0c;而且左侧导航栏的pom.xml的图标颜色也不是正常的&#xff0c;与此同时我…

设计模式01-类图及设计原理(Java)

一、设计模式综述 1.设计模式基本概念 设计模式&#xff08;Design Pattern&#xff09;是前辈们对代码开发经验的总结&#xff0c;是解决特定问题的一系列套路。它不是语法规定&#xff0c;而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。 …

电商价格监测:开启品牌渠道管控新时代

在当今数字化高速发展的时代&#xff0c;电商领域如同一艘艘巨轮在浩瀚的网络海洋中破浪前行。然而&#xff0c;对于众多品牌而言&#xff0c;电商数据的庞大体量却犹如一片迷雾之海&#xff0c;要在其中准确找到自己需监测的 SKU&#xff0c;无异于大海捞针。 品牌的价格监测之…

Linux的启动流程、移植到开发板

1、linux驱动开发与裸机开发的区别 Linux系统驱动和裸机驱动的主要区别在于运行时的环境和依赖。Linux系统驱动依赖于Linux内核提供的API和服务&#xff0c;而裸机驱动则是在没有操作系统支持的情况下直接与硬件交互。因此&#xff0c;两者的开发和调试方法也有很大差异。 2、…

【Qt】控件概述(7)—— 布局管理器

布局管理器 1. 布局管理器2. QVBoxLayout——垂直布局3. QHBoxLayout——水平布局4. QGridLayout——网格布局5. QFormLayout——表单布局6. QSpacer 1. 布局管理器 在我们之前值ui界面进行拖拽设置控件时&#xff0c;都是通过手动的控制控件的位置的。同时每个控件的位置都是…

Spring Boot新闻推荐系统:用户体验优化

3系统分析 3.1可行性分析 通过对本新闻推荐系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本新闻推荐系统采用JAVA作为开发语言&#xff0c;Spring Boot框…

STM32F407寄存器操作(DMA+SPI)

1.前言 前面看B站中有些小伙伴吐槽F4的SPIDMA没有硬件可控的CS引脚&#xff0c;那么今天我就来攻破这个问题 我这边暂时没有SPI的从机芯片&#xff0c;并且接收的过程与发送的过程类似&#xff0c;所以这里我就以发送的过程为例了。 2.理论 手册上给出了如下的描述 我们关注…

Graphviz是一个开源的图形可视化软件

官网没有给出代码示例&#xff0c;所以需要自己琢磨&#xff0c; 这里最底下给了一些简单的&#xff0c; 确实可以出很好看的图片 Graphviz介绍 Graphviz是一个开源的图形可视化软件&#xff0c;主要用于绘制各种类型的图表&#xff0c;如流程图、结构图、网络拓扑图等。它通…

【黑马点评】5 Redisson分布式锁

【黑马点评】5 Redisson分布式锁 5 分布式锁-redisson5.1 分布式锁-redission功能介绍5.2 分布式锁-Redission快速入门5.3 分布式锁-redission可重入锁原理5.4 分布式锁-redission锁重试和WatchDog机制5.5 分布式锁-redission锁的MutiLock原理5.6 总结 黑马点评跟做笔记之 5 Re…

如何使用ssm实现学生工作管理系统

TOC ssm794学生工作管理系统jsp 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规范化管理。…

Java爬虫技术:解锁1688商品搜索的新维度

Java爬虫技术简介 Java爬虫技术是指使用Java语言编写的程序&#xff0c;模拟浏览器行为&#xff0c;自动化地从互联网上获取信息。随着技术的发展&#xff0c;Java爬虫技术已经非常成熟&#xff0c;有多种框架和库可以使用&#xff0c;如Jsoup、HttpClient、WebMagic等。 1688…