您的位置:首页 > 运维架构

opencv程序十九:基于帧间差分法的区域目标入侵检测

2014-10-19 15:34 501 查看
运行程序在原图像上画个入侵检测的方框,有运动目标进入方框产生报警,并将入侵时的帧保存为视频

程序如下:

// 26RuQinDetection_BaseTwoDiff.cpp : 定义控制台应用程序的入口点。
// 区域入侵检测,基于两帧差分法

#include "stdafx.h"
#include <cv.h>  
#include <cxcore.h>  
#include <highgui.h>  
//CAM定义用摄像头获得视频else文件
//#define CAM 

int apos=30;
CvRect box;
bool Drawing=false;
bool out=false;
int xx1,xx2,yy1,yy2;
int n=0;
CvVideoWriter* writer;//保存视频
CvFont font;  //字体

void DrawRect(IplImage*img,CvRect rect)
{
	xx1=box.x;
	xx2=box.x +box.width ;
	yy1=box.y ;
	yy2=box.y +box.height ;
    cvRectangle(img,cvPoint(box.x,box.y),cvPoint(box.x+box.width,box.y+box.height),cvScalar(0x00,0xff,0x00),2);

}  
//实现对窗口Window_Name上的对象param添加鼠标响应操作
void my_mouse_callback(int event,int x,int y,int flags,void* param)
{
	IplImage*img=(IplImage*)param;
	switch(event)
	{
		case CV_EVENT_MOUSEMOVE:
		{
			if(Drawing)
			{
			box.width=x-box.x;
			box.height=y-box.y;
			}
		}
		break;
		
		case CV_EVENT_LBUTTONDOWN:
		{
			Drawing=true;
			box=cvRect(x,y,0,0);
		}
		break;

		case CV_EVENT_LBUTTONUP:
		{
			Drawing=false;
			if (box.width<0)
			{
				box.x+=box.width;
				box.width*=-1;
			}
			if (box.height<0)
			{
				box.y+=box.height;
				box.height*=-1;
			}
			out=true;
			DrawRect(img,box);

		}
		break;
		
	}
}

void on_trackbar(int pos)  
{  
        apos=pos;   
}    
  
