樹莓派基於OpenCV的人臉檢測和處理
阿新 • • 發佈:2018-12-16
對圖片&視訊進行人臉檢測和處理
一、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); // 顯示
}
執行