您好,
会员登录 快速注册
退出 ( 条未读消息)
关于本站 意见反馈 首页

公告:小宅博客网可以开发票了,需要发票的,去群里找群主哈!!
全部文章分类
  • 人工智能 >

  • 编程语言 >

  • WPF系列 >

  • ASP.NET系列 >

  • Linux >

  • 数据库 >

  • 嵌入式 >

  • WEB技术 >

  • PLC系列 >

  • 微服务与框架 >

  • 小宅DIY >

  • 学习资料 >

OpenCv基础 ANN车牌识别 yolov5车牌识别 指针式仪表识别 ROS系列 YOLO Halcon Detectron2 昇腾AI ChatGPT在线体验 英伟达JETSON ChatGLM ChatTTS FunASR 地平线 ByteTrack 魔搭社区 LangChain
C C# C++ Python Java Go
WPF
ASP.NET小功能 GPS定位系统-MVC GPS定位系统-VUE ASP.NET WebRTC
Linux Linux内核 Shell MakeFile
MySql SqlServer Oracle
STM8 STM32 51单片机
VUE入门 HTML JavaScript CSS layui镜像网站 ElementUi中文官网 element-plus 图标
三菱 欧姆龙 西门子 施耐德 松下 台达
IOTSharp IOTGateway ABP FRAMEWORK Docker
亚克力音响 编程仙途:智驭万法
面试题与技巧 Python入门技能树 微软C#教程
首页 编程之美 工具下载 全国就业 流量地图 文心一言
OpenCv基础
内容介绍与资料分享 C# OpenCv环境搭建 C++ OpenCv环境搭建 Python OpenCv环境搭建 Java OpenCv环境搭建 OpenCv组件结构解析 OpenCv命名规范 OpenCv基本专业术语与方法 OpenCV 常用函数与构造体详细说明 创建画布 打开一张图片 利用imwrite生成透明png图像 图像打开、混合显示和输出 图像腐蚀 blur图像模糊(均值滤波) sobel边缘检测 canny边缘检测 Scharr滤波器 程序性能检测及优化 视频播放 摄像头录像与播放 双摄像头操作与图像相似度检测 颜色空间转换与物体追踪 彩色目标追踪 光流法运动目标检测 OpenCV中的稠密光流 背景减除 点追踪 人脸识别 支持向量机之SVM引导 支持向量机之处理线性不可分数据 ROI矩形截取 鼠标绘制矩形 用OpenCV进行基本绘图 绘图函数(python中文显示) 把鼠标当画笔 用滑动条做调色板 图像的基础操作 图像上的算术运算 多通道图像混合 图像的亮度、对比度调整 XML和YAML文件的写入 XML和YAML文件的读取 卷积操作 三种线性滤波 两种非线性滤波 7种图像处理形态学(1) 7种图像处理形态学(2) 漫水填充 图像缩放与图像金字塔 二值化基本阈值操作 图像阈值 Laplacian图像变换(拉普拉斯算子) 霍夫变换HoughLines边缘检测与线性矢量 霍夫变换HoughLinesP边缘检测与线性矢量 霍夫变换HoughCircles边缘检测与线性矢量 LSD快速直线检测 几何变换 remap重映射 remap实现多种重映射 仿射变换综合示例 直方图均衡化 CLAHE有限对比适应性直方图均衡化 draw最大的轮廓 轮廓的性质 点到多边形的最短距离 形状匹配 椭圆拟合与直线拟合 基础轮廓查找 查找并绘制轮廓综合示例 凸缺陷/凸包检测 凸包检测 创建包围轮廓的矩形边界 创建包围轮廓的圆形边 创建包围轮廓的矩形和圆形边界框 查找和绘制图片轮廓矩 分水岭算法 图像修补 H-S二维直方图的绘制/2D直方图 一维直方图的绘制 RGB三色直方图的绘制 直方图对比 使用掩膜绘制直方图 直方图反向投影 模板匹配 多对象模板匹配 cornerHarris角点检测 cornerHarris角点检测综合示例 Shi-Tomasi角点检测 亚像素级角点检测 角点检测的FAST算法(FAST特征检测器) 颜色识别 warpPerspective透视变换 SURF/SIFT特征点检测 SURF/SIFT特征描述 使用FLANN进行特征点匹配 FLANN结合SURF/SIFT进行关键点的描述和匹配 寻找已知物体(一) 寻找已知物体(二) 目标查找与跟踪 - Meanshift与CamShift BRIEF描述符 ORB ORB算法描述与匹配 LUT 图像灰度调整 离散傅里叶变换 双目摄像头与图像拼接 环境亮度检测 stitching 全景拼接 Maze-Solver迷宫解密 使用Haar分类器之面部检测 使用Haar分类器之行人检测 OpenCv Haar/LBP/HOG分类器-人脸识别 斑点检测 使用GrabCut算法进行交互式前景提取 对极几何 摄像机标定 姿势估计 立体图像中的深度地图 OpenCv中的KNN KNN手写数字识别 ​SVM手写数字识别(使用SVM进行手写数据OCR) 英文字母的OCR 预测手写数字(预测不准) K值聚类(一) K值聚类(二) 计算摄影学-图像去噪 高动态范围成像(HDRI或HDR) MSER区域检测 二维码、条形码识别 删除图像中的水印 OpenCv深度学习dnn Kinect-深度相机 OpenCv常用数学算法 360度旋转直线绘制 向量延长线上的像素扫描 Tools工具包-窗体分配
寻找已知物体(二)
BRIEF描述符
激萌の小宅 小宅博客 OpenCv基础

