场景

    车辆通过帧间差分,捕获到轮廓的线条,而大部分的线条是不连续的,无法链接成一个矩形的大致区域,通过最小矩形获取到的区域,可能仅仅是车辆的一部分,可能是车牌,也可能是车顶,甚至可能是车的镜头,提出了两种解决方案:

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 p_w_picpathContours=Mat::zeros(frameDet.size(),CV_8UC1); //最小外接矩形画布 

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

    {         

      //绘制轮廓  

      drawContours(p_w_picpathContours,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(p_w_picpathContours,P[j],P[(j+1)%4],Scalar(255, 0, 0),2);  

      }  

    }  

    imshow("MinAreaRect",p_w_picpathContours); 

    waitKey(1000);

  }

  return 0;

}