场景

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

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.wh364");

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;

}