文章作者:激萌の小宅

促销:¥0

价格:¥0

配送方式: 购买后立即生效(如购买异常,请联系站长)
付款之后一定要等待自动跳转结束,否则购买可能会失败
  • 0 天

    有效期

  • 0

    总销量

  • 0

    累计评价

目标查找与跟踪 - Meanshift与CamShift

当前系列所有demo下载地址:

https://github.com/GaoRenBao/OpenCv4-Demo


源码参考原文:

OpenCV-Python-Tutorial-中文版.pdf (P222)  

https://docs.opencv.org/3.2.0/db/df8/tutorial_py_meanshift.html

不同编程语言对应的OpenCv版本以及开发环境信息如下: 

语言

OpenCv版本

IDE

C#

OpenCvSharp4.4.8.0.20230708

Visual Studio 2022

C++

OpenCv-4.5.5-vc14_vc15

Visual Studio 2022

Python

OpenCv-Python (4.6.0.66)

PyCharm Community Edition 2022.1.3


        要在OpenCV中使用Meanshift算法首先我们要对目标对象进行设置,计算目标对象的直方图,这样在执行meanshift算法时我们就可以将目标对象反向投影到每一帧中去 了。另外我们还需要提供窗口的起始位置。在这里我们值计算H ( Hue )通道的直方图,同样为了避免低亮度造成的影响,我们使用函数cv2.inRange()将低亮度的值忽略掉。


问题:

        我们的窗口的大小是固定的。而汽车由远及近,在视觉上是一个渐变大的过程,固定的窗口是不合适的。所以我们需要根据目标的大小和角度来对窗口的大小和角度进行修订


Camshift的优点与缺点

        原文:https://blog.csdn.net/guozhihao12345/article/details/50310253

        之前做的一个项目:在手机上实现波波球、人脸的跟踪。采用的是opencv的Camshift跟踪算法,其结果是对人脸的跟踪效果较好,对小球的跟踪效果较差。通过分析之后发现根本原因是小球移动过快,而人脸的移动较慢,所以Camshift跟踪的上人脸但跟综不上小球,任何一个跟踪算法都有其跟踪速度的极限。还有另外的一个原因是:人脸在视频中占有的区域较大 ,所以背景较简单(相对于人脸),相对于小球在视频中占用的区域较小,所以背景叫复杂(相对于小球而言),为了更好地解释这一原因这面就描述一下Camshift算法的优缺点。

       Camshift的优点:简单,计算量较少,因为Camshift的本质就局部检测,在局部里检测“密度”最大的位置。

       Camshift的缺点:Camshift的优点有时候也正是其缺点,因为其简单,所以对于复杂背景或者纹理丰富的物体跟踪效果较差。因为Camshift是对直方图反投影所形成的二值图像进行处理的,如果背景较为复杂或者物体的纹理较为丰富,那么此二值图像的噪声就很多(具体原因可参考直方图反投影的原理),这将直接干扰Camshift对物体位置的判断。

       所以对Camshift的总结为:Camshift适用于物体表面颜色较为单一,且和背景颜色差距较大

       为了实现手机下的小球跟踪,现进行了如下改进:对直方图反投影图像进行滤波处理,采用的是中值滤波,但滤波处理的计算量较大,这将影响跟踪的速度,所以这里将图像的分辨率减小至原来的三分之一,使整个工程的计算量跟之前的差不多,滤波之后就没有了噪声的影响,但是小球移动过快的情况下依然跟踪失败,这里就将Camshift的局部检测改为全局下的检测,因为没有了噪声(实际效果的确如此),所以这样做是可行的,从而实现了对小球的跟踪


