[OpenCv]简单摄像头监控Demo

最近发现一篇报道,十分好玩,有兴趣的可以点击下面的链接

公安部门的摄像头每天都拍到了啥?

然后就写了这个小视频或者摄像头监控Demo玩玩。

1.主要使用OpenCv

2.帧差法与Cascade相结合

      Demo主要利用帧差法(主要是CvSub和cvAbsDiff,感兴趣的同学可以搜搜)实现移动物体检测,后利用cascade分类器检测路人。十分简单。

1.第一步利用帧差法,做移动物体检测

bool MoveCheck(IplImage *PreImg,IplImage*Currnet,CvRect& rc)
{
	//cvNamedWindow("diff", CV_WINDOW_AUTOSIZE);
	vector<CvPoint2D32f> bPt;
	bPt.clear();
	int n = 0;
	if (PreImg->width != Currnet->width || PreImg->height != Currnet->height)
	{
		return false;
	}
	IplImage* bImage1 = nullptr;
	IplImage* bImage2 = nullptr;
	IplImage *dImage = nullptr;
	IplImage *bImage = nullptr;
//使用openmp 加快处理速度
#pragma omp  sections
	{
#pragma omp section
	 {
		 if (PreImg->nChannels = 3)
		 {
			 bImage1 = cvCreateImage(cvSize(PreImg->width, PreImg->height), 8, 1);
			 cvCvtColor(PreImg, bImage1, CV_BGR2GRAY);
		 }
		 else
		 {
			 bImage1 = cvCloneImage(PreImg);
		 }
		 cvSmooth(bImage1, bImage1);
		 bImage = cvCreateImage(cvSize(PreImg->width, PreImg->height), 8, 1);
	 }
#pragma omp section
	 {
		 if (Currnet->nChannels = 3)
		 {
			 bImage2 = cvCreateImage(cvSize(Currnet->width, Currnet->height), 8, 1);
			 cvCvtColor(Currnet, bImage2, CV_BGR2GRAY);
		 }
		 else
		 {
			 bImage2 = cvCloneImage(Currnet);
		 }
		 cvSmooth(bImage2, bImage2);
		 dImage = cvCreateImage(cvSize(PreImg->width, PreImg->height), 8, 1);
	 }
}

	int MinThre = 80;
	IplImage *rImage = cvCreateImage(cvSize(PreImg->width, PreImg->height), 8, 1);   
    //帧差法
	cvSub(bImage1, bImage2, bImage);
	cvAbsDiff(bImage1, bImage2, dImage);
    //加一个add 增强一下效果
	cvAdd(bImage, dImage, rImage);
	cvThreshold(rImage, rImage, 80, 255, CV_THRESH_BINARY);
	cvErode(rImage, rImage);
	IplConvKernel *pele = cvCreateStructuringElementEx(4,4,2,2,CV_SHAPE_ELLIPSE);
    //突出一下关机点
	cvDilate(rImage, rImage, pele);
	cvReleaseStructuringElement(&pele);

	//cvShowImage("diff", rImage);
	//cvWaitKey(10);
	
	CvMemStorage *pStorage = cvCreateMemStorage(0);
	CvSeq *pContour = nullptr;
	cvFindContours(rImage, pStorage, &pContour);

	for (CvSeq *bSeq = pContour; bSeq != NULL;bSeq=bSeq->h_next)
	{
		if (bSeq->total < 6)
		{
			continue;
		}
#pragma omp for
		for (int i = 0; i < bSeq->total;i++)
		{
			CvPoint bPt1 = *(CvPoint*)cvGetSeqElem(bSeq, i);
			bPt.push_back(cvPoint2D32f(bPt1.x, bPt1.y));
		}
	}
	if (bPt.size() > 0)
	{
		int minX, maxX, minY, maxY;
        //找最大的x和最小的x
		sort(bPt.begin(), bPt.end(), Max_x);
		maxX = (int)bPt.at(0).x;
		minX = (int)bPt.at(bPt.size() - 1).x;
        //找最大的y和最小的y
		sort(bPt.begin(), bPt.end(), Max_y);
		maxY = (int)bPt.at(0).y;
		minY = (int)bPt.at(bPt.size() - 1).y;

		rc.x = minX;
		rc.y = minY;
		rc.width = maxX - minX;
		rc.height = maxY - minY;
		if (rc.width < 5)
		{
			rc.width = 20;
		}
		if (rc.height < 5)
		{
			rc.height = 20;
		}
	}

	cvReleaseMemStorage(&pStorage);
	cvReleaseImage(&bImage1);
	cvReleaseImage(&bImage2);
	cvReleaseImage(&bImage);
	cvReleaseImage(&dImage);
	cvReleaseImage(&rImage);
	return true;
}

