对图片&视频进行人脸检测和处理
一、Windows下使用opencv采集视频
-
属性配置与上一篇相同
-
代码
#include<opencv2\opencv.hpp>
using namespace cv;
//========================
//调用摄像头录像保存
//==========================
int main() {
VideoCapture capture(0);
// 设置摄像头的拍摄属性为 分辨率640x480,帧率30fps
capture.set(CAP_PROP_FRAME_HEIGHT, 480);
capture.set(CAP_PROP_FRAME_WIDTH, 640);
capture.set(CAP_PROP_FPS, 30.0);
// 设置保存视频的格式为AVI,编码为MJPG
VideoWriter writer("chen.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), 30.0, Size(640, 480), true);
Mat videoPlay;
// 通过总帧数来控制拍摄时间,如果是10s的段视频的话,循环300次
int count(300);
namedWindow("VideoPlay", WINDOW_NORMAL);
while (count--) {
capture >> videoPlay;
writer << videoPlay;
imshow("VideoPlay", videoPlay);
waitKey(1000 / 30);
}
// 释放相关对象
writer.release();
capture.release();
destroyWindow("VideoPlay");
return 0;
}
- 视频录制
二、基于opencv对视频中人脸进行检测
(一)Windows(VS2015)
1. 对图片中检测出的人脸画一个矩形框或圆圈
代码:
#include<opencv2/objdetect/objdetect.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <stdio.h>
// 对图片进行人脸检测
using namespace cv;
using namespace std;
CascadeClassifier faceCascade;
int main()
{
faceCascade.load("D:/dasan/qianrushi/opencv/build/etc/haarcascades/haarcascade_frontalface_alt2.xml");
Mat img = imread("bo.jpg"); // 载入图片
Mat imgGray;
vector<Rect> faces;
if (img.empty()){
return 1;
}
if (img.channels() == 3){
cvtColor(img, imgGray, CV_RGB2GRAY); // RGB转化为灰度
}
else{
imgGray = img; // 不转化
}
faceCascade.detectMultiScale(imgGray, faces, 1.2, 6, 0, Size(0, 0));// 检测人脸
if (faces.size() > 0){
for (int i = 0; i < faces.size(); i++){
rectangle(img, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width, faces[i].y + faces[i].height), Scalar(0, 255, 0), 1, 8); // 框出人脸
}
}
imshow("FacesOfPrettyGirl", img); // 显示图片
waitKey(0);
return 0;
}
执行结果:
2.对摄像头或视频中检测出的人脸画一个矩形框
代码:
// 对视频进行人脸检测
#include<opencv2/objdetect/objdetect.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
CascadeClassifier faceCascade;
int main(){
faceCascade.load("D:/dasan/qianrushi/opencv/build/etc/haarcascades/haarcascade_frontalface_alt2.xml");
VideoCapture capture;
// capture.open(0); // 打开摄像头
// capture.open("test.avi"); // 打开视频
capture.open("chen.mp4"); // 打开视频
if (!capture.isOpened()){
cout << "open camera failed. " << endl;
return -1;
}
Mat img, imgGray;
vector<Rect> faces;
while (1){
capture >> img; // 读取图像至img
if (img.empty()){
continue;
}
if (img.channels() == 3){
cvtColor(img, imgGray, CV_RGB2GRAY);
}
else{
imgGray = img;
}
faceCascade.detectMultiScale(imgGray, faces, 1.2, 6, 0, Size(0, 0)); // 检测人脸
if (faces.size() > 0){
for (int i = 0; i < faces.size(); i++){
rectangle(img, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width, faces[i].y + faces[i].height), Scalar(0, 255, 0), 1, 8);
}
}
imshow("CamerFace", img);// 显示
if (waitKey(1) > 0) // delay ms 等待按键退出
{
break;
}
}
return 0;
}
执行结果:
调用视频:
调用摄像头:
3.对视频中检测出的人脸区域进行模糊处理
代码:
// 高斯模糊
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "cv.h"
using namespace cv;
using namespace std;
int g_slider_position = 0, temp;
CvCapture *g_captrue = NULL;
void onTrackbarSlide(int pos){
cvSetCaptureProperty(g_captrue, CV_CAP_PROP_POS_FRAMES,
pos);
temp = g_slider_position;
}
int main(int argc, char **argv){
cvNamedWindow("sample-out", CV_WINDOW_AUTOSIZE);
//创建输出处理后视频的窗口
cvNamedWindow("sample", CV_WINDOW_AUTOSIZE);
//创建初始视频窗口
g_captrue = cvCreateFileCapture("chen.mp4");
//Cvcapture结构体赋值
int frames = (int)cvGetCaptureProperty(g_captrue,
CV_CAP_PROP_FRAME_COUNT);
//获取视频总帧数
if (frames != 0)///若视频存在即帧数不为0则创建滚动条
{
cvCreateTrackbar("Position", "sample",
&g_slider_position, frames, onTrackbarSlide);
}
IplImage *frame;//创建图像指针
while (1){
frame = cvQueryFrame(g_captrue);//读取一帧
if (!frame)//读完退出
break;
cvShowImage("sample", frame);//显示在sample窗口中
IplImage* out = cvCreateImage(cvGetSize(frame),
IPL_DEPTH_8U, 3);
//创建视频地址并为其开辟空间。
cvSmooth(frame, out, CV_GAUSSIAN, 7, 7);//对每一帧高斯模糊||数值越大越模糊
cvShowImage("sample-out", out);//视频输出到sample-out窗口中
char c = cvWaitKey(30);//每一帧间隔30ms
cvSetTrackbarPos("Position", "sample", temp++);//滚动条随动
if (c == 27)
break;
}
cvReleaseCapture(&g_captrue);//释放指针
cvDestroyWindow("sample");//删除sample初始视频窗口
cvDestroyWindow("sample-out");//删除sample-out处理后的视频窗口
return 0;
}
执行结果:
(二)树莓派
对此视频中检测出的人脸区域画框并进行模糊处理
将视频传至树莓派
新建cpp文件
代码:
#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
void DetectAndDraw(Mat& img, CascadeClassifier& cascade, double scale);
int main(){
CascadeClassifier faceCascade;
double scale = 4;
int nRet = 0;
VideoCapture capture;
//capture.open(0);//此句为调用摄像头,下一句为调用视频
capture.open("chen.mp4");//mp4文件需放在工程文件夹下
if (!capture.isOpened()){
cout << "open camera failed. " << endl;
return -1;
}
cout << "open camera succeed. " << endl;
/* 加载分类器 */
#ifdef VERSION_2_4
nRet = faceCascade.load("home/pi/opencv-3.4.1/data/haarcascades/haarcascade_frontalface_alt2.xml");
#else
nRet = faceCascade.load("home/pi/opencv-3.4.1/data/haarcascades/haarcascade_frontalface_alt2.xml");
#endif
if (!nRet){
printf("load xml failed.\n");
return -1;
}
Mat frame;
vector<Rect> faces;
while (1){
capture >> frame;
if (frame.empty()){
continue;
}
Mat frame1 = frame.clone();
DetectAndDraw(frame1, faceCascade, scale);
if (waitKey(1) > 0){ // delay ms 等待按键退出
break;
}
}return 0;
}
void DetectAndDraw(Mat& img, CascadeClassifier& cascade, double scale){
double t = 0;
vector<Rect> faces;
Mat gray, smallImg;
double fx = 1 / scale;
cvtColor(img, gray, COLOR_BGR2GRAY); // 将源图像转为灰度图
/* 缩放图像 */
#ifdef VERSION_2_4
resize(gray, smallImg, Size(), fx, fx, INTER_LINEAR);
#else
resize(gray, smallImg, Size(), fx, fx, INTER_LINEAR_EXACT);
#endif
equalizeHist(smallImg, smallImg); // 直方图均衡化,提高图像质量
/* 检测目标 */
t = (double)getTickCount();
cascade.detectMultiScale(smallImg, faces,
1.1, 2, 0
//|CASCADE_FIND_BIGGEST_OBJECT
//|CASCADE_DO_ROUGH_SEARCH
| CASCADE_SCALE_IMAGE,
Size(30, 30));
t = (double)getTickCount() - t;
printf("detection time = %g ms\n", t * 1000 / getTickFrequency());
/* 画矩形框出目标 */
for (size_t i = 0; i < faces.size(); i++) // faces.size():检测到的目标数量
{
Rect rectFace = faces[i];
rectangle(img, Point(rectFace.x, rectFace.y) * scale,
Point(rectFace.x + rectFace.width, rectFace.y + rectFace.height) * scale,
Scalar(0, 255, 0), 2, 8);
}
imshow("FaceDetect", img); // 显示
}
执行