【无标题】(c++&opencv)基于高斯混合模型的多目标追踪方法练习

参考 https://blog.csdn.net/xiao__run/article/details/77478579 运动目标检测部分,简单手写了一下多目标追踪
存在一些问题未解决:由于检测部分并不时刻准确,导致同一物体不同时刻id会变
ubuntu 下 opencv4(用3的话改一些cv里变量的名字即可)

效果一般但多少像点样子:
【无标题】(c++&opencv)基于高斯混合模型的多目标追踪方法练习_第1张图片

CmakeList.txt:

cmake_minimum_required( VERSION 2.8 )
project( track )
find_package( OpenCV REQUIRED )
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(test test.cpp)
target_link_libraries(test ${OpenCV_LIBS})

源代码test.cpp:

#include   
#include   
#include   
#include 
using namespace std;
using namespace cv;

; 
//画叉
#define drawCross( img, center, color, d )\
line(img, Point(center.x - d, center.y - d), Point(center.x + d, center.y + d), color, 2, CV_AA, 0);\
line(img, Point(center.x + d, center.y - d), Point(center.x - d, center.y + d), color, 2, CV_AA, 0);

//计算两中心点距离
double ComputeDistance( vector<double> c1, vector<double> c2){
    return sqrt( (c1[0]-c2[0])*(c1[0]-c2[0])+(c1[1]-c2[1])*(c1[1]-c2[1]) );
}

string num2str(int i)//int转型为字符串
{
	stringstream ss;
	ss << i;
	return ss.str();
}

