ubuntu端opencv人脸检测,并实现自动拍照,录视频
现在在做毕业设计,打算用树莓派做一个监控,实现人脸检测后拍照,并录取一段30S的视频,然后继续进行人脸检测。本次教程我们由浅入深,先讲解人脸检测部分代码。注意:如果您有linux上opencv开发基础,那么本教程足够,如果没有那么您可能要移步下载https://download.csdn.net/download/groot_lee/11075171下载完成后,解压到home文件夹,定...
现在在做毕业设计,打算用树莓派做一个监控,实现人脸检测后拍照,并录取一段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),那么您要尽量大的调大这个数。
更多推荐
所有评论(0)