测试视频:Meanshift_CamShift.mp4


C#的效果会比python的效果好很多,下面这个是C#的效果展示:

Camshift (1).gif


C#版本代码如下:

参考博客:https://blog.csdn.net/jimtien/article/details/118574551

using OpenCvSharp;
using System;

namespace demo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var capture = new VideoCapture("../../../images/Meanshift_CamShift.mp4");
            if (!capture.IsOpened())
            {
                Console.WriteLine("Open video failed!");
                return;
            }

            // take first frame of the video
            Mat frame = new Mat();
            capture.Read(frame);

            //setup initial location of window
            Rect track_window = new Rect(65, 275, 105, 105); // simply hardcoded the values

            //set up the ROI for tracking
            Mat roi = frame[track_window];
            //Cv2.ImShow("frame", frame);
            //Cv2.ImShow("roi", roi);
            //Cv2.WaitKey(0);

            Mat hsv_roi = new Mat();
            Cv2.CvtColor(roi, hsv_roi, ColorConversionCodes.BGR2HSV);

            //将低亮度的值忽略掉
            Mat mask = new Mat();
            Cv2.InRange(hsv_roi, new Scalar(0, 100, 0), new Scalar(100, 255, 255), mask);

            Mat roi_hist = new Mat();
            Cv2.CalcHist(new Mat[] { hsv_roi }, new int[] { 0 }, mask,
                roi_hist, 1, new int[] { 180 }, new float[][] { new float[] { 0, 180 } });
            //归一化
            Cv2.Normalize(roi_hist, roi_hist, 0, 255, NormTypes.MinMax);

            //Setup the termination criteria, either 10 iteration or move by atleast 1 pt
            TermCriteria term_crit = new TermCriteria(CriteriaTypes.Eps | CriteriaTypes.Count, 10, 1);

            Mat hsv = new Mat();
            Mat dst = new Mat();
            Mat img1 = new Mat();
            Mat img2 = new Mat();
            Rect track_window1 = track_window;
            Rect track_window2 = track_window;
            while (true)
            {
                capture.Read(frame);
                if (frame.Empty())
                    break;
                frame.CopyTo(img1);
                frame.CopyTo(img2);

                Cv2.CvtColor(frame, hsv, ColorConversionCodes.BGR2HSV);
                Cv2.CalcBackProject(new Mat[] { hsv }, new int[] { 0 },
                    roi_hist, dst, new Rangef[] { new Rangef(0, 180) }, true);

                // meanShift 效果
                Cv2.MeanShift(dst, ref track_window1, term_crit);
                Cv2.PutText(img1, "MeanShift", new Point(10, 30), HersheyFonts.HersheyComplex, 1, new Scalar(0, 0, 255), 2);
                Cv2.Rectangle(img1, track_window1, 255, 2);
                Cv2.ImShow("img1", img1);

                // CamShift 效果
                RotatedRect ret = Cv2.CamShift(dst, ref track_window2, term_crit);
                Point2f[] line = ret.Points();
                Cv2.PutText(img2, "CamShift", new Point(10, 30), HersheyFonts.HersheyComplex, 1, new Scalar(0, 0, 255), 2);
                Cv2.Line(img2, (Point)line[0], (Point)line[1], new Scalar(0, 0, 255), 2, LineTypes.Link8);
                Cv2.Line(img2, (Point)line[1], (Point)line[2], new Scalar(0, 0, 255), 2, LineTypes.Link8);
                Cv2.Line(img2, (Point)line[2], (Point)line[3], new Scalar(0, 0, 255), 2, LineTypes.Link8);
                Cv2.Line(img2, (Point)line[3], (Point)line[0], new Scalar(0, 0, 255), 2, LineTypes.Link8);
                Cv2.ImShow("img2", img2);

                // 按ESC退出
                if (Cv2.WaitKey(30) == 27)
                    break;
            }
        }
    }
}