int main(){
    Mat frame, thresh_frame;
    int therehold = 100;
    /**/
    int count = 0;
    //用vetor来作容器,(按道理用map应该会更方便点)
    vector<vector<double> > center_points_prev_frame;//存上一帧各boxs中心
    vector<vector<double> > center_points_cur_frame;//存储当前帧boxs中心
    vector<vector<double> > tracking_object_center;//跟踪的目标的中心
    vector<vector<vector<double> > > tractory;//跟踪的目标的每个id的轨迹
    int track_id = 0;
    /**/
	vector<Mat> channels;
	VideoCapture capture("cars.avi");
	if (!capture.isOpened())
		cout << "hello";
	vector<Vec4i> hierarchy;
	vector<vector<Point> > contours;
    cv::Mat back, img;
	cv::Mat fore;
	cv::Ptr<BackgroundSubtractorMOG2> bg = createBackgroundSubtractorMOG2();
	int incr = 0;
	int track = 0;
	bool update_bg_model = true;
    if (!capture.isOpened())
		cerr << "Problem opening video source" << endl;

    bool isfirstframe = true;
    while ((char)waitKey(1) != 'q' && capture.grab()){
        capture.retrieve(frame);
        count ++;//计第几帧

		/***************************根据背景提取动态目标**********************/
        bg->apply(frame, fore, update_bg_model ? -1 : 0);
		bg->getBackgroundImage(back);
		erode(fore, fore, Mat());
		erode(fore, fore, Mat());
		dilate(fore, fore, Mat());
		dilate(fore, fore, Mat());
		dilate(fore, fore, Mat());
		dilate(fore, fore, Mat());
		dilate(fore, fore, Mat());
		dilate(fore, fore, Mat());
		dilate(fore, fore, Mat());

        cv::normalize(fore, fore, 0, 1., cv::NORM_MINMAX);
		cv::threshold(fore, fore, .5, 1., cv::THRESH_BINARY);

        split(frame, channels);
		add(channels[0], channels[1], channels[1]);
		subtract(channels[2], channels[1], channels[2]);
		threshold(channels[2], thresh_frame, 50, 255, cv::THRESH_BINARY);
		medianBlur(thresh_frame, thresh_frame, 5);
        findContours(fore, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, Point(0, 0));
		vector<vector<Point> > contours_poly(contours.size());
		vector<Rect> boundRect(contours.size());
        Mat drawing = Mat::zeros(thresh_frame.size(), CV_8UC1);
		for (size_t i = 0; i < contours.size(); i++)
		{
			//          cout << contourArea(contours[i]) << endl;  
			if (contourArea(contours[i]) > 500)
				drawContours(drawing, contours, i, Scalar::all(255), cv::FILLED, 8, vector<Vec4i>(), 0, Point());
		}
		thresh_frame = drawing;

		findContours(fore, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, Point(0, 0));

		drawing = Mat::zeros(thresh_frame.size(), CV_8UC1);
		for (size_t i = 0; i < contours.size(); i++)
		{
			//          cout << contourArea(contours[i]) << endl;  
			if (contourArea(contours[i]) > 1000)
				drawContours(drawing, contours, i, Scalar::all(255), cv::FILLED, 8, vector<Vec4i>(), 0, Point());
		}
		thresh_frame = drawing;

		for (size_t i = 0; i < contours.size(); i++)
		{
			approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);//把一个连续光滑曲线折线化,对图像轮廓点进行多边形拟合。
			boundRect[i] = boundingRect(Mat(contours_poly[i]));

		}
        /****************************************************************************/
        //计算当前帧各个box中心
        center_points_prev_frame.assign(center_points_cur_frame.begin(),center_points_cur_frame.end());//赋值
        center_points_cur_frame.clear();
        for (size_t i = 0; i < contours.size(); i++){
            if (contourArea(contours[i]) > 3000){
            vector<double> center;
            center.push_back(boundRect[i].x + (boundRect[i].width / 2));
            center.push_back(boundRect[i].y + (boundRect[i].height / 2));
            //cout<
            center_points_cur_frame.push_back(center);
            //rectangle(frame, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 2, 8, 0);
            }
        }
        //cout<<" cur_num1 " <
        if( count == 1 ) {
            imshow("Video", frame);
            //waitKey(0);
            cout<<"第一帧"<<endl;
            continue;}
        if( count ==2  ){
            for(auto center_cur:center_points_cur_frame ){
                int trac_index = 0;
                double distance = 0;
                double min_distance = 100000;
                for(auto center_prev:center_points_prev_frame){
                    distance =ComputeDistance( center_cur , center_prev );
                    //cout<<"distance"<
                    min_distance = distance < min_distance ? distance : min_distance ;
                    //cout<<"min_distance"<
                }
                if( min_distance < therehold ){
                        tracking_object_center.push_back(center_cur);//不同id在当前帧对应的点
                        
                        tractory.resize(tracking_object_center.size());
                        for(auto trac:tractory ){
                            trac.resize(100);
                            for( auto trac1:trac ){
                                trac1.resize(2);
                            }
                        }
                        tractory[track_id].push_back(center_cur);
                        track_id ++;
                        trac_index ++;
                    }
            }
            cout<<"第二帧"<<endl;
            continue;
        }
       /* if( count <= 7 ) {
            center_points_prev_frame.assign(center_points_cur_frame.begin(),center_points_cur_frame.end());//赋值
           cout<<"size "<=8 ){
            for(auto center_cur:center_points_cur_frame ){
                double distance = 0;
                double min_distance = 100000;
                for(auto center_prev:center_points_prev_frame){
                    distance =ComputeDistance( center_cur , center_prev );
                    cout<<"distance"<
        //开始第二帧后的匹配 当前帧中的点与上一帧的点进行匹配,匹配成功则继承id
        cout<<" cnt "<<count<<"  cur_num " <<center_points_cur_frame.size()<<endl;
        for(int object_id = 0; object_id < tracking_object_center.size();object_id ++){
            double distance = 0;
            double min_distance = 100000;
            vector<double> temp;
            int temp_index = 0;
            bool object_exist = false;
            
            for( int i = 0; i < center_points_cur_frame.size(); i++ ){
                if(tracking_object_center[object_id][0]==-1) continue;
                distance = ComputeDistance(tracking_object_center[object_id] , center_points_cur_frame[i]);
                if( distance < min_distance ){
                    min_distance = distance < min_distance ? distance : min_distance ;
                    temp = center_points_cur_frame[i];
                    temp_index = i;
                }
                
            }
            //cout<<"distance "<
            if( min_distance < therehold ){
                object_exist = true;
                
                /*Point p1= Point(tracking_object_center[object_id][0], tracking_object_center[object_id][1]);
                Point p2= Point(temp[0],temp[1]);
                line(frame,p1 , p2, Scalar(0, 255, 0), 1);*/

                tracking_object_center[object_id] = temp;
                tractory[object_id].push_back(temp);

                Scalar color = CV_RGB(255, 0, 0);
                Point pt= Point(temp[0], temp[1] - 10);
                putText(frame, "car"+num2str(object_id), pt, cv::FONT_HERSHEY_DUPLEX, 1.0f, color);

                center_points_cur_frame.erase(center_points_cur_frame.begin() + temp_index);
            }
            if( object_exist == false ){
                //cout<<"non "<
                tracking_object_center[object_id][0]=-1;
                tracking_object_center[object_id][1]=-1;
                tractory[object_id].clear();
                //cout<<" yes "<
            }
        }
       for( auto center_cur:center_points_cur_frame ){
            tracking_object_center.push_back(center_cur);
            tractory.resize(tracking_object_center.size());
            tractory[track_id].push_back(center_cur);
            Scalar color = CV_RGB(255, 0, 0);
            Point pt= Point(center_cur[0], center_cur[1] - 10);
            putText(frame, "car"+num2str(track_id), pt, cv::FONT_HERSHEY_DUPLEX, 1.0f, color);


            track_id ++;
        }
        //cout<<" center_size "<< tracking_object_center.size()<<" "<

        //加文本
        /*for(size_t i=0; i < tracking_object_center.size();i++){
            cout<< "huizhi"<
        string text;
		for (size_t i = 0; i < contours.size(); i++)
		{
			if (contourArea(contours[i]) > 3000)
			{
				rectangle(frame, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 2, 8, 0);
				Point pt = Point(boundRect[i].x, boundRect[i].y + boundRect[i].height + 15);
				Point pt1 = Point(boundRect[i].x, boundRect[i].y - 10);
				Point center = Point(boundRect[i].x + (boundRect[i].width / 2), boundRect[i].y + (boundRect[i].height / 2));
				//cv::circle(frame, center, 8, Scalar(0, 0, 255), -1, 1, 0);
				Scalar color = CV_RGB(255, 0, 0);
				text = num2str(boundRect[i].width) + "*" + num2str(boundRect[i].height);
				//putText(frame, "people", pt, cv::FONT_HERSHEY_DUPLEX, 1.0f, color);
				putText(frame, text, pt1, cv::FONT_HERSHEY_DUPLEX, 1.0f, color);

	

			}
		}
		//画轨迹
        for( auto trac:tractory ){
           // cout<<" trac "<
            for(size_t i = 1; i < trac.size(); i++){
               // cout<<" "<
                Point p1 ,p2;
                p1.x = trac[i][0];
                p1.y = trac[i][1];
                p2.x = trac[i-1][0];
                p2.y = trac[i-1][1];
                line(frame,p1,p2,Scalar(0, 255, 0),4);
            }
        }
        
        imshow("Video", frame);
        //waitKey(0);
    }
    return 0;

}

你可能感兴趣的:(c++,计算机视觉,opencv)