第二步,用CvHaarClassifierCascade做人体检测

int PeopleDetection(CvHaarClassifierCascade* body_Classifier, IplImage *src, CvRect *bRect)
{
	int num = -1;
	IplImage *cvtImage = cvCreateImage(cvSize(src->width, src->height), 8, 1);
	// = (CvHaarClassifierCascade*)cvLoad(faceCascadeFilename, 0, 0, 0);
	if (src->nChannels != 1)
	{
		cvCvtColor(src, cvtImage, CV_BGR2GRAY);
	}
	else
	{
		cvtImage = cvCloneImage(src);
	}
	cvCvtColor(src, cvtImage, CV_BGR2GRAY);
    //加快运算速度,图像缩小一半
	IplImage *ReImage = cvCreateImage(cvSize(src->width/2, src->height/2), 8, 1);
	cvResize(cvtImage, ReImage);
	CvMemStorage *pStorage = cvCreateMemStorage(0);
	const double scale_factore = 1.1f;
	const int flag = CV_HAAR_DO_CANNY_PRUNING;
	CvSeq *pSeq = cvHaarDetectObjects(ReImage, body_Classifier, pStorage, scale_factore, 3, flag, cvSize(20, 20));
	num = pSeq->total;
	for (int i = 0; i < (pSeq->total); i++)
	{
		bRect[i] = *(CvRect *)cvGetSeqElem(pSeq, i);
		bRect[i].x *= 2;
		bRect[i].y *= 2;
		bRect[i].width *= 2;
		bRect[i].height *= 2;

	}
	cvReleaseImage(&ReImage);
	cvReleaseImage(&cvtImage);
	cvReleaseMemStorage(&pStorage);
	return num;
}

然后,分类的效果很不理想老是会误检,不过只是一个demo,不影响

下面给出整个工程代码

// Demo.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <math.h>
#include "cv.h"  
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\objdetect\objdetect.hpp>
#include "opencv2/core/internal.hpp"
#include <string>
#include <fstream>
#include<windows.h>

using namespace std;
using namespace cv;

//定义路径
const char *faceCascadeFilename = "haarcascade_frontalface_alt_tree.xml";
const char* bodyCascadeFilename = "haarcascade_fullbody.xml";
const char* UpbodyCascadeFilename = "haarcascade_upperbody.xml";

#define  TEST 1
bool Max_x(CvPoint2D32f p1, CvPoint2D32f p2)
{
	return p1.x > p2.x;
}
bool Max_y(CvPoint2D32f p1, CvPoint2D32f p2)
{
	return  p1.y > p2.y;
}