C++版本代码如下:

C++效果不是很好,感觉是calcBackProject方法用错了,暂时没搞定,不过可以参考这个博客:https://blog.csdn.net/akadiao/article/details/78991095

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <video/tracking.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    //保存目标轨迹  
    std::vector<Point> pt;

    VideoCapture capture("../images/Meanshift_CamShift.mp4");
    if (!capture.isOpened())
    {
        cout << "Open video failed!" << endl;
        return 0;
    }

    // take first frame of the video
    Mat frame;
    capture.read(frame);

    //setup initial location of window
    Rect track_window(65, 275, 105, 105); // simply hardcoded the values

    //set up the ROI for tracking
    Mat roi = frame(track_window);
    //imshow("frame", frame);
    //imshow("roi", roi);
    //waitKey(0);

    Mat hsv_roi;
    cvtColor(roi, hsv_roi, COLOR_BGR2HSV);

    // 将低亮度的值忽略掉
    Mat mask;
    inRange(hsv_roi, Scalar(0, 100, 0), Scalar(100, 255, 255), mask);

    MatND roi_hist;
    int channels[] = { 0 };
    int histSize[] = { 180 };
    float range[] = { 0, 180 };
    const float* ranges[] = { range };

    // 归一化
    calcHist(&hsv_roi, 1, channels, Mat(), roi_hist, 1, histSize, ranges);
    normalize(roi_hist, roi_hist, 0, 255, NORM_MINMAX);

    //Setup the termination criteria, either 10 iteration or move by atleast 1 pt
    TermCriteria term_crit(TermCriteria::EPS | TermCriteria::COUNT, 10, 1);

    Mat hsv;
    Mat dst;
    Mat img1;
    Mat img2;
    Rect track_window1 = track_window;
    Rect track_window2 = track_window;
    while (true)
    {
        capture.read(frame);
        if (frame.empty())
            break;
        frame.copyTo(img1);
        frame.copyTo(img2);

        cvtColor(frame, hsv, COLOR_BGR2HSV);

        float hrange[] = { 0, 180 };
        const float* hranges = hrange;
        std::vector<cv::Mat> hue;
        cv::split(hsv, hue);
        calcBackProject(&hue[1], 1, 0, roi_hist, dst, &hranges);
        //calcBackProject(vector<Mat>{hue[1]}, vector<int>{0}, roi_hist, dst, vector<float>{ 0, 180 }, 1);
        
        // meanShift 效果
        meanShift(dst, track_window1, term_crit);
        putText(img1, "MeanShift", Point(10, 30), FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);
        rectangle(img1, track_window1, 255, 2);
        imshow("img1", img1);

        // CamShift 效果
        cv::Point2f lines[4];
        RotatedRect ret = CamShift(dst, track_window2, term_crit);
        ret.points(lines);
        putText(img2, "CamShift", Point(10, 30), FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2);
        line(img2, lines[0], lines[1], Scalar(0, 0, 255), 2, LINE_8);
        line(img2, lines[1], lines[2], Scalar(0, 0, 255), 2, LINE_8);
        line(img2, lines[2], lines[3], Scalar(0, 0, 255), 2, LINE_8);
        line(img2, lines[3], lines[0], Scalar(0, 0, 255), 2, LINE_8);

        // 绘制路径,原文链接:https://blog.csdn.net/akadiao/article/details/78991095
        Rect rect;
        rect.x = ret.center.x - ret.size.width / 2.0;
        rect.y = ret.center.y - ret.size.height / 2.0;
        rect.width = ret.size.width;
        rect.height = ret.size.height;
        pt.push_back(Point(rect.x + rect.width / 2, rect.y + rect.height / 2));
        for (int i = 0; i < pt.size() - 1; i++)
        {
            line(img2, pt[i], pt[i + 1], Scalar(0, 255, 0), 2);
        }
        imshow("img2", img2);

        // 按ESC退出
        if (waitKey(30) == 27)
            break;
    }
    return 0;
}


