初學opencv,這是我做的第一個小項目,其實原理很簡單,我就貼出來與大家分享下,希望能對新手有些幫助,但是這個小項目還不是很成熟,希望大神們可以踊躍的提出建議。
這個項目其實和運動物體的檢測很相似,只是在其基礎上做了一些改進,具體的步驟:
一。取第一幀圖像作爲背景圖
二.取後來的每一幀與第一幀進行差值運算得到差分圖,對差值圖進行閾值處理,
三。調用求二值圖像輪廓的函數對差值圖求輪廓,如果輪廓數大於1,則有物體進入,計數加一,但是在程序中要進入一個循環,避免物體進入後還沒離開造成的不斷計數
具體的程序實現:
/************************************************************
定義窗口
**************************************************************/
cvNamedWindow("haiyingyang" , 1);
/*******************************************88
聲明定義程序中所需要的數據結構以及一些函數所需要的參數
****************************************************************/
CvCapture *capture = 0;
IplImage *pbkimage = 0;
int flow = 0;
int number = 1;
int contour_number;
capture = cvCaptureFromCAM(0);
IplImage * image = 0;
IplImage *pfrimage = 0;
CvMat *pfrmat;
CvMat *pframemat;
CvMemStorage *storage = cvCreateMemStorage(0);
CvSeq *cont = 0;
CvMat *pbkmat;
/**************************************************************
程序主體部分,完成計數功能
******************************************************/
capture = cvCaptureFromCAM(0);
/********************************************************************************
用以後的幀不斷的減去前一幀,對得到的差值圖進行輪廓提取,如果有輪廓則有物體進入
************************************************************************************/
for(; ;)
{
image= cvQueryFrame(capture);
int n =1;
if(number == 1)
{
/************************************************************
下面的if語句取首幀圖像作爲背景圖
***************************************************************/
pfrimage = cvCreateImage(cvGetSize(image) , IPL_DEPTH_8U , 1);
pbkimage = cvCreateImage(cvGetSize(image) , IPL_DEPTH_8U , 1);
pfrmat = cvCreateMat(image->height , image->width , CV_32FC1);
pbkmat = cvCreateMat(image->height , image->width , CV_32FC1);
pframemat = cvCreateMat(image->height , image->width , CV_32FC1);
cvCvtColor(image , pfrimage , CV_BGR2GRAY);
cvCvtColor(image , pbkimage , CV_BGR2GRAY);
cvConvert(pbkimage , pbkmat);
number = 0;
}
else
{
CvMemStorage *storage = cvCreateMemStorage(0);
CvSeq *cont = 0;
image = cvQueryFrame(capture);
cvShowImage("haiyingyang" , image);
cvCvtColor(image , pfrimage , CV_BGR2GRAY);
cvConvert(pfrimage , pframemat);
cvAbsDiff(pframemat , pbkmat , pfrmat);
cvThreshold(pfrmat , pfrimage ,180 , 255 , CV_THRESH_BINARY);
contour_number = cvFindContours(pfrimage , storage , &cont , sizeof(CvContour) , CV_RETR_CCOMP , CV_CHAIN_APPROX_SIMPLE);
while(contour_number)
{
if(n == 1)
{
flow++;
printf("current flow number:%d/n" , flow);
n = 0;
}
image = cvQueryFrame(capture);
cvShowImage("haiyingyang" , image);
cvCvtColor(image , pfrimage , CV_BGR2GRAY);
cvConvert(pfrimage , pframemat);
cvAbsDiff(pframemat , pbkmat , pfrmat);
cvThreshold(pfrmat , pfrimage , 180 , 255 , CV_THRESH_BINARY);
contour_number = cvFindContours(pfrimage , storage , &cont , sizeof(CvContour) , CV_RETR_CCOMP , CV_CHAIN_APPROX_SIMPLE);
}
}
if(cvWaitKey(2) >= 0)
{
cvReleaseMemStorage(&storage);
cvReleaseImage(&image);
cvReleaseImage(&pfrimage);
cvReleaseImage(&pbkimage);
break;
}
}
return 0;
演示效果網址:http://v.youku.com/v_show/id_XMjkxMDAyOTc2.html
顯示窗口的顯示可能有些卡,視屏中沒閃一次就是手進入一次後離開