OpenCV视觉分析之目标跟踪(12)找到局部的最大值函数meanShift()的使用

  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

在反向投影图像上找到一个对象。

meanShift 是一种用于图像处理和计算机视觉领域的算法,特别适用于目标跟踪、图像分割等任务。该算法基于一个简单的概念:通过迭代地移动窗口到更高密度的区域,直到找到局部的最大值(即密度最高的点)。在图像处理中,这个"密度"通常指的是像素颜色或特征空间中的分布。

基本原理

  • 颜色空间中的应用:在颜色空间中,每个像素可以被视为一个点,这些点具有特定的颜色值。对于给定的目标(如一个特定颜色的物体),可以通过计算目标区域内所有像素的颜色直方图来定义其特征。meanShift 算法通过迭代地寻找颜色直方图中概率密度最大的点来跟踪目标的位置变化。
  • 迭代过程:在每次迭代中,算法会计算当前窗口内所有点的加权平均位置(权重通常是基于距离的核函数),并将窗口中心移动到这个新位置。这一过程会重复进行,直到窗口中心的变化小于某个阈值或达到最大迭代次数为止。

函数原型

cpp 复制代码
int cv::meanShift	
(
	InputArray 	probImage,
	Rect & 	window,
	TermCriteria 	criteria 
)		

参数

  • 参数probImage 对象直方图的反向投影。详情见 calcBackProject。
  • 参数window 初始搜索窗口。
  • 参数criteria 迭代搜索算法的停止准则。返回值:CAMSHIFT 收敛所需的迭代次数。该函数实现了迭代对象搜索算法。它接受对象的输入反向投影和初始位置。计算反向投影图像中窗口的质量中心,并将搜索窗口中心移动到质量中心。该过程重复进行,直到达到指定的迭代次数 criteria.maxCount 或者窗口中心移动的距离小于 criteria.epsilon。该算法在 CamShift 内部使用,与 CamShift 不同的是,在搜索过程中搜索窗口的大小或方向不会改变。您可以直接将 calcBackProject 的输出传递给此函数。但是,如果先对反向投影进行预过滤并去除噪声,可以获得更好的结果。例如,您可以通过 findContours 获取连通组件,丢弃面积较小的轮廓(contourArea),并使用 drawContours 绘制剩余的轮廓。

代码示例

cpp 复制代码
#include <iostream>
#include <opencv2/opencv.hpp>

int main()
{
    // 读取视频
    cv::VideoCapture cap( 0 );
    if ( !cap.isOpened() )
    {
        std::cout << "Error opening video file" << std::endl;
        return -1;
    }

    cv::Mat frame, hsv, mask, hist, backproj;
    cv::Rect trackWindow;

    // 从第一帧选择ROI
    cap >> frame;
    cv::imshow( "Select ROI", frame );
    trackWindow = cv::selectROI( "Select ROI", frame );
    cv::destroyWindow( "Select ROI" );

    // 转换到HSV色彩空间
    cv::cvtColor( frame, hsv, cv::COLOR_BGR2HSV );

    // 创建掩码
    cv::inRange( hsv, cv::Scalar( 0, 60, 32 ), cv::Scalar( 180, 255, 255 ), mask );

    // 定义直方图的范围
    const int channels[]  = { 0 };    // 仅使用H通道
    const int histSize[]  = { 180 };  // H通道有180个bin
    float hranges[]       = { 0, 180 };
    const float* ranges[] = { hranges };

    // 计算ROI的直方图
    cv::calcHist( &hsv, 1, channels, mask, hist, 1, histSize, ranges );

    // 归一化直方图
    cv::normalize( hist, hist, 0, 255, cv::NORM_MINMAX );

    while ( true )
    {
        cap >> frame;
        if ( frame.empty() )
            break;

        // 计算反向投影
        cv::cvtColor( frame, hsv, cv::COLOR_BGR2HSV );
        cv::calcBackProject( &hsv, 1, channels, hist, backproj, ranges );

        // 执行meanShift
        cv::meanShift( backproj, trackWindow, cv::TermCriteria( cv::TermCriteria::EPS | cv::TermCriteria::COUNT, 10, 1 ) );

        // 在图像上画出跟踪框
        cv::rectangle( frame, trackWindow, cv::Scalar( 255, 0, 0 ), 2, 1 );

        // 显示结果
        cv::imshow( "Mean Shift Tracking", frame );

        char c = ( char )cv::waitKey( 30 );
        if ( c == 27 )
            break;  // 按ESC键退出
    }

    cap.release();
    cv::destroyAllWindows();

    return 0;
}

运行结果

相关推荐
HDU-Dade26 分钟前
【校招笔试真题】简要介绍 Self-Attention 的前沿算法
人工智能·算法
2601_967987371 小时前
用Python+OpenCV+YOLO写个游戏脚本:从自动瞄准到自动采集的保姆级教程
python·opencv·yolo·目标检测·游戏自动化
在所不辞兄1 小时前
【零基础学智能仿真-63】ABACUS作业工具与MCP接口
人工智能·深度学习·神经网络·机器学习·智能仿真
楚山之石1 小时前
【Medical Image Analysis】深度学习医学图像合成综述:伪CT、合成MRI与合成PET的架构、性能与临床边界
图像处理·人工智能·学习·mr·mri
blackappleD1 小时前
百度 Unlimited OCR 2 拆解:SR-SWA 如何让百页文档的 KV 缓存不再涨
人工智能·llm
数字新视界1 小时前
国产动环数据库在智能机房环境监控中的应用与优势分析
大数据·人工智能·数据中心·机房管理·模块化机房
holly就是我1 小时前
AI 编程助手为什么跑偏?用开源 ccglass 看清 Prompt、工具调用和 Token 消耗
人工智能·后端
雨中飘荡的记忆2 小时前
额度又见底了?这个开源项目,给 AI 编程助手接上 61 家"加油站"
人工智能
天远Date Lab2 小时前
零信任架构实战:基于天远企业年报信息核验构建自动化商业保理财务与社保穿透评估网关
人工智能·架构·自动化
EnCi Zheng2 小时前
后端怎么把AI接口稳定安全低成本接进业务:超时重试、密钥隔离与成本熔断清单
人工智能·后端·安全·架构·api