天天看點

膨脹處理提取車輛的大緻輪廓

場景

    車輛通過幀間差分,捕獲到輪廓的線條,而大部分的線條是不連續的,無法連結成一個矩形的大緻區域,通過最小矩形擷取到的區域,可能僅僅是車輛的一部分,可能是車牌,也可能是車頂,甚至可能是車的鏡頭,提出了兩種解決方案:

1)嘗試合并兩個相近的區域,然後找到一個比較大的矩形

2)利用膨脹的方法,對相鄰的區域進行合并,效果還是可以的

代碼

#include "opencv2/highgui/highgui.hpp"

#include "opencv2/imgproc/imgproc.hpp"

#include <vector>

using namespace cv;

using namespace std;

int main(int argc,char *argv[])

{

  VideoCapture videoCap("E:/smoky-cars/positive/大慶東路與水機路交叉口(東北)_冀BU0157_02_141502_01_3_50.wh264");

  if(!videoCap.isOpened())

  {

    return -1;

  }

  double videoFPS=videoCap.get(CV_CAP_PROP_FPS);  //擷取幀率

  double videoPause=1000/videoFPS;

  Mat framePrePre; //上上一幀

  Mat framePre; //上一幀

  Mat frameNow; //目前幀

  Mat frameDet; //運動物體

  videoCap>>framePrePre;

  videoCap>>framePre;

  cvtColor(framePrePre,framePrePre,CV_RGB2GRAY);

  cvtColor(framePre,framePre,CV_RGB2GRAY);

  int save=0;

  while(true)

    videoCap>>frameNow;

    if(frameNow.empty()||waitKey(videoPause)==27)

    {

      break;

    }

    cvtColor(frameNow,frameNow,CV_RGB2GRAY);

    Mat Det1;

    Mat Det2;

    absdiff(framePrePre,framePre,Det1);  //幀差1

    absdiff(framePre,frameNow,Det2);     //幀差2

    threshold(Det1,Det1,0,255,CV_THRESH_OTSU);  //自适應門檻值化

    threshold(Det2,Det2,0,255,CV_THRESH_OTSU);

    Mat element=getStructuringElement(0,Size(3,3));  //膨脹核

    dilate(Det1,Det1,element);    //膨脹

    dilate(Det2,Det2,element);

    bitwise_and(Det1,Det2,frameDet);

    framePrePre=framePre;

    framePre=frameNow;

    imshow("Video",frameNow);

    int dilation_type;

    int dilation_elem = 0;

    int dilation_size = 10;

    if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; }

    else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; }

    else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }

    Mat dielem = getStructuringElement( dilation_type,

      Size( 2*dilation_size + 1, 2*dilation_size+1 ),

      Point( dilation_size, dilation_size ) );

    ///膨脹操作

    dilate( frameDet, frameDet, dielem );

    imshow("Detection",frameDet);

    //尋找最外層輪廓  

    vector<vector<Point>> contours;  

    vector<Vec4i> hierarchy;  

    findContours(frameDet, contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_NONE,Point()); 

    Mat imageContours=Mat::zeros(frameDet.size(),CV_8UC1); //最小外接矩形畫布 

    for(int i=0;i<contours.size();i++)  

    {         

      //繪制輪廓  

      drawContours(imageContours,contours,i,Scalar(255, 0, 0),1,8,hierarchy);  

      //繪制輪廓的最小外結矩形  

      RotatedRect rect=minAreaRect(contours[i]);  

      Point2f P[4];  

      rect.points(P);  

      for(int j=0;j<=3;j++)  

      {  

        line(imageContours,P[j],P[(j+1)%4],Scalar(255, 0, 0),2);  

      }  

    }  

    imshow("MinAreaRect",imageContours); 

    waitKey(1000);

  return 0;

}

    本文轉自fengyuzaitu 51CTO部落格,原文連結:http://blog.51cto.com/fengyuzaitu/1905881,如需轉載請自行聯系原作者

繼續閱讀