Python版本代码如下:

import numpy as np
import cv2

cap = cv2.VideoCapture('../images/Meanshift_CamShift.mp4')

# take first frame of the video
ret, frame = cap.read()
# setup initial location of window
c, r, w, h = 65, 275, 105, 105

track_window = (c, r, w, h)
# set up the ROI for tracking
roi = frame[r:r + h, c:c + w]
# cv2.imshow('frame', frame)
# cv2.imshow('roi', roi)

hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)

# 将低亮度的值忽略掉
mask = cv2.inRange(hsv_roi, np.array((0, 100, 0)), np.array((100, 255, 255)))

# 这个方法貌似也行
# roi2 = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
# ret, mask = cv2.threshold(roi2, 100, 255, cv2.THRESH_BINARY)
# mask = cv2.bitwise_not(mask)

# cv2.imshow('hsv_roi', hsv_roi)
# cv2.imshow('mask', mask)
# cv2.waitKey(0)

roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0, 180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)

# Setup the termination criteria, either 10 iteration or move by atleast 1 pt
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

track_window1 = track_window
track_window2 = track_window

while True:
    ret, frame = cap.read()
    if ret is True:
        img1 = np.copy(frame)
        img2 = np.copy(frame)

        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
        dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)

        # meanShift 效果
        ret, track_window = cv2.meanShift(dst, track_window1, term_crit)
        x, y, w, h = track_window
        img1 = cv2.rectangle(img1, (x, y), (x + w, y + h), (0, 0, 255), 2)
        img1 = cv2.putText(img1, "MeanShift", (10, 30), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255), 2)
        cv2.imshow('img1', img1)

        # CamShift 效果
        ret, track_window = cv2.CamShift(dst, track_window2, term_crit)
        pts = cv2.boxPoints(ret)
        pts = np.int0(pts)
        print('len pts:', len(pts), pts)
        img2 = cv2.polylines(img2, [pts], True, (0, 255, 0), 2)
        img2 = cv2.putText(img2, "CamShift", (10, 30), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)
        cv2.imshow('img2', img2)
        # 按ESC退出
        if cv2.waitKey(30) == 27:
            break
    else:
        break
cv2.destroyAllWindows()
cap.release()


寻找已知物体(二)
BRIEF描述符

友情链接: CSDN激萌の小宅 95知识库 自考题库 罗分明个人网络博客 精益编程leanboot

小宅博客  www.bilibili996.com All Rights Reserved. 备案号: 闽ICP备2024034575号

网站经营许可证  福建省福州市 Copyright©2021-2025 版权所有

小宅博客
首页 智能家居 地图定位
公告:小宅博客网可以开发票了,需要发票的,去群里找群主哈!!

文章作者:激萌の小宅

促销:¥0

价格:¥0

配送方式: 购买后立即生效(如购买异常,请联系站长)
付款之后一定要等待自动跳转结束,否则购买可能会失败
  • 0 天

    有效期

  • 0

    总销量

  • 0

    累计评价

目标查找与跟踪 - Meanshift与CamShift

当前系列所有demo下载地址:

https://github.com/GaoRenBao/OpenCv4-Demo


源码参考原文:

OpenCV-Python-Tutorial-中文版.pdf (P222)  

https://docs.opencv.org/3.2.0/db/df8/tutorial_py_meanshift.html

不同编程语言对应的OpenCv版本以及开发环境信息如下: 

语言

OpenCv版本

IDE

C#

OpenCvSharp4.4.8.0.20230708

Visual Studio 2022

C++

OpenCv-4.5.5-vc14_vc15

Visual Studio 2022

Python

OpenCv-Python (4.6.0.66)