int main( int argc, char** argv )  
{  
    //声明IplImage指针  
    IplImage* pFrame = NULL; //原始视频帧  
    IplImage* pFrImg = NULL; //提取的前景图像,即运动目标  
    IplImage* pBkImg = NULL; //背景图像 
  
    CvMat* pFrameMat = NULL; //原始视频矩阵 
    CvMat* pFrMat = NULL;    //前景矩阵
    CvMat* pBkMat = NULL;    //背景矩阵
  
    CvCapture* pCapture = NULL;  
    //帧数
    int nFrmNum = 0;  
	box=cvRect(0,0,-1,-1);
	CvScalar s;
	int i, j;
	cvInitFont(&font, CV_FONT_HERSHEY_COMPLEX, 1.0, 1.0, 0, 2, 8);
    //创建窗口  
    cvNamedWindow("video", 1);  
    //cvNamedWindow("background",1);  
    cvNamedWindow("foreground",1);  
    //使窗口有序排列  
    cvMoveWindow("video", 30, 0);  
    //cvMoveWindow("background", 360, 0);  
    cvMoveWindow("foreground", 690, 0);  
    // 滑动条          
    //int nThreshold = 30;        
    cvCreateTrackbar("阀值", "foreground", &apos, 100, on_trackbar);
	
#ifdef CAM
    if( !(pCapture = cvCaptureFromCAM(0)))  
    {  
        //pCapture = cvCaptureFromCAM(-1))  
        fprintf(stderr, "Can not open CAM .\n");  
        return -2;  
    }  
#else
	char *filename="../../0VideoSource/zjk_out.avi";
	if( !(pCapture = cvCaptureFrom***I(filename)))  
    {  
        //pCapture = cvCaptureFromCAM(-1))  
        fprintf(stderr, "Can not open file %s.\n",filename);  
        return -2;  
    }    
#endif
	pFrame = cvQueryFrame( pCapture );
	IplImage*temp1=cvCloneImage(pFrame);
	cvSetMouseCallback("video",my_mouse_callback,(void*)pFrame);
	while(out==false)
	{
		cvCopyImage(pFrame,temp1);
		if(Drawing)
			DrawRect(temp1,box);
		cvShowImage("video",temp1);
		if(cvWaitKey(100)==27)
			break;
	}
	printf("%d,%d,%d,%d,",xx1,xx2,yy1,yy2);
	//创建视频
	writer = cvCreateVideoWriter( "zjk_out.avi", CV_FOURCC('M','J','P','G'), 27, cvSize(pFrame->width, pFrame->height));
	//逐帧读取视频  
    while(pFrame = cvQueryFrame( pCapture ))  
    {  
        nFrmNum++;  
		
		n=0;
        //如果是第一帧,需要申请内存,并初始化  
        if(nFrmNum == 1)  
        {  
            pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);  
            pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);  
  
            pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);  
            pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);  
            pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);  
  
            //转化成单通道图像再处理  
            cvCvtColor(pFrame, pBkImg, CV_BGR2GRAY); //第一帧作为背景了 
            //cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY); // 
			//转换成矩阵
            cvConvert(pBkImg, pFrameMat);  //虽然没用,相当于给矩阵赋了初值
            cvConvert(pBkImg, pFrMat);	   //虽然没用,相当于给矩阵赋了初值
            cvConvert(pBkImg, pBkMat);  
        }  
        else  
        {  
            cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);  
            cvConvert(pFrImg, pFrameMat);  
            //高斯滤波先,以平滑图像  
            //cvSmooth(pFrameMat, pFrameMat, CV_GAUSSIAN, 3, 0, 0);  
  
            //当前帧跟背景图相减 计算两个数组差的绝对值 
            cvAbsDiff(pFrameMat, pBkMat, pFrMat);  
			
            //二值化前景图  
            cvThreshold(pFrMat, pFrImg, apos, 255.0, CV_THRESH_BINARY);  
			
            //进行形态学滤波,去掉噪音  只有摄像头时候会用
			#ifdef CAM
			cvErode(pFrImg, pFrImg, 0, 1);  
            cvDilate(pFrImg, pFrImg, 0, 1);  
			/* cvDilate(pFrImg, pFrImg, 0, 1);
			cvErode(pFrImg, pFrImg, 0, 1);*/  
			#endif
            //更新背景  
            //cvRunningAvg(pFrameMat, pBkMat, 0.003, 0);  
            //将背景转化为图像格式,用以显示  
            //cvConvert(pBkMat, pBkImg);  
			cvCopy(pFrameMat,pBkMat,NULL);
			//pBkMat=pFrameMat;
            //显示图像  
			for(j = xx1; j < xx2; j++)	
				for(i = yy1; i < yy2; i++)
				{ 
					s = cvGet2D(pFrImg,i,j);
					if (s.val[0]==0xff)//0xff为白色的
					{
						n++;
					}
				}
			printf("n=%d\n",n);
			//没有目标入侵
			if(n<=50)
			{
				//在原图像上画框
				cvRectangle(pFrame,cvPoint(box.x,box.y),cvPoint(box.x+box.width,box.y+box.height),cvScalar(0x00,0xff,0x00),2);
				//在二值化前景图上画框
				cvRectangle(pFrImg,cvPoint(box.x,box.y),cvPoint(box.x+box.width,box.y+box.height),cvScalar(0xff,0xff,0xff),2);
				
			}
			else //有目标入侵
			{
				//在原图像上报警并保存视频
				cvRectangle(pFrame,cvPoint(box.x,box.y),cvPoint(box.x+box.width,box.y+box.height),cvScalar(0x00,0x00,0xff),2);
				cvPutText(pFrame, "warning!", cvPoint(0,20), &font, CV_RGB(255,0,0));
				cvWriteFrame(writer, pFrame);//将图像写入视频
				//在二值化前景图上报警
				cvRectangle(pFrImg,cvPoint(box.x,box.y),cvPoint(box.x+box.width,box.y+box.height),cvScalar(0xff,0xff,0xff),2);
				cvPutText(pFrImg, "warning!", cvPoint(0,20), &font, CV_RGB(255,255,255));
				
			}
			
            cvShowImage("video", pFrame);  
            //cvShowImage("background", pBkImg);  
            cvShowImage("foreground", pFrImg);  
			
            //如果有按键事件,则跳出循环  
            //此等待也为cvShowImage函数提供时间完成显示  
            //等待时间可以根据CPU速度调整  
            if( cvWaitKey(100) >= 0 )  
            {  
                printf("into wait if");
				//break;  
            }  
			
        }  
    }  
    cvWaitKey();  
  
    //销毁窗口  
    cvDestroyWindow("video");  
    //cvDestroyWindow("background");  
    cvDestroyWindow("foreground");  
  
    //释放图像和矩阵  
    cvReleaseImage(&pFrImg);  
    cvReleaseImage(&pBkImg);  
  
    cvReleaseMat(&pFrameMat);  
    cvReleaseMat(&pFrMat);  
    cvReleaseMat(&pBkMat);  
  
    cvReleaseCapture(&pCapture);  
	cvReleaseVideoWriter(&writer);
    return 0;  
}


结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: