一、储备知识
1)MeanShift迭代原理、直方图的计算,反向投影等
2)代码用到的函数:
void calcHist(const Mat* arrays, int narrays, const int* channels, InputArray mask, SparseMat&
hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=
false );
arrays:输入图像指针;
int arrays:输入图像个数
channels:通道数
Mat mask:掩码,一般为空
hist:计算出来的直方图
dims:计算出来的直方图的维数
histsize:直方图bins数目
ranges:每一个bin的范围
反向投影:
void cvCalcBackProject( IplImage** image, CvArr* back_project, const CvHistogram* hist );
image:输入图像 (也可以传递 CvMat** ).
back_project:反向投影图像,与输入图像具有同样类型.
hist:直方图
二、代码
#include <opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
Mat frame, frameHSV, imgROI, dstHist, backproj;
int histSize[1] = { 256 };
float hranges[2] = { 0, 255 };//直方图每一个bins的范围
const float* ranges[1] = { hranges };
int channels[1] = { 0};
int main()
{
VideoCapture cap("E://Datasets//img%4d.jpg");
cap >> frame;
cvtColor(frame, frameHSV, COLOR_RGB2HSV);
Rect rect(200, 115, 45, 45);//初始帧确定足球位置
imgROI = frameHSV(rect);
calcHist(&imgROI, 1, channels, Mat(), dstHist, 1, histSize, ranges);
normalize(dstHist, dstHist, 0.0, 1.0, NORM_MINMAX);
rectangle(frame, rect, Scalar(0, 255, 255));
imshow("Frame", frame);
waitKey(0);
while (true)
{
cap >> frame;
if (frame.empty()) break;
cvtColor(frame, frameHSV, COLOR_RGB2HSV);
calcBackProject(&frameHSV, 1, channels, dstHist, backproj, ranges, 255.0);
//criteria初始化,这个类是对整个meanshift迭代过程进行控制的初始参量,最大迭代次数是10,收敛阈值是0.001
TermCriteria criteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 10, 0.001);
meanShift(backproj, rect, criteria);
imgROI = frameHSV(rect);//此rect是meanshift迭代出来的新区域,新区域窗口大小不变
calcHist(&imgROI, 1, channels, Mat(), dstHist, 1, histSize, ranges);
normalize(dstHist, dstHist, 0.0, 1.0, NORM_MINMAX);
rectangle(frame, rect, Scalar(0, 255, 0));
imshow("Frame", frame);
waitKey(30);
}
return 0;
}
三、结果
初始图:
跟踪迭代图:
四、图片资源如下:
链接:https://yunpan.cn/cq9GfQDrsDL7r 密码:b135
五、后续有时间对该程序进行扩展和完善,使之功能更强大。
六、参考资料