PyCharm Community Edition 2022.1.3


        要在OpenCV中使用Meanshift算法首先我们要对目标对象进行设置,计算目标对象的直方图,这样在执行meanshift算法时我们就可以将目标对象反向投影到每一帧中去 了。另外我们还需要提供窗口的起始位置。在这里我们值计算H ( Hue )通道的直方图,同样为了避免低亮度造成的影响,我们使用函数cv2.inRange()将低亮度的值忽略掉。


问题:

        我们的窗口的大小是固定的。而汽车由远及近,在视觉上是一个渐变大的过程,固定的窗口是不合适的。所以我们需要根据目标的大小和角度来对窗口的大小和角度进行修订


Camshift的优点与缺点

        原文:https://blog.csdn.net/guozhihao12345/article/details/50310253

        之前做的一个项目:在手机上实现波波球、人脸的跟踪。采用的是opencv的Camshift跟踪算法,其结果是对人脸的跟踪效果较好,对小球的跟踪效果较差。通过分析之后发现根本原因是小球移动过快,而人脸的移动较慢,所以Camshift跟踪的上人脸但跟综不上小球,任何一个跟踪算法都有其跟踪速度的极限。还有另外的一个原因是:人脸在视频中占有的区域较大 ,所以背景较简单(相对于人脸),相对于小球在视频中占用的区域较小,所以背景叫复杂(相对于小球而言),为了更好地解释这一原因这面就描述一下Camshift算法的优缺点。

       Camshift的优点:简单,计算量较少,因为Camshift的本质就局部检测,在局部里检测“密度”最大的位置。

       Camshift的缺点:Camshift的优点有时候也正是其缺点,因为其简单,所以对于复杂背景或者纹理丰富的物体跟踪效果较差。因为Camshift是对直方图反投影所形成的二值图像进行处理的,如果背景较为复杂或者物体的纹理较为丰富,那么此二值图像的噪声就很多(具体原因可参考直方图反投影的原理),这将直接干扰Camshift对物体位置的判断。

       所以对Camshift的总结为:Camshift适用于物体表面颜色较为单一,且和背景颜色差距较大

       为了实现手机下的小球跟踪,现进行了如下改进:对直方图反投影图像进行滤波处理,采用的是中值滤波,但滤波处理的计算量较大,这将影响跟踪的速度,所以这里将图像的分辨率减小至原来的三分之一,使整个工程的计算量跟之前的差不多,滤波之后就没有了噪声的影响,但是小球移动过快的情况下依然跟踪失败,这里就将Camshift的局部检测改为全局下的检测,因为没有了噪声(实际效果的确如此),所以这样做是可行的,从而实现了对小球的跟踪


测试视频:Meanshift_CamShift.mp4


C#的效果会比python的效果好很多,下面这个是C#的效果展示:

Camshift (1).gif


C#版本代码如下:

参考博客:https://blog.csdn.net/jimtien/article/details/118574551

using OpenCvSharp;
using System;

