一、运动物体轮廓椭圆拟合及中心

1 #include "opencv2/opencv.hpp"
 2 #include<iostream>
 3 
 4 using namespace std;
 5 using namespace cv;
 6 
 7 Mat MoveDetect(Mat frame1, Mat frame2)
 8 {
 9     Mat result = frame2.clone();
10     Mat gray1, gray2;
11     cvtColor(frame1, gray1, CV_BGR2GRAY);
12     cvtColor(frame2, gray2, CV_BGR2GRAY);
13 
14     Mat diff;
15     absdiff(gray1, gray2, diff);
16     imshow("absdiss", diff);
17     threshold(diff, diff, 45, 255, CV_THRESH_BINARY);
18     imshow("threshold", diff);
19  
20     Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
21     Mat element2 = getStructuringElement(MORPH_RECT, Size(25, 25));
22     erode(diff, diff, element);
23     imshow("erode", diff);
24  
25     dilate(diff, diff, element2);
26     imshow("dilate", diff);
27 
28     vector<vector<Point>> contours;
29     vector<Vec4i> hierarcy;
30     //画椭圆及中心
31     findContours(diff, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
32     cout<<"num="<<contours.size()<<endl;
33     vector<RotatedRect> box(contours.size());
34     for(int i=0; i<contours.size(); i++)
35     {
36         box[i] = fitEllipse(Mat(contours[i]));
37         ellipse(result, box[i], Scalar(0, 255, 0), 2, 8);    
38         circle(result, box[i].center, 3, Scalar(0, 0, 255), -1, 8);
39     }    
40     return result;    
41 }
42 int main()
43 {     
44     VideoCapture cap("E://man.avi");
45     if(!cap.isOpened()) //检查打开是否成功
46          return;
47     Mat frame;
48     Mat result;
49     Mat background;
50     int count=0;
51     while(1)
52     {
53         cap>>frame;
54         if(frame.empty())
55             break;
56         else{            
57             count++;
58             if(count==1)
59                  background = frame.clone(); //提取第一帧为背景帧
60             imshow("video", frame);
61             result = MoveDetect(background, frame);
62             imshow("result", result);
63             if(waitKey(50)==27)
64                break;
65         }
66     }
67     cap.release();  
68     return 0;   
69 }

二、滤波方法去除噪声

1、中值滤波去除噪声

1     //二值化后使用中值滤波+膨胀
2   Mat element = getStructuringElement(MORPH_RECT, Size(11, 11));
3     medianBlur(diff, diff, 5);//中值滤波
4     imshow("medianBlur", diff);
5     dilate(diff, diff, element);
6     imshow("dilate", diff);

2、均值滤波去除噪声

1 #include "opencv2/opencv.hpp"
 2 #include<iostream>
 3 
 4 using namespace std;
 5 using namespace cv;
 6 
 7 //int to string helper function
 8 string intToString(int number)
 9 {
10     stringstream ss;
11     ss << number;
12     return ss.str();
13 }
14 
15 Mat MoveDetect(Mat background, Mat img)
16 {
17     Mat result = img.clone();
18     Mat gray1, gray2;
19     cvtColor(background, gray1, CV_BGR2GRAY);
20     cvtColor(img, gray2, CV_BGR2GRAY);
21 
22     Mat diff;
23     absdiff(gray1, gray2, diff);
24     threshold(diff, diff, 20, 255, CV_THRESH_BINARY);
25     imshow("threshold", diff);
26     blur(diff, diff, Size(10, 10));//均值滤波
27     imshow("blur", diff);
28 
29     vector<vector<Point>> contours;  
30     vector<Vec4i> hierarcy;
31     findContours(diff, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓
32     vector<Rect> boundRect(contours.size()); //定义外接矩形集合
33     //drawContours(img2, contours, -1, Scalar(0, 0, 255), 1, 8);  //绘制轮廓
34     int x0=0, y0=0, w0=0, h0=0;
35     for(int i=0; i<contours.size(); i++)
36     {
37         boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形
38     
39         x0 = boundRect[i].x;  //获得第i个外接矩形的左上角的x坐标
40         y0 = boundRect[i].y; //获得第i个外接矩形的左上角的y坐标
41         w0 = boundRect[i].width; //获得第i个外接矩形的宽度
42         h0 = boundRect[i].height; //获得第i个外接矩形的高度
43         //rectangle(result, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形
44         circle(result, Point(x0+w0/2, y0+h0/2), 15, Scalar(0, 255, 0), 2, 8);
45         line(result, Point(x0+w0/2-15, y0+h0/2), Point(x0+w0/2+15, y0+h0/2), Scalar(0, 255, 0), 2, 8);
46         line(result, Point(x0+w0/2, y0+h0/2-10), Point(x0+w0/2, y0+h0/2+15), Scalar(0, 255, 0), 2, 8);
47         putText(result,"(" + intToString(x0+w0/2)+","+intToString(y0+h0/2)+")",Point(x0+w0/2+15, y0+h0/2), 1, 1,Scalar(255,0,0),2);
48     }
49     return result;
50 }
51 
52 int main()
53 {     
54     VideoCapture cap("E://ball.avi");
55     if(!cap.isOpened()) //检查打开是否成功
56          return;
57     Mat frame;
58     Mat result;
59     Mat background;
60     int count=0;
61     while(1)
62     {
63         cap>>frame;
64         if(frame.empty())
65             break;
66         else{            
67             count++;
68             if(count==1)
69                  background = frame.clone(); //提取第一帧为背景帧
70             imshow("video", frame);
71             result = MoveDetect(background, frame);
72             imshow("result", result);
73             if(waitKey(50)==27)
74                break;
75         }
76     }
77     cap.release();  
78     return 0;
79 }

三、轮廓筛选去除噪声

1     //其余代码相同
 2     int x0=0, y0=0, w0=0, h0=0;
 3     for(int i=0; i<contours.size(); i++)
 4     {
 5         boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形
 6         
 7         x0 = boundRect[i].x;  //获得第i个外接矩形的左上角的x坐标
 8         y0 = boundRect[i].y; //获得第i个外接矩形的左上角的y坐标
 9         w0 = boundRect[i].width; //获得第i个外接矩形的宽度
10         h0 = boundRect[i].height; //获得第i个外接矩形的高度
11         //筛选
12         if(w0>30 && h0>30)
13             rectangle(result, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形
14     }

四、运动轨迹绘制

1 #include "opencv2/opencv.hpp"
 2 #include<iostream>
 3 using namespace std;
 4 using namespace cv;
 5 
 6 Point center;
 7 Point fre_center;//存储前一帧中心坐标
 8 int num=0;
 9 vector<Point> points;
10 
11 Mat MoveDetect(Mat background, Mat img)
12 {
13     Mat result = img.clone();
14     Mat gray1, gray2;
15     cvtColor(background, gray1, CV_BGR2GRAY);
16     cvtColor(img, gray2, CV_BGR2GRAY);
17 
18     Mat diff;
19     absdiff(gray1, gray2, diff);
20     imshow("absdiss", diff);
21     threshold(diff, diff, 45, 255, CV_THRESH_BINARY);
22     imshow("threshold", diff);
23  
24     Mat element = getStructuringElement(MORPH_RECT, Size(1, 1));
25     Mat element2 = getStructuringElement(MORPH_RECT, Size(9, 9));
26     erode(diff, diff, element);
27     imshow("erode", diff);
28     dilate(diff, diff, element2);
29     imshow("dilate", diff);
30 
31     vector<vector<Point>> contours;  
32     vector<Vec4i> hierarcy;
33     findContours(diff, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓
34     vector<Rect> boundRect(contours.size()); //定义外接矩形集合
35     //drawContours(img2, contours, -1, Scalar(0, 0, 255), 1, 8);  //绘制轮廓
36     vector<RotatedRect> box(contours.size());
37     int x0=0, y0=0, w0=0, h0=0;
38     for(int i=0; i<contours.size(); i++)
39     {
40         boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形
41         
42         x0 = boundRect[i].x;  //获得第i个外接矩形的左上角的x坐标
43         y0 = boundRect[i].y; //获得第i个外接矩形的左上角的y坐标
44         w0 = boundRect[i].width; //获得第i个外接矩形的宽度
45         h0 = boundRect[i].height; //获得第i个外接矩形的高度
46         if(w0>30 && h0>30)//筛选长宽大于30的轮廓
47         {
48             num++;
49             //rectangle(result, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形
50             box[i] = fitEllipse(Mat(contours[i]));
51             ellipse(result, box[i], Scalar(255, 0, 0), 2, 8);            //椭圆轮廓
52             circle(result, box[i].center, 3, Scalar(0, 0, 255), -1, 8); //画中心
53             center = box[i].center;//当前帧的中心坐标
54             points.push_back(center);//中心塞进points向量集
55             if(num !=1)
56             {
57                 //line(result, fre_center, center, Scalar(255, 0, 0), 2, 8);
58                 for(int j=0; j<points.size()-1; j++)
59                     line(result, points[j], points[j+1], Scalar(0, 255, 0), 2, 8);
60             }
61             //fre_center = center;
62         }
63     }
64     return result;
65 }
66 
67 int main()
68 {     
69     VideoCapture cap("E://man.avi");
70     if(!cap.isOpened()) //检查打开是否成功
71          return;
72     Mat frame;
73     Mat background;
74     Mat result;
75     int count=0;
76     while(1)
77     {
78         cap>>frame;
79         if(!frame.empty())
80         {
81             count++;
82             if(count==1)
83                 background = frame.clone(); //提取第一帧为背景帧
84             imshow("video", frame);
85             result = MoveDetect(background, frame);
86             imshow("result", result);
87             if(waitKey(30)==27)
88                break;
89         }
90         else
91             break;
92     }
93     cap.release();  
94     return 0;
95 }

五、车辆数量检测

1.帧差法检测运动目标

2.预处理:a.转灰度图,绝对值做差  b.二值化,腐蚀,中值滤波,膨胀  c.查找轮廓,筛选轮廓,绘制外接矩形,计数,输出

1 #include "opencv2/opencv.hpp"
 2 #include<iostream>
 3 
 4 using namespace std;
 5 using namespace cv;
 6 
 7 int CarNum = 0;
 8 //int to string helper function
 9 string intToString(int number)
10 {
11     //this function has a number input and string output
12     stringstream ss;
13     ss << number;
14     return ss.str();
15 }
16 
17 Mat MoveDetect(Mat frame1, Mat frame2) {
18     Mat result = frame2.clone();
19     Mat gray1, gray2;
20     cvtColor(frame1, gray1, CV_BGR2GRAY);
21     cvtColor(frame2, gray2, CV_BGR2GRAY);
22 
23     Mat diff;
24     absdiff(gray1, gray2, diff);
25     //imshow("absdiss", diff);
26     threshold(diff, diff, 25, 255, CV_THRESH_BINARY);
27     imshow("threshold", diff);
28 
29     Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
30     Mat element2 = getStructuringElement(MORPH_RECT, Size(19, 19));
31     erode(diff, diff, element);
32     //imshow("erode", dst);
33     medianBlur(diff, diff, 3);
34     imshow("medianBlur", diff);
35     dilate(diff, diff, element2);
36     imshow("dilate", diff);
37 
38     vector<vector<Point>> contours;
39     vector<Vec4i> hierarcy;
40     findContours(diff, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));//查找轮廓
41     vector<vector<Point>>contours_poly(contours.size());
42     vector<Rect> boundRect(contours.size()); //定义外接矩形集合
43                                              //drawContours(img2, contours, -1, Scalar(0, 0, 255), 1, 8);  //绘制轮廓
44     int x0 = 0, y0 = 0, w0 = 0, h0 = 0;
45     for (int i = 0; i<contours.size(); i++)
46     {
47         approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);//对图像轮廓点进行多边形拟合:轮廓点组成的点集,输出的多边形点集,精度(即两个轮廓点之间的距离),输出多边形是否封闭
48         boundRect[i] = boundingRect(Mat(contours_poly[i]));
49         if (boundRect[i].width>55 && boundRect[i].width<180 && boundRect[i].height>55 && boundRect[i].height<180) {//轮廓筛选
50             x0 = boundRect[i].x;
51             y0 = boundRect[i].y;
52             w0 = boundRect[i].width;
53             h0 = boundRect[i].height;
54 
55             rectangle(result, Point(x0, y0), Point(x0 + w0, y0 + h0), Scalar(0, 255, 0), 2, 8, 0);
56             if ((y0 + h0 / 2 + 1) >= 138 && (y0 + h0 / 2 - 1) <= 142) {//经过这条线(区间),车辆数量+1
57                 CarNum++;
58             }
59         }
60         line(result, Point(0, 140), Point(568, 140), Scalar(0, 0, 255), 1, 8);//画红线
61         Point org(0, 35);
62         putText(result, "CarNum=" + intToString(CarNum), org, CV_FONT_HERSHEY_SIMPLEX, 0.8f, Scalar(0, 255, 0), 2);
63     }
64     return result;
65 }
66 
67 int main()
68 {
69     VideoCapture cap("E://2.avi");
70     if (!cap.isOpened()) //检查打开是否成功
71         return;
72     Mat frame;
73     Mat tmp;
74     Mat result;
75     int count = 0;
76     while (1)
77     {
78         cap >> frame;
79         if(frame.empty())//检查视频是否结束
80             break;
81         else{
82             count++;
83             if (count == 1)    
84                 result = MoveDetect(frame, frame);
85             else    result = MoveDetect(tmp, frame);
86             imshow("video", frame);
87             imshow("result", result);
88             tmp = frame.clone();
89             if (waitKey(20) == 27)        
90                 break;
91         }
92     }
93     cap.release();
94     return 0;
95 }