• 36、【opencv入门】运动物体检测(2)


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

     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 }
  • 相关阅读:
    新概念英语(第一册)Lesson 1
    第七篇、Python之模块/包
    解压序列
    eval函数
    python--magic module 文件类型识别
    MIME_type
    彻底删除git中的文件(包括历史提交记录)
    for循环与range()函数
    Linux 内核的 Makefile
    Python module ---- abc
  • 原文地址:https://www.cnblogs.com/Long-w/p/9669867.html
Copyright © 2020-2023  润新知