如題
這里將任務分解為三大部分:
1.錄播放視頻
2.人臉檢測
3.部分高斯模糊
其中重點放在人臉檢測和部分高斯模糊上
1.錄播放視頻(以opencv中的VideoCapture類進行實現)
首先羅列下操作環境:win10+vs2013+opencv3.0+單攝像頭
opencv中提供了VideoCapture和CvCapture對視頻進行操作
其中官方給出CvCapture的API為
實例化CvCapture對象的時候,需要調用cvCaptureFromCAM(int device)進行實例化。
博主的是單攝像頭沒有外接攝像頭,根據API進行填寫操作
1 #include<opencv2\highgui\highgui.hpp> 2 #include<opencv2\imgproc\imgproc.hpp> 3 #include<opencv2\core\core.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進行源碼克隆下載
如有問題請留言評論。轉載請注明出處,謝謝。