Opencv 2フレーム差分法により、動きターゲットと抽出プロファイルを検出する。
Opencv学習の二フレーム差分運動目標検出とアウトライン抽出は、以下の通りです。
コードはネットから抜粋して勉強しています。注釈をたくさんつけています。まるで本を読みながらメモを取るように、満足できるような感じがします。Let's do this
改善すべきところはあります。
①映像の処理速度が遅いため、映像の処理速度は動画の正常再生速度の2分の1しかない。
②歩行者の測定に対して、赤い枠が不安定であり、歩行者全体を枠ではなく、人のいくつかの異なる部分をそれぞれ枠で囲んでいることが多いorz。
③二つの物体が少し重なったら、重なりの物体を一つの物体として囲みます。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。
コードはネットから抜粋して勉強しています。注釈をたくさんつけています。まるで本を読みながらメモを取るように、満足できるような感じがします。Let's do this
#include "highgui.h"
#include "cv.h"
#include "stdio.h"
#include <time.h>
#include <math.h>
#include <string.h>
const double MHI_DURATION=0.1;// 0.1s
const double MAX_TIME_DELTA=0.5// 0.5s
const double MIN_TIME_DELTA=0.05;// 0.05s
const int N=3;
const int CONTOUR_MAX_AERA=16;
/* */
IplImage **buf=0;
int last=0;
/* */
IplImage* mhi=0;// mhi
CvConnectedComp* cur_comp,mincomp;
/*typedef struct CvConnectedComp
{
double area; //
CvScalar value; //
CvRect rect; //
CvSeq * contour; //
};*/
/* */
CvMemStorage* storage;
/* , , 0 , x、y */
CvPoint pt[4];
/* */
int nCurFrameIndex=0;
/* */
/*img- ;dst- */
void update(IplImage *img,IplImage *dst,int diff_threshold)
{
/* , */
double timestamp=clock()/100;
/* , size */
CvSize size=cvSize(img->width,img->height);
/* */
int i,idx1,idx2;
/* , nimg */
IplImage* nimg;
/* - -!*/
IplImage* pyr=cvCreateImage(cvSize((size.width&-2)/2,(size.height&-2)/2),8,1);
/* */
CvMemStorage* stor;
/* seq*/
CvSeq* seq;
/* */
/* , ( ?)*/
if(!mhi||mhi->width!=size.width||mhi->height!=size.height)
{
/* buf , buf */
if(buf==0)
{
/*N=3*/
buf=(IplImage**)malloc(N*sizeof(buf[0]));
/* s ch ASCII , :memset(void *s,char ch,unsigned n)。 buf */
memset(buf,0,N*sizeof(buf[0]));
}
/* buf , buf */
for(i=0;i<N;i++)
{
cvReleaseImage(&buf[i]);
buf[i]=cvCreateImage(size,IPL_DEPTH_8U,1);
cvZero(buf[i]);
}
/* mhi*/
cvReleaseImage(&mhi);
mhi=cvCreateImage(size,IPL_DEPTH_32F,1);
cvZero(mhi);
}
/* , buf */
cvCvtColor(img,buf[last],CV_BGR2GRAY);
/* , buf[idx1] ,buf[idx2] */
idx1=last;
idx2=(last+1)%N;
last=idx2;
/* , cvAbsDiff */
nimg=buf[idx2];
cvAbsDiff(buf[idx1],buf[idx2],nimg);
/* , */
cvThreshold(nimg,nimg,50,255,CV_THRESH_BINARY);
/* */
cvUpdateMotionHistory(nimg,mhi,timestamp,MHI_DURATION);
cvConvert(mhi,dst);
/* ,
cvPyrDown Gaussian , ,
cvDialate ,
cvPyrUp Gaussian , , */
cvSmooth(dst,dst,CV_MEDIAN,3,0,0,0);
cvPyrDown(dst,pyr,CV_GAUSSIAN_5x5);
cvDilate(pyr,pyr,0,1);
cvPyrUp(pyr,dst,CV_GAUSSIAN_5x5);
/* */
stor=cvCreateMemStorage(0);
seq=cvCreateSeq(CV_SEQ_ELTYPE_POINT,//
sizeof(CvSeq),// ; sizeof(CvSeq)
/* , 。 ( seq_flags ) , , , CV_SEQ_ELTYPE_POINT , elem_size sizeof(CvPoint)。
*/
sizeof(CvPoint),
stor);//
/* */
cvFindContours(dst,//
stor,//
&seq,// , 。
sizeof(CvContour),
CV_RETR_EXTERNAL,//mode:EXTERNAL――
CV_CHAIN_APPROX_NONE,// , - -
cvPoint(0,0));
/* CONTOUR */
/* seq */
for(;seq;seq=seq->h_next)
{
/* , rect x、y , */
CvRect r=((CvContour*)cont)->rect;// ?
/* , ; */
if((r.height*r.width>CONTOUR_MAX_AERA)&&(r.height*r.width>2560))
{
/*cvRectangle , */
cvRectangle(img,//
cvPoint(r.x,r.y),//
cvPoint(r.x + r.width, r.y + r.height),//
CV_RGB(255,0,0),//
1,//
CV_AA,//
0); //
}
}
/* , */
cvReleaseMemStorage(&stor);
cvReleaseImage(&pyr);
}
/ , /
int main(int argc,char**argv)
{
IplImage *motion=0;
CvCapture *capture=0;
/* */
capture=cvCaptureFromFile("D:\\ \\01.mp4");
if(capture)
{
cvNamedWindow("Motion",1);
for(;;)
{
IplImage *image;
/* cvGrabFrame */
if(!cvGrabFrame(capture))
break;
/* cvRetrieveFrame cvGrabFrame */
image=cvRetrieveFrame(capture);
if(image)
{
/* motion , 。 motion */
if(!motion)
{
motion=cvCreateImage(cvSize(image->width,image->height),8,1);
cvZero(motion);
/* */
motion->origin=image->origin;
}
}
/* , motion , */
update(image,motion,10);
/* */
cvShowImage("Motion",image);
/*10ms , */
if(cvWaitKey(10)>=0)
break;
}
/* for , */
cvReleaseCapture(&capture);
cvDestroyWindow("Motion");
}
return 0;
}
テストを経て、このプログラムは正常に検出され、赤い枠で移動する車両と歩行者を囲むことができます。改善すべきところはあります。
①映像の処理速度が遅いため、映像の処理速度は動画の正常再生速度の2分の1しかない。
②歩行者の測定に対して、赤い枠が不安定であり、歩行者全体を枠ではなく、人のいくつかの異なる部分をそれぞれ枠で囲んでいることが多いorz。
③二つの物体が少し重なったら、重なりの物体を一つの物体として囲みます。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。