现在在做毕业设计,打算用树莓派做一个监控,实现人脸检测后拍照,并录取一段30S的视频,然后继续进行人脸检测。

本次教程我们由浅入深,先讲解人脸检测部分代码。

注意:如果您有linux上opencv开发基础,那么本教程足够,如果没有那么您可能要移步下载https://download.csdn.net/download/groot_lee/11075171或者公众号"嵌入式老码农"内回复qita0000获取

下载完成后,解压到home文件夹,定位到“ opetes2_视频人脸检测测试+拍照保存时间+储存录像 ”下-->cmake . -->make  编译完成

然后./tes运行即可。

一、检测到人脸并画方框

(本段代码借鉴于一博主,由于时间长了我忘记哪个博主了,以后找到必加链接。)

#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>

using namespace cv;

void Pic2Gray(Mat camerFrame,Mat &gray)
{
	//普通台式机3通道BGR,移动设备为4通道
	if (camerFrame.channels() == 3)
	{
		cvtColor(camerFrame, gray, CV_BGR2GRAY);
	}
	else if (camerFrame.channels() == 4)
	{
		cvtColor(camerFrame, gray, CV_BGRA2GRAY);
	}
	else
		gray = camerFrame;
}


int main()
{
	//加载Haar人脸检测器
	CascadeClassifier faceDetector;
	std::string faceCascadeFilename = "haarcascade_frontalface_default.xml";

	//错误信息提示
	try{
		faceDetector.load(faceCascadeFilename);
	}
	catch (cv::Exception e){}
	if (faceDetector.empty())
	{
		std::cerr << "脸部检测器不能加载 (";
		std::cerr << faceCascadeFilename << ")!" << std::endl;
		exit(1);
	}

	//打开摄像头
	VideoCapture cap(0);
	while (true)
	{
		Mat camerFrame;
		cap >> camerFrame;
		if (camerFrame.empty())
		{
			std::cerr << "无法获取摄像头图像" << std::endl;
			getchar();
			exit(1);
		}
		Mat displayedFrame(camerFrame.size(),CV_8UC3);


		//人脸检测只适用于灰度图像
		Mat gray;
		Pic2Gray(camerFrame, gray);



		//直方图均匀化(改善图像的对比度和亮度)
		Mat equalizedImg;
		equalizeHist(gray, equalizedImg);

		//人脸检测用Cascade Classifier::detectMultiScale来进行人脸检测

		//int flags = CASCADE_FIND_BIGGEST_OBJECT|CASCADE_DO_ROUGH_SEARCH;//只检测脸最大的人
		int flags = CASCADE_SCALE_IMAGE;	//检测多个人
		Size minFeatureSize(30, 30);//最小检测区域,越小对cpu要求越高,检测越准确
		float searchScaleFactor = 1.1f;//每次检测后,检测区域扩增比,越小(不小于等于1)对cpu要求越高,检测越准确
		int minNeighbors = 4;//在同一区域识别人脸次数,越大越消耗cpu,检测越准确
		std::vector<Rect> faces;
		faceDetector.detectMultiScale(equalizedImg, faces, searchScaleFactor, minNeighbors, flags, minFeatureSize);

		//画矩形框
		cv::Mat face;
		cv::Point text_lb;
		for (size_t i = 0; i < faces.size(); i++)
		{
			if (faces[i].height > 0 && faces[i].width > 0)
			{
				face = gray(faces[i]);
				text_lb = cv::Point(faces[i].x, faces[i].y);
				cv::rectangle(equalizedImg, faces[i], cv::Scalar(255, 0, 0), 1, 8, 0);
				cv::rectangle(gray, faces[i], cv::Scalar(255, 0, 0), 1, 8, 0);
				cv::rectangle(camerFrame, faces[i], cv::Scalar(255, 0, 0), 1, 8, 0);
			}
		}
		imshow("jkjk", camerFrame);
		waitKey(20);
	}

	getchar();
	return 0;
}

1、现象

单人人脸检测

多人人脸检测

2、注意

注意看注解,很详细了,如果你的cpu运算速度很慢,那你需要调节程序中我标注出来的那几个参数(faceDetector.detectMultiScale中几个参数),如果条件放的太松,那有可能造成识别不到人脸或者识别处处都是人脸

二、识别到人脸自动拍照并录取一段30s的视频

#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>
#include<stdlib.h>
#include "time.h"
#include<string.h>
using namespace std;
using namespace cv;
int i=0,a=1;
int time_jishi=0;
int SHIPIN_Huanchong=1;//由于outputVideoPath只有10个元素,所以为了防止数组溢出,设定此标志位
string outputVideoPath[11]={"test1.avi","test2.avi","test3.avi","test4.avi","test5.avi","test6.avi","test6.avi","/test7.avi","test8.avi","test9.avi","test10.avi"};//用于储存文件名
string getTime()//获取系统时间
{
	time_t timep;
	time (&timep);
	char tmp[64];
	strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S",localtime(&timep) );
	return tmp;
}
void Pic2Gray(Mat camerFrame,Mat &gray)
{
	//普通台式机3通道BGR,移动设备为4通道
	if (camerFrame.channels() == 3)
	{
		cvtColor(camerFrame, gray, CV_BGR2GRAY);
	}
	else if (camerFrame.channels() == 4)
	{
		cvtColor(camerFrame, gray, CV_BGRA2GRAY);
	}
	else
		gray = camerFrame;
}


