// OpenCV46.cpp : 定义控制台应用程序的入口点。
//利用均值迁移法跟踪目标
#include "stdafx.h"
#include
#include
using namespace cv;
using namespace std;
int main()
{
VideoCapture video(0);
if (!video.isOpened()) {
return -1;
}
//是否已经计算目标区域直方图标志,0表示没有计算,1表示已经计算
int trackObject = 0;
//计算直方图和反向直方图相关参数
int hsize = 16;
float hranges[] = { 0,180 };
const float * phranges = hranges;
//选择目标区域
Mat frame, hsv, hue, hist, histimg = Mat::zeros(200, 320, CV_8UC3), backproj;
video.read(frame);
Rect selection = selectROI("选择目标跟踪区域", frame, true, false);
while (true) {
//判断是否已经读取全部图像
if (!video.read(frame)) {
break;
}
//将图像转化为HSV颜色空间
cvtColor(frame, hsv, COLOR_BGR2HSV);
//定义计算直方图和方向直方图相关数据和图像
int ch[] = { 0,0 };
hue.create(hsv.size(), hsv.depth());
mixChannels(&hsv, 1, &hue, 1, ch, 1);
//是否已经完成跟踪目标直方图的计算
if (trackObject <= 0) {
//目标区域的HSV颜色空间
Mat roi(hue, selection);
calcHist(&roi, 1, 0, roi, hist, 1, &hsize, &phranges);
normalize(hist, hist, 0, 255, NORM_MINMAX);
//将标志设置为1,不再计算目标区域的直方图
trackObject = 1;
//显示目标区域的直方图,可以将该部分注释掉,不影响追踪效果
histimg = Scalar::all(0);
int binW = histimg.cols / hsize;
Mat buf(1, hsize, CV_8UC3);
for (int i = 0; i < hsize; i++)
buf.at(i) = Vec3b(saturate_cast(i*180. / hsize), 255, 255);
cvtColor(buf, buf, COLOR_HSV2BGR);
for (int i = 0; i < hsize; i++) {
int val = saturate_cast(hist.at(i)*histimg.rows / 255);
rectangle(histimg, Point(i*binW, histimg.rows), Point((i + 1)*binW, histimg.rows - val), Scalar(buf.at(i)), -1, 8);
}
}
//计算目标区域的方向直方图
calcBackProject(&hue, 1, 0, hist, backproj, &phranges);
//均值迁移法追踪目标
meanShift(backproj, selection, TermCriteria(TermCriteria::EPS | TermCriteria::COUNT, 10, 1));
rectangle(frame, selection, Scalar(0, 0, 255), 3, LINE_AA);
namedWindow("CamShifr Demo显示追踪结果", WINDOW_AUTOSIZE);
namedWindow("Histogram显示目标区域直方图", WINDOW_AUTOSIZE);
imshow("CamShifr Demo显示追踪结果", frame);
imshow("Histogram显示目标区域直方图", histimg);
char c = (char)waitKey(50);
if (c == 27)
break;
}
system("pause");
return 0;
}