使用opencv自带的gmm前景提取算法以及kcf算法,实现自动跟踪移动目标,效果一般般。代码如下
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/tracking.hpp>
using namespace cv;
using namespace std;
int main()
{
string videp_path = "";
VideoCapture cap(0);
if (!cap.isOpened()) {
return -1;
}
Mat frame;
Mat foreground;
Mat background;
Mat fgmask;
Mat track_img;
//定义gmm前景提取模型
Ptr<BackgroundSubtractorMOG2> ptrMOG = createBackgroundSubtractorMOG2();
//定义kcf跟踪器
Ptr<TrackerKCF> tracker = TrackerKCF::create();
bool startTrack = false;
bool restartTrack = false;
bool stopTrack = false;
bool isTracking = false;
Rect2d track_box;
vector<vector<Point>> contours;
vector<Point> maxContour;
Rect2d target;
while (cap.read(frame))
{
frame.copyTo(track_img);
ptrMOG->apply(frame, fgmask, -1);
foreground = Scalar::all(0);
//对fgmask进行处理
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
erode(fgmask, fgmask, element);
dilate(fgmask, fgmask, element);
frame.copyTo(foreground, fgmask);
imshow("fgmask", fgmask);
//找轮廓
findContours(fgmask, contours, noArray(), RETR_LIST, CHAIN_APPROX_SIMPLE);
//--------------------------
//开始跟踪 先检测前景,再筛选轮廓
if (startTrack) {
if (contours.size() > 0) { //找到最大轮廓
maxContour = contours[0];
for (vector<Point> t : contours) {
if (t.size() > maxContour.size()) {
maxContour = t;
}
}
target = boundingRect(maxContour);//最大轮廓的包围框
if (target.area() > 400) { //目标满足条件,则进行跟踪 否则继续查找目标
track_box = target;
tracker->init(track_img, track_box); //初始化跟踪器
isTracking = true;
startTrack = false;
}
}
}
//------------------------------
//跟踪
if (isTracking == true) {
tracker->update(track_img, track_box);
rectangle(track_img, track_box, Scalar(0, 255, 0), 2);
putText(track_img, "Tracking", Point(20, 40), CV_FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 255, 0), 2);
imshow("track", track_img);
}
//------------------------------
//重新跟踪
if (restartTrack == true) {
if (isTracking == true) { //首先停止跟踪
isTracking = false;
}
else {
startTrack = true; //重新跟踪
restartTrack = false;
}
}
//-------------------------------
//停止跟踪
if (stopTrack == true) {
isTracking = false;
stopTrack = false;
}
//imshow("mask", fgmask);
//imshow("foreground", foreground);
imshow("frame", frame);
switch (cvWaitKey(10))
{
case 's': //s键开始
cout << "开始跟踪.................." << endl;
startTrack = true;
break;
case 'r': //r键重置
cout << "重新跟踪.................." << endl;
restartTrack = true;
break;
case 'p': //p键停止
cout << "停止跟踪.................." << endl;
stopTrack = true;
break;
default:
break;
}
}
return 1;
}