int main()
{
	//system("time");
	//加载Haar或LBP对象或人脸检测器
	CascadeClassifier faceDetector;
	std::string faceCascadeFilename = "haarcascade_frontalface_default.xml";

	//友好错误信息提示
	try{
		faceDetector.load(faceCascadeFilename);
	}
	catch (cv::Exception e){}
	if (faceDetector.empty())
	{
		std::cerr << "脸部检测器不能加载 (";
		std::cerr << faceCascadeFilename << ")!" << std::endl;
		exit(1);
	}

	//打开摄像头
	VideoCapture cap(0);
	int frameNum = 300;//计时视频时间,取决于你的cpu运算速度,如果cpu为pc而不是树莓派等移动端,请调大这个参数
	//获取当前摄像头的视频信息
	cv::Size sWH = cv::Size((int)cap.get(CV_CAP_PROP_FRAME_WIDTH),
	(int)cap.get(CV_CAP_PROP_FRAME_HEIGHT));
	VideoWriter outputVideo;
	outputVideo.open(outputVideoPath[0], CV_FOURCC('M', 'P', '4', '2'), 10.0, sWH);
	//cap.set(CV_CAP_PROP_FRAME_WIDTH,1280);
	//cap.set(CV_CAP_PROP_FRAME_HEIGHT,800);
	while (true)
	{
		frameNum=300;
		time_jishi++;
		Mat camerFrame;
		cap >> camerFrame;

		if (camerFrame.empty())
		{
			std::cerr << "无法获取摄像头图像" << std::endl;
			camerFrame.release();
			getchar();
			
			exit(1);
		}
		Mat displayedFrame(camerFrame.size(),CV_8UC3);
		//人脸检测只试用于灰度图像
		Mat gray;
		Pic2Gray(camerFrame, gray);



		//直方图均匀化(改善图像的对比度和亮度)
		Mat equalizedImg;
		equalizeHist(gray, equalizedImg);

		//人脸检测用Cascade Classifier::detectMultiScale来进行人脸检测
		//double t = (double)cvGetTickCount();/********************测试点:测试时间*******************/
		//int flags = CASCADE_FIND_BIGGEST_OBJECT|CASCADE_DO_ROUGH_SEARCH;	//只检测脸最大的人
		int flags = CASCADE_SCALE_IMAGE;	//检测多个人
		Size minFeatureSize(60, 60);
		float searchScaleFactor = 1.3f;
		int minNeighbors = 2;
		std::vector<Rect> faces;
		faceDetector.detectMultiScale(equalizedImg, faces, searchScaleFactor, minNeighbors, flags, minFeatureSize);
		//t = (double)cvGetTickCount() - t;/********************测试点:测试时间*******************/
		//cout<<"detection time = "<< t / ((double)cvGetTickFrequency()*1000.) << "%gms/n" <<endl;
		/********************测试点:测试时间*******************/
		//画矩形框
		cv::Mat face;
		cv::Point text_lb;
		for (size_t i = 0; i < faces.size(); i++)
		{
			if (faces[i].height > 0 && faces[i].width > 0)
			{
				//if(time_jishi%10==0)//拍照
				/****************拍照***************/
				{
					string time = getTime();//获取系统日期
					//cout << time << endl;
					String filename = format("photo%d.jpg", a++);
					imwrite(filename, camerFrame);//储存图片
		        	//imshow("photo", camerFrame);
					cout<<"************** 有人来过"<<a-1<<" "<<"发生时间:"<<time<<" **************"<<endl;
				}
				/****************拍照完成***************/

				/****************录制视频***************/
				while(frameNum!=0)
				{
					cap >> camerFrame;
					outputVideo << camerFrame;
					frameNum--;
					imshow("renlian", camerFrame);
					waitKey(10);

					if (char(waitKey(1)) == 'q') break;
					if(frameNum==0)
					{
						string time = getTime();//获取系统日期
						SHIPIN_Huanchong++;
						if(SHIPIN_Huanchong>10)SHIPIN_Huanchong=1;//循环储存视频
						outputVideo.open(outputVideoPath[SHIPIN_Huanchong-1], CV_FOURCC('M', 'P', '4', '2'), 25.0, sWH);
						cout<<outputVideoPath[SHIPIN_Huanchong-1]<<" "<<"视频储存完成"<<" "<<"发生时间:"<<time<<endl;
					}
				}
				/****************录制视频完成***************/

				/****************画方框***************/
				face = gray(faces[i]);
				text_lb = cv::Point(faces[i].x, faces[i].y);
				cv::rectangle(equalizedImg, faces[i], cv::Scalar(255, 0, 0), 1, 8, 0);
				cv::rectangle(gray, faces[i], cv::Scalar(255, 0, 0), 1, 8, 0);
				cv::rectangle(camerFrame, faces[i], cv::Scalar(255, 0, 0), 1, 8, 0);
				/****************画方框完成***************/
				
			}
		}

		imshow("renlian", camerFrame);

		waitKey(20);
	}

	getchar();
	return 0;
}

1、现象

终端显示

储存的照片

 

储存的视频

b站链接:https://www.bilibili.com/video/av47907598

2、注意

代码中我也都一一注解了,还有一点就是现在这段代码实现录制30s视频不是依靠时间函数来实现的,而是程序中的变量自加(frameNum=300),初始值为300,当您的cpu运算速度很快(比如pc),那么您要尽量大的调大这个数。

Logo

更多推荐