如题
这里将任务分解为三大部分:
1.录播放视频
2.人脸检测
3.部分高斯模糊
其中重点放在人脸检测和部分高斯模糊上
1.录播放视频(以opencv中的VideoCapture类进行实现)
首先罗列下操作环境:win10+vs2013+opencv3.0+单摄像头
opencv中提供了VideoCapture和CvCapture对视频进行操作
其中官方给出CvCapture的API为
实例化CvCapture对象的时候,需要调用cvCaptureFromCAM(int device)进行实例化。
博主的是单摄像头没有外接摄像头,根据API进行填写操作
1 #include<opencv2highguihighgui.hpp> 2 #include<opencv2imgprocimgproc.hpp> 3 #include<opencv2corecore.hpp> 4 5 int main(int argc, const char** argv) 6 { 7 CvCapture* capture; 8 capture = cvCaptureFromCAM(0); 9 IplImage* frame; 10 namedWindow("video", 1); 11 while (true) 12 { 13 frame = cvQueryFrame(capture); 14 cvShowImage("video",frame); 15 char c = cvWaitKey(0); 16 if (c == 27)break;//捕获Esc 17 } 18 destroyWindow("video"); 19 cvReleaseCapture(&capture); 20 return 0; 21 }
通过简单的进行捕获摄像头的图像,结果如下:
并没有捕获到摄像头的所采集的图像。查阅的相关资料,有个方法将cvCaptureFromCAM()中填入-1。很遗憾是同样的效果。感兴趣的童鞋可以研究下,提出解决方案,共同促进学习。
所以这里采用VideoCapture进行采集视频
首先定义一个视频采集器,一个视频写入器;
VideoCapture capture;
VideoWriter writer;
初始化
1 /****************************************************** 2 函数名称: MyClass 3 函数功能: 初始化 4 传入参数: 5 返 回 值: 6 建立时间: 2018-05-13 7 修改时间: 8 建 立 人: 9 修 改 人: 10 其它说明: 11 ******************************************************/ 12 MyClass::MyClass() 13 { 14 if (!cascade.load(cascadeName)) 15 { 16 cerr << "ERROR: Could not load classifier cascade" << endl; 17 exit(1); 18 } 19 capture = 0; 20 string filepath = "test.avi"; 21 //获得帧的宽高 22 int w = static_cast<int>(capture.get(CV_CAP_PROP_FRAME_WIDTH)); 23 int h = static_cast<int>(capture.get(CV_CAP_PROP_FRAME_HEIGHT)); 24 Size S(w, h); 25 //获得帧率 26 double r = capture.get(CV_CAP_PROP_FPS); 27 //打开视频文件,准备写入 28 writer.open(filepath, -1, r, S, true); 29 //打开失败 30 if (!capture.isOpened()) 31 { 32 exit(1); 33 } 34 }
开始显示并录制:
1 /****************************************************** 2 函数名称: play 3 函数功能: 开始播放 4 传入参数: 5 返 回 值: 6 建立时间: 2018-05-13 7 修改时间: 8 建 立 人: 9 修 改 人: 10 其它说明: 11 ******************************************************/ 12 void MyClass::play(){ 13 Mat image; 14 namedWindow("直播页面按Esc退出", 1); 15 while (true) 16 { 17 capture >> image; 18 if (image.empty())break; 19 imshow("直播页面按Esc退出", image); 20 writer.write(image); 21 char c = waitKey(30); 22 if (c == 27)break; 23 } 24 cvDestroyWindow("直播页面按Esc退出"); 25 } 26 /******************************************************
下面是播放录制好的视频,校验原来是否成功录制:
1 /****************************************************** 2 函数名称: replay 3 函数功能: 播放测试 4 传入参数: 5 返 回 值: 6 建立时间: 2018-05-13 7 修改时间: 8 建 立 人: 9 修 改 人: 10 其它说明: 11 ******************************************************/ 12 void replay() 13 { 14 char* path = "test.avi"; 15 IplImage* frame; 16 CvCapture* capture=cvCreateFileCapture(path); 17 namedWindow("播放界面按Esc退出", 1); 18 while (true) 19 { 20 frame = cvQueryFrame(capture); 21 cvShowImage("播放界面按Esc退出", frame); 22 char c = waitKey(33); 23 if (c == 27)break; 24 } 25 26 }
结果:
成功播放了^.^.
2.人脸识别(以opencv中CascadeClassifier类进行实现)
在opencv安装处"../opencv/sources/samples/cpp/facedetect.cpp",里面有示例代码。(示例代码有图片和视频的识别,但是这种方式识别精准度不是很好。)
其中示例代码的视频处理部分主要的思想就是将视频中的每一帧提出来,然后根据CascadeClassifier类和haarcascade_frontalface_alt.xml所生成的对象,将图片进行类比区分。
ps:haarcascade_frontalface_alt.xml存储在"../opencv/sources/data/haarcascades"中。
将"../opencv/sources/data"包拷到项目中去,开始人脸识别。
1 /****************************************************** 2 函数名称: detectAndDraw 3 函数功能: 在人脸上绘制圆圈 4 传入参数: 5 返 回 值: 6 建立时间: 2018-05-13 7 修改时间: 8 建 立 人: 9 修 改 人: 10 其它说明: 11 ******************************************************/ 12 void MyClass::detectAndDraw(Mat& img,char* title) 13 { 14 Mat dog; 15 dog = imread("F:\Pictures\gdog.png",1); 16 Mat tempdog; 17 double alpha = 1; double beta = 1 - alpha; 18 19 double scale = 1; 20 vector<Rect> faces; 21 Mat gray,smallImg(cvRound(img.rows / scale), cvRound(img.cols / scale), CV_8UC1);; 22 cvtColor(img, gray, COLOR_BGR2GRAY); 23 resize(gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR); 24 equalizeHist(smallImg, smallImg); 25 cascade.detectMultiScale( smallImg, faces,1.1,2,0|CASCADE_SCALE_IMAGE,Size(30,30));//匹配人脸 26 for (vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++){ 27 Scalar color = colors[6];//红色 28 int radius; 29 Point center; 30 double aspect_ratio = (double)r->width / r->height; 31 if (0.75 < aspect_ratio && aspect_ratio < 1.3) 32 { 33 center.x = cvRound((r->x + r->width*0.5)*scale); 34 center.y = cvRound((r->x + r->height*0.5)*scale); 35 radius = cvRound((r->width + r->height)*0.25*scale); 36 circle(img, center, radius, color, 3, 8, 0); 37 } 38 else 39 { 40 rectangle(img, CvPoint(cvRound(r->x*scale), cvRound(r->y*scale)), 41 CvPoint(cvRound((r->x + r->width - 1)*scale), cvRound((r->y + r->height - 1)*scale)), 42 color, 3, 8, 0); 43 44 } 45 } 46 writer.write(img); 47 cv::imshow(title,img); 48 }
然后在采集的方法(void play())中调用这个方法即可实现人脸识别。这里不展示结果。
3.部分高斯模糊
部分高斯模糊的关键是找到ROI(感兴趣区域)
其中在人脸识别的时候已经找出ROI了,所以只要对找到ROI进行高斯模糊就可以了
1 /****************************************************** 2 函数名称: detectAndDraw 3 函数功能: 绘制圆圈和高斯模糊 4 传入参数: 5 返 回 值: 6 建立时间: 2018-05-13 7 修改时间: 8 建 立 人: 9 修 改 人: 10 其它说明: 11 ******************************************************/ 12 void MyClass::detectAndDraw(Mat& img,char* title) 13 { 14 Mat dog; 15 dog = imread("F:\Pictures\gdog.png",1); 16 Mat tempdog; 17 double alpha = 1; double beta = 1 - alpha; 18 19 double scale = 1; 20 vector<Rect> faces; 21 Mat gray,smallImg(cvRound(img.rows / scale), cvRound(img.cols / scale), CV_8UC1);; 22 cvtColor(img, gray, COLOR_BGR2GRAY); 23 resize(gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR); 24 equalizeHist(smallImg, smallImg); 25 cascade.detectMultiScale( smallImg, faces,1.1,2,0|CASCADE_SCALE_IMAGE,Size(30,30));//匹配人脸 26 for (vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++){ 27 Scalar color = colors[6];//红色 28 int radius; 29 Point center; 30 double aspect_ratio = (double)r->width / r->height; 31 if (0.75 < aspect_ratio && aspect_ratio < 1.3) 32 { 33 center.x = cvRound((r->x + r->width*0.5)*scale); 34 center.y = cvRound((r->x + r->height*0.5)*scale); 35 radius = cvRound((r->width + r->height)*0.25*scale); 36 circle(img, center, radius, color, 3, 8, 0); 37 Mat *imageROI=&img(Rect(r->x, r->y, 2 * radius, 2 * radius));//感兴趣区域 38 Mat temp = img(Rect(r->x, r->y, 2 * radius, 2 * radius)); 39 cv::GaussianBlur(temp, temp, Size(21, 21), 3, 3); 40 cv::GaussianBlur(temp, temp, Size(21, 21), 3, 3); 41 } 42 else 43 { 44 rectangle(img, CvPoint(cvRound(r->x*scale), cvRound(r->y*scale)), 45 CvPoint(cvRound((r->x + r->width - 1)*scale), cvRound((r->y + r->height - 1)*scale)), 46 color, 3, 8, 0); 47 48 } 49 } 50 writer.write(img); 51 cv::imshow(title,img); 52 }
结果:
:
成功生成人脸识别视频文件。
如需要源码请转移至码云:https://gitee.com/cjqbaba/MediaTest/tree/Face_Find进行源码克隆下载
如有问题请留言评论。转载请注明出处,谢谢。