学习记录
虽然网络上基于OpenCV实现的人脸检测有很多,但是大部分都是基于Python实现的,很少有完整的C++例程,所以我将自己的代码整理出来,供参考。
环境
- OpenCV 4.3.0
- 树莓派4B(在Windows系统下也可以)
功能
实现人脸检测,并在人脸处画框
代码
/*******************************************************
> File Name: main.cpp
> Author: admin
> Mail: ffffffan@foxmail.com
> Created Time: Fri 24 Apr 2020 09:46:00 CST
> Modified Time:2020年06月28日 星期日 16时42分49秒
> Note: No
*******************************************************/
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <unistd.h>
#include <time.h>
using namespace std;
// OpenCV includes
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/ml.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/face.hpp"
using namespace cv;
using namespace cv::ml;
CascadeClassifier faceCascade;
Mat preprocessImage(Mat input);
Mat extractFace(Mat input, vector<Rect> *faces);
bool detection(void);
//输出灰度图像,直方图均衡,长宽缩小0.5倍
Mat preprocessImage(Mat input)
{
//cout<<"-->>function preprocessImage"<<endl;
Mat result;
resize(input, input, Size(), 0.5, 0.5, INTER_AREA);
cvtColor(input, result, COLOR_BGR2GRAY);
// Equalize the histogram
equalizeHist(result, result);
return result;
}
//仅支持单脸
//未检测到脸时返回纯黑
//返回灰度脸图,缩小了1.1倍
Mat extractFace(Mat input, vector<Rect> *faces)
{
Mat result;
result = preprocessImage(input);
Mat zero= Mat::zeros(result.rows, result.cols, CV_8UC1);
faceCascade.detectMultiScale(result, *faces, \
1.1, 2, 0|CV_HAL_CMP_GE, Size(100, 100), Size(200, 200) );
if((*faces).size() == 0)
return zero;
Mat grayc = result.clone();
grayc = grayc((*faces)[0]);//
return grayc;
}
//检测人脸
Mat detection(Mat img)
{
vector<Rect> faces;
Mat grayt = extractFace(img, &faces);
Scalar he= sum(grayt);
if(he[0] == 0)
{
resize(img, img, Size(), 0.5, 0.5, INTER_AREA);
return img;
}
resize(img, img, Size(), 0.5, 0.5, INTER_AREA);
rectangle(img, faces[0], Scalar(255, 255, 255), 2);
return img;
}
int main(int argc, char* argv[])
{
Mat camera;
string faceCascadeName = "../haar/haarcascade_frontalface_alt.xml";
if( !faceCascade.load(faceCascadeName) )
{
cerr << "Error loading cascade file. Exiting!" << endl;
return -1;
}
VideoCapture cap(0);
if( !cap.isOpened() )
{
cout<< "No video!"<<endl;
return -1;
}
while(true)
{
cap >> camera;
camera = detection(camera);
imshow("camera", camera);
if(waitKey(10) == 27)
{
break;
}
}
cap.release();
destroyAllWindows();
return 0;
}
注意事项
文中代码string faceCascadeName = "../haar/haarcascade_frontalface_alt.xml";
的意思是级联分类器的路径,实际使用中根据个人选择。