目标跟踪:反向投影直方图+mean shift
来源:互联网 发布:单门网络门禁控制器 编辑:程序博客网 时间:2024/05/22 12:22
假设我们希望从图2(待检测图像)中检测出“飞行的蜥蜴”。首先要做的就是准备一个样本,比如在图1(参考图像)中选择一个包含样本的兴趣区域。
图1(参考图像):
图2(待检测图像,可注意到飞蜥位置和形态都出现了轻微改变):
我们计算参考图像中兴趣区域的直方图(这里取H(色调)通道),然后将直方图归一化。这时直方图的箱子值代表的是特定颜色出现的概率。
反向投影直方图的过程包括:从归一化的直方图中读取概率值并把待检测图像中的每个像素替换成与之对应的概率值。
OpenCV中的反向投影函数:
//Calculates the back projection of a histogram.void calcBackProject(const Mat* images, int nimages,//图像个数(这里选1) const int* channels, //用到的通道数,取决于直方图维数 InputArray hist,//输入直方图OutputArray backProject,//反向投影结果 const float** ranges, //iamges图像值的范围 double scale=1, bool uniform=true )
反向投影的结果就是概率分布图,表示一个指定图像片段出现在特定位置的概率,属于该位置的概率从亮(高概率)到暗(低概率):
假设我们已经知道图像中某个物体的大概位置(视频跟踪中相邻帧目标位置改变不大),就可以用概率分布图找到物体的准确位置。最可能出现的位置就是窗口中概率最大的位置。因此我们可以从一个初始位置开始,在周围反复移动,就可能找到物体所在的准确位置。这种算法称为mean shift。
OpenCV中的meanshift函数用法:
//设置迭代停止条件cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER,10,0.01);//meanshift算法实现,运行后rect的值会更新cv::meanShift(result,rect,criteria);
最终目标跟踪的结果:
完整代码:
反向投影直方图的取得,封装在了ContentFinder类中
//头文件 ContentFinder.h#pragma once#include"opencv2/opencv.hpp"#include"opencv2/core/core.hpp"#include"opencv2/highgui/highgui.hpp"class ContentFinder{private: //直方图参数 float hranges[2]; const float* ranges[3]; int channels[3]; float threshold; cv::Mat histogram;public: ContentFinder(); void setThreshold(float t);//阈值化参数。t>0,将反向投影结果阈值化,t<=0则不阈值化 void setHistogram(cv::Mat hist);//输入要反投影的直方图 cv::Mat find(const cv::Mat& image);//返回反投影结果 cv::Mat find(const cv::Mat& image, float minValue, float maxValue, int* channels);//重载 ~ContentFinder();};
//实现文件 ContentFinder.cpp#include "ContentFinder.h"ContentFinder::ContentFinder() :threshold(0.1f){ ranges[0] = hranges; ranges[1] = hranges; ranges[2] = hranges;}void ContentFinder::setThreshold(float t){ threshold = t;}void ContentFinder::setHistogram(cv::Mat hist){ histogram = hist; cv::normalize(histogram,histogram,1.0);}cv::Mat ContentFinder::find(const cv::Mat& image){ hranges[0] = 0.0; hranges[1] = 256.0; channels[0] = 0; channels[1] = 1; channels[2] = 2; return find(image,hranges[0],hranges[1],channels);}cv::Mat ContentFinder::find(const cv::Mat& image, float minValue, float maxValue, int* channels){ cv::Mat result; hranges[0] = minValue; hranges[1] = maxValue; for (int i = 0; i < histogram.dims;i++) { this->channels[i] = channels[i]; } //反投影直方图 cv::calcBackProject(&image,1,channels,histogram,result,ranges,255.0); //阈值化 if (threshold > 0) { cv::threshold(result,result,255.0*threshold,255.0,cv::THRESH_BINARY); } return result;}ContentFinder::~ContentFinder(){}
main函数里的代码:
//main.cppcv::Mat image = cv::imread("001.jpg", 1);//参考图像 cv::Mat hsv; cv::cvtColor(image,hsv,CV_BGR2HSV); cv::Rect rect(230, 210, 130, 140);//采样区域 cv::rectangle(image, rect, cv::Scalar(0, 255, 0));//初始位置,为绿框 cv::imshow("image", image); cv::Mat imageROI = image(rect); int minSat = 65; ColorHistogram hc; hc.setSize(8); cv::Mat colorHist = hc.getHueHistogram(imageROI,minSat); //在第二幅图中检测 cv::Mat image2 = cv::imread("002.jpg", 1); cv::Mat hsv2; cv::cvtColor(image2, hsv2, CV_BGR2HSV); ContentFinder finder; finder.setHistogram(colorHist); finder.setThreshold(-1.0f);//不设阈值 int ch[1] = {0}; cv::Mat result = finder.find(hsv2,0.0f,180.0f,ch);//反投影结果 cv::imshow("finder", result); cv::rectangle(image2, rect, cv::Scalar(0, 255, 0));//初始位置,为绿框 cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER,10,0.01); cv::meanShift(result,rect,criteria); cv::rectangle(image2, rect, cv::Scalar(0, 0, 255));//跟踪位置,为红框 cv::imshow("draw rectangle", image2);
代码中调用了彩色图像直方图计算类的方法。彩色图像直方图的计算,参见另一篇博客:OpenCV计算和显示图像直方图
0 0
- 目标跟踪:反向投影直方图+mean shift
- OpenCV—Mean Shift算法:直方图反向投影查找目标
- 目标跟踪之mean shift
- 基于核函数加权直方图的Mean Shift目标跟踪 (二维颜色直方图)
- 反向投影和mean-shift图形检测
- Mean Shift 目标跟踪算法(一)
- 基于mean-shift的简单目标跟踪
- 目标跟踪方法--Mean Shift 算法
- 【跟踪】基于mean shift的目标跟踪算法
- mean-shift算法在目标跟踪方面的应用
- 基于mean shift方法的目标跟踪学习
- mean shift 跟踪算法
- cvCalcBackProject-直方图反向投影
- 直方图反向投影
- opencv 直方图反向投影
- 直方图的反向投影
- 直方图的反向投影
- 直方图的反向投影
- 《Linux内核设计与实现》读书笔记(十五)- 进程地址空间(kernel 2.6.32.60)
- HTML5拖拉上传文件
- How to Check Whether Oracle Binary/Instance is RAC Enabled and Relink Oracle Binary in RAC
- java虚拟机------java内存结构
- 干货:结合Scikit-learn介绍几种常用的特征选择方法
- 目标跟踪:反向投影直方图+mean shift
- API函数
- vpn架设思路
- 前端构建工具gulp入门教程
- 小程序tabBar底部导航详细介绍
- Android程序员学PHP开发(4)-可变变量变量引用-PhpStorm
- SMTP, POP3, IMAP,Exchange ActiveSync区别
- AndroidStudio快速打开别人的demo(同样是用AS写的demo可用此方法)
- C#中如何连接数据库并执行SQL语句