namespace demo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var capture = new VideoCapture("../../../images/Meanshift_CamShift.mp4");
            if (!capture.IsOpened())
            {
                Console.WriteLine("Open video failed!");
                return;
            }

            // take first frame of the video
            Mat frame = new Mat();
            capture.Read(frame);

            //setup initial location of window
            Rect track_window = new Rect(65, 275, 105, 105); // simply hardcoded the values

            //set up the ROI for tracking
            Mat roi = frame[track_window];
            //Cv2.ImShow("frame", frame);
            //Cv2.ImShow("roi", roi);
            //Cv2.WaitKey(0);

            Mat hsv_roi = new Mat();
            Cv2.CvtColor(roi, hsv_roi, ColorConversionCodes.BGR2HSV);

            //将低亮度的值忽略掉
            Mat mask = new Mat();
            Cv2.InRange(hsv_roi, new Scalar(0, 100, 0), new Scalar(100, 255, 255), mask);

            Mat roi_hist = new Mat();
            Cv2.CalcHist(new Mat[] { hsv_roi }, new int[] { 0 }, mask,
                roi_hist, 1, new int[] { 180 }, new float[][] { new float[] { 0, 180 } });
            //归一化
            Cv2.Normalize(roi_hist, roi_hist, 0, 255, NormTypes.MinMax);

            //Setup the termination criteria, either 10 iteration or move by atleast 1 pt
            TermCriteria term_crit = new TermCriteria(CriteriaTypes.Eps | CriteriaTypes.Count, 10, 1);

            Mat hsv = new Mat();
            Mat dst = new Mat();
            Mat img1 = new Mat();
            Mat img2 = new Mat();
            Rect track_window1 = track_window;
            Rect track_window2 = track_window;
            while (true)
            {
                capture.Read(frame);
                if (frame.Empty())
                    break;
                frame.CopyTo(img1);
                frame.CopyTo(img2);

                Cv2.CvtColor(frame, hsv, ColorConversionCodes.BGR2HSV);
                Cv2.CalcBackProject(new Mat[] { hsv }, new int[] { 0 },
                    roi_hist, dst, new Rangef[] { new Rangef(0, 180) }, true);

                // meanShift 效果
                Cv2.MeanShift(dst, ref track_window1, term_crit);
                Cv2.PutText(img1, "MeanShift", new Point(10, 30), HersheyFonts.HersheyComplex, 1, new Scalar(0, 0, 255), 2);
                Cv2.Rectangle(img1, track_window1, 255, 2);
                Cv2.ImShow("img1", img1);

                // CamShift 效果
                RotatedRect ret = Cv2.CamShift(dst, ref track_window2, term_crit);
                Point2f[] line = ret.Points();
                Cv2.PutText(img2, "CamShift", new Point(10, 30), HersheyFonts.HersheyComplex, 1, new Scalar(0, 0, 255), 2);
                Cv2.Line(img2, (Point)line[0], (Point)line[1], new Scalar(0, 0, 255), 2, LineTypes.Link8);
                Cv2.Line(img2, (Point)line[1], (Point)line[2], new Scalar(0, 0, 255), 2, LineTypes.Link8);
                Cv2.Line(img2, (Point)line[2], (Point)line[3], new Scalar(0, 0, 255), 2, LineTypes.Link8);
                Cv2.Line(img2, (Point)line[3], (Point)line[0], new Scalar(0, 0, 255), 2, LineTypes.Link8);
                Cv2.ImShow("img2", img2);

                // 按ESC退出
                if (Cv2.WaitKey(30) == 27)
                    break;
            }
        }
    }
}


C++版本代码如下:

C++效果不是很好,感觉是calcBackProject方法用错了,暂时没搞定,不过可以参考这个博客:https://blog.csdn.net/akadiao/article/details/78991095

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <video/tracking.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    //保存目标轨迹  
    std::vector<Point> pt;

    VideoCapture capture("../images/Meanshift_CamShift.mp4");
    if (!capture.isOpened())
    {
        cout << "Open video failed!" << endl;
        return 0;
    }

    // take first frame of the video
    Mat frame;
    capture.read(frame);

    //setup initial location of window
    Rect track_window(65, 275, 105, 105); // simply hardcoded the values

    //set up the ROI for tracking
    Mat roi = frame(track_window);
    //imshow("frame", frame);
    //imshow("roi", roi);
    //waitKey(0);

    Mat hsv_roi;
    cvtColor(roi, hsv_roi, COLOR_BGR2HSV);

    // 将低亮度的值忽略掉
    Mat mask;
    inRange(hsv_roi, Scalar(0, 100, 0), Scalar(100, 255, 255), mask);

    MatND roi_hist;
    int channels[] = { 0 };
    int histSize[] = { 180 };
    float range[] = { 0, 180 };
    const float* ranges[] = { range };

    // 归一化
    calcHist(&hsv_roi, 1, channels, Mat(), roi_hist, 1, histSize, ranges);
    normalize(roi_hist, roi_hist, 0, 255, NORM_MINMAX);

    //Setup the termination criteria, either 10 iteration or move by atleast 1 pt
    TermCriteria term_crit(TermCriteria::EPS | TermCriteria::COUNT, 10, 1);

    Mat hsv;
    Mat dst;
    Mat img1;
    Mat img2;
    Rect track_window1 = track_window;
    Rect track_window2 = track_window;
    while (true)
    {
        capture.read(frame);
        if (frame.empty())
            break;
        frame.copyTo(img1);
        frame.copyTo(img2);

        cvtColor(frame, hsv, COLOR_BGR2HSV);

        float hrange[] = { 0, 180 };
        const float* hranges = hrange;
        std::vector<cv::Mat> hue;
        cv::split(hsv, hue);
        calcBackProject(&hue[1], 1, 0, roi_hist, dst, &hranges);
        //calcBackProject(vector<Mat>{hue[1]}, vector<int>{0}, roi_hist, dst, vector<float>{ 0, 180 }, 1);
        
        // meanShift 效果
        meanShift(dst, track_window1, term_crit);
        putText(img1, "MeanShift", Point(10, 30), FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);
        rectangle(img1, track_window1, 255, 2);
        imshow("img1", img1);

        // CamShift 效果
        cv::Point2f lines[4];
        RotatedRect ret = CamShift(dst, track_window2, term_crit);
        ret.points(lines);
        putText(img2, "CamShift", Point(10, 30), FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2);
        line(img2, lines[0], lines[1], Scalar(0, 0, 255), 2, LINE_8);
        line(img2, lines[1], lines[2], Scalar(0, 0, 255), 2, LINE_8);
        line(img2, lines[2], lines[3], Scalar(0, 0, 255), 2, LINE_8);
        line(img2, lines[3], lines[0], Scalar(0, 0, 255), 2, LINE_8);

        // 绘制路径,原文链接:https://blog.csdn.net/akadiao/article/details/78991095
        Rect rect;
        rect.x = ret.center.x - ret.size.width / 2.0;
        rect.y = ret.center.y - ret.size.height / 2.0;
        rect.width = ret.size.width;
        rect.height = ret.size.height;
        pt.push_back(Point(rect.x + rect.width / 2, rect.y + rect.height / 2));
        for (int i = 0; i < pt.size() - 1; i++)
        {
            line(img2, pt[i], pt[i + 1], Scalar(0, 255, 0), 2);
        }
        imshow("img2", img2);

        // 按ESC退出
        if (waitKey(30) == 27)
            break;
    }
    return 0;
}


Python版本代码如下:

import numpy as np
import cv2

cap = cv2.VideoCapture('../images/Meanshift_CamShift.mp4')

# take first frame of the video
ret, frame = cap.read()
# setup initial location of window
c, r, w, h = 65, 275, 105, 105

track_window = (c, r, w, h)
# set up the ROI for tracking
roi = frame[r:r + h, c:c + w]
# cv2.imshow('frame', frame)
# cv2.imshow('roi', roi)

hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)

# 将低亮度的值忽略掉
mask = cv2.inRange(hsv_roi, np.array((0, 100, 0)), np.array((100, 255, 255)))

# 这个方法貌似也行
# roi2 = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
# ret, mask = cv2.threshold(roi2, 100, 255, cv2.THRESH_BINARY)
# mask = cv2.bitwise_not(mask)

# cv2.imshow('hsv_roi', hsv_roi)
# cv2.imshow('mask', mask)
# cv2.waitKey(0)

roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0, 180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)

# Setup the termination criteria, either 10 iteration or move by atleast 1 pt
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

track_window1 = track_window
track_window2 = track_window

while True:
    ret, frame = cap.read()
    if ret is True:
        img1 = np.copy(frame)
        img2 = np.copy(frame)

        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
        dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)

        # meanShift 效果
        ret, track_window = cv2.meanShift(dst, track_window1, term_crit)
        x, y, w, h = track_window
        img1 = cv2.rectangle(img1, (x, y), (x + w, y + h), (0, 0, 255), 2)
        img1 = cv2.putText(img1, "MeanShift", (10, 30), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255), 2)
        cv2.imshow('img1', img1)

        # CamShift 效果
        ret, track_window = cv2.CamShift(dst, track_window2, term_crit)
        pts = cv2.boxPoints(ret)
        pts = np.int0(pts)
        print('len pts:', len(pts), pts)
        img2 = cv2.polylines(img2, [pts], True, (0, 255, 0), 2)
        img2 = cv2.putText(img2, "CamShift", (10, 30), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)
        cv2.imshow('img2', img2)
        # 按ESC退出
        if cv2.waitKey(30) == 27:
            break
    else:
        break
cv2.destroyAllWindows()
cap.release()