int FaceDetection(CvHaarClassifierCascade* face_Classifier,IplImage *src, CvRect *bRect)
{
	int num = -1;
	IplImage *cvtImage =  cvCreateImage(cvSize(src->width, src->height), 8, 1);;
	// = (CvHaarClassifierCascade*)cvLoad(faceCascadeFilename, 0, 0, 0);
	if (src->nChannels != 1)
	{
		cvCvtColor(src, cvtImage, CV_BGR2GRAY);
	}
	else
	{
		cvtImage = cvCloneImage(src);
	}
	cvCvtColor(src, cvtImage, CV_BGR2GRAY);
	//整张脸
	CvMemStorage *pStorage = cvCreateMemStorage(0);
	const double scale_factore = 1.1f;
	const int flag = CV_HAAR_DO_CANNY_PRUNING;
	CvSeq *pSeq = cvHaarDetectObjects(cvtImage, face_Classifier, pStorage, scale_factore, 3, flag, cvSize(20, 20));
	num = pSeq->total;
	for (int i = 0; i < (pSeq->total); i++)
	{
		bRect[i] = *(CvRect *)cvGetSeqElem(pSeq, i);
	}

	cvReleaseImage(&cvtImage);
	cvReleaseMemStorage(&pStorage);
	return num;
}
int PeopleDetection(CvHaarClassifierCascade* body_Classifier, IplImage *src, CvRect *bRect)
{
	int num = -1;
	IplImage *cvtImage = cvCreateImage(cvSize(src->width, src->height), 8, 1);
	// = (CvHaarClassifierCascade*)cvLoad(faceCascadeFilename, 0, 0, 0);
	if (src->nChannels != 1)
	{
		cvCvtColor(src, cvtImage, CV_BGR2GRAY);
	}
	else
	{
		cvtImage = cvCloneImage(src);
	}
	cvCvtColor(src, cvtImage, CV_BGR2GRAY);
	IplImage *ReImage = cvCreateImage(cvSize(src->width/2, src->height/2), 8, 1);
	cvResize(cvtImage, ReImage);
	//整张脸
	CvMemStorage *pStorage = cvCreateMemStorage(0);
	const double scale_factore = 1.1f;
	const int flag = CV_HAAR_DO_CANNY_PRUNING;
	CvSeq *pSeq = cvHaarDetectObjects(ReImage, body_Classifier, pStorage, scale_factore, 3, flag, cvSize(20, 20));
	num = pSeq->total;
	for (int i = 0; i < (pSeq->total); i++)
	{
		bRect[i] = *(CvRect *)cvGetSeqElem(pSeq, i);
		bRect[i].x *= 2;
		bRect[i].y *= 2;
		bRect[i].width *= 2;
		bRect[i].height *= 2;

	}
	cvReleaseImage(&ReImage);
	cvReleaseImage(&cvtImage);
	cvReleaseMemStorage(&pStorage);
	return num;
}
int PeopleDetection(HOGDescriptor hog,IplImage *src, CvRect *bRect)
{
	IplImage *cvtImage = cvCreateImage(cvSize(src->width, src->height), 8, 1);;
	// = (CvHaarClassifierCascade*)cvLoad(faceCascadeFilename, 0, 0, 0);
	if (src->nChannels != 1)
	{
		cvCvtColor(src, cvtImage, CV_BGR2GRAY);
	}
	else
	{
		cvtImage = cvCloneImage(src);
	}
	int num = -1;
	vector<Rect> found;
	Mat bMat(cvtImage, true);
	hog.detectMultiScale(bMat, found, 0, Size(8, 8), Size(32, 32), 1.05, 2);
	if (found.size() == 0)
	{
		return num;
	}
	num = found.size();
	for (int i = 0; i < num;i++)
	{
		bRect[i].x = found.at(i).tl().x;
		bRect[i].y = found.at(i).tl().y;
		bRect[i].width = found.at(i).width;
		bRect[i].height = found.at(i).height;
	}
	cvReleaseImage(&cvtImage);
	return num;
}
bool MoveCheck(IplImage *PreImg,IplImage*Currnet,CvRect& rc)
{
	//cvNamedWindow("diff", CV_WINDOW_AUTOSIZE);
	vector<CvPoint2D32f> bPt;
	bPt.clear();
	int n = 0;
	if (PreImg->width != Currnet->width || PreImg->height != Currnet->height)
	{
		return false;
	}
	IplImage* bImage1 = nullptr;
	IplImage* bImage2 = nullptr;
	IplImage *dImage = nullptr;
	IplImage *bImage = nullptr;
#pragma omp  sections
	{
#pragma omp section
	 {
		 if (PreImg->nChannels = 3)
		 {
			 bImage1 = cvCreateImage(cvSize(PreImg->width, PreImg->height), 8, 1);
			 cvCvtColor(PreImg, bImage1, CV_BGR2GRAY);
		 }
		 else
		 {
			 bImage1 = cvCloneImage(PreImg);
		 }
		 cvSmooth(bImage1, bImage1);
		 bImage = cvCreateImage(cvSize(PreImg->width, PreImg->height), 8, 1);
	 }
#pragma omp section
	 {
		 if (Currnet->nChannels = 3)
		 {
			 bImage2 = cvCreateImage(cvSize(Currnet->width, Currnet->height), 8, 1);
			 cvCvtColor(Currnet, bImage2, CV_BGR2GRAY);
		 }
		 else
		 {
			 bImage2 = cvCloneImage(Currnet);
		 }
		 cvSmooth(bImage2, bImage2);
		 dImage = cvCreateImage(cvSize(PreImg->width, PreImg->height), 8, 1);
	 }
}

	int MinThre = 80;
	IplImage *rImage = cvCreateImage(cvSize(PreImg->width, PreImg->height), 8, 1);
	cvSub(bImage1, bImage2, bImage);
	cvAbsDiff(bImage1, bImage2, dImage);
	cvAdd(bImage, dImage, rImage);
	cvThreshold(rImage, rImage, 80, 255, CV_THRESH_BINARY);
	cvErode(rImage, rImage);
	IplConvKernel *pele = cvCreateStructuringElementEx(4,4,2,2,CV_SHAPE_ELLIPSE);
	cvDilate(rImage, rImage, pele);
	cvReleaseStructuringElement(&pele);

	//cvShowImage("diff", rImage);
	//cvWaitKey(10);
	
	CvMemStorage *pStorage = cvCreateMemStorage(0);
	CvSeq *pContour = nullptr;
	cvFindContours(rImage, pStorage, &pContour);

	for (CvSeq *bSeq = pContour; bSeq != NULL;bSeq=bSeq->h_next)
	{
		if (bSeq->total < 6)
		{
			continue;
		}
#pragma omp for
		for (int i = 0; i < bSeq->total;i++)
		{
			CvPoint bPt1 = *(CvPoint*)cvGetSeqElem(bSeq, i);
			bPt.push_back(cvPoint2D32f(bPt1.x, bPt1.y));
		}
	}
	if (bPt.size() > 0)
	{
		int minX, maxX, minY, maxY;
		sort(bPt.begin(), bPt.end(), Max_x);
		maxX = (int)bPt.at(0).x;
		minX = (int)bPt.at(bPt.size() - 1).x;
		sort(bPt.begin(), bPt.end(), Max_y);
		maxY = (int)bPt.at(0).y;
		minY = (int)bPt.at(bPt.size() - 1).y;

		rc.x = minX;
		rc.y = minY;
		rc.width = maxX - minX;
		rc.height = maxY - minY;
		if (rc.width < 5)
		{
			rc.width = 20;
		}
		if (rc.height < 5)
		{
			rc.height = 20;
		}
	}

	cvReleaseMemStorage(&pStorage);
	cvReleaseImage(&bImage1);
	cvReleaseImage(&bImage2);
	cvReleaseImage(&bImage);
	cvReleaseImage(&dImage);
	cvReleaseImage(&rImage);
	return true;
}
int main(int argc, _TCHAR* argv[])
{
	cvNamedWindow("frame", CV_WINDOW_AUTOSIZE);
	CvHaarClassifierCascade* face_Classifier = (CvHaarClassifierCascade*)cvLoad(faceCascadeFilename, 0, 0, 0);
	CvHaarClassifierCascade* body_Classifier = (CvHaarClassifierCascade*)cvLoad(bodyCascadeFilename, 0, 0, 0);
	CvHaarClassifierCascade* car_Classifier = (CvHaarClassifierCascade*)cvLoad("cascade1203_20.xml");
	//stop area;
	CvRect StopRect = cvRect(200, 100, 300, 300);
	HOGDescriptor hog;
	hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());
	CvRect bRect;
    //这部分可以换成摄像机
	CvCapture* capture = cvCreateFileCapture("vtest.avi");
	IplImage* PreFrame = nullptr;
	IplImage* CurrentImg = nullptr;
	IplImage* ShowImg = nullptr;
	int num = 0;
	while (true)
	{
		if (CurrentImg!=nullptr)
	    {
			cvReleaseImage(&CurrentImg);
	    }
		CurrentImg = cvCloneImage(cvQueryFrame(capture));
		if (CurrentImg==NULL)
		{
			break;
		}
		if (ShowImg != nullptr)
		{
			cvReleaseImage(&ShowImg);
		}
		ShowImg = cvCloneImage(CurrentImg);
	    if (num==0)
	    {
			if (PreFrame != nullptr)
			{
				cvReleaseImage(&PreFrame);
			}
			PreFrame = cvCloneImage(CurrentImg);
			num = 1;
			continue;
	    }
		CvPoint2D32f Pt[1000];
		cvRectangle(ShowImg, cvPoint(StopRect.x, StopRect.y), cvPoint(StopRect.x + StopRect.width, StopRect.y + StopRect.height), cvScalar(0, 0, 255));
		int Num = 0;
		double start = (double)GetTickCount();
		if (MoveCheck(PreFrame, CurrentImg, bRect))
		{
			double end = (double)GetTickCount();
			printf("Move Check Cost:%f\n", end - start);
			printf("SomeThing is Moving\n");
			cvRectangle(ShowImg, cvPoint(bRect.x, bRect.y), cvPoint(bRect.x + bRect.width, bRect.y + bRect.height), cvScalar(255, 0, 0));
			//开始行人检测
			CvRect PRect[100];
			double bStart = (double)GetTickCount();
			//int total = PeopleDetection(hog,CurrentImg, PRect);
			int total = PeopleDetection(body_Classifier, CurrentImg, PRect);
			double bEnd = (double)GetTickCount();
			printf("PeopleDetection Cost:%f\n", bEnd-bStart);
			if (total>0)
			{
				printf("there is %d people\n", total);
#pragma omp parallel for
				for (int i = 0; i < total;i++)
				{
					if (PRect[i].x >= StopRect.x&&PRect[i].x < StopRect.x + StopRect.width&PRect[i].y >= StopRect.y&&PRect[i].x < StopRect.y + StopRect.height)
					{
						cvRectangle(ShowImg, cvPoint(PRect[i].x, PRect[i].y), cvPoint(PRect[i].x + PRect[i].width, PRect[i].y + PRect[i].height), cvScalar(0, 0, 255));
					}
					else
					{
						cvRectangle(ShowImg, cvPoint(PRect[i].x, PRect[i].y), cvPoint(PRect[i].x + PRect[i].width, PRect[i].y + PRect[i].height), cvScalar(0, 255, 0));
					}
				}
			}
			if (PreFrame != nullptr)
			{
				cvReleaseImage(&PreFrame);
			}
			PreFrame = cvCloneImage(CurrentImg);
		}
		else
		{
			//printf("Safe\n");
		}
		
		cvShowImage("frame", ShowImg);
		cvWaitKey(10);
	}
	return 0;
}

检测效果如下,感觉还不错

 自己买一个,高清摄像头就可以当做监控使用了,后面你还可以自己加上视频保存啊,人脸识别啊等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值