初学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
显示窗口的显示可能有些卡,视屏中没闪一次就是手进入一次后离开