如何使用 Opencv 实现人脸检测和人脸识别?
如何使用 Opencv 实现人脸检测和人脸识别?
Note:
使用人脸识别需要自行编译 Opencv 第三方模块,地址如下:
https://github.com/opencv/opencv_contrib
1.人脸检测 CascadeClassifier
- 加载 Opencv 自带的人脸检测
haarcascade_frontalface_alt.xml
分类器。 - 图像预处理
cvtColor(灰度化)
equalizeHist(直方图均衡化)
。 - 使用
detectMultiScale
函数进行识别。 - 使用
rectangle
函数绘制找到的目标矩形框。 - 在原图像上
ROI
截取彩色的人脸保存。
2.人脸识别 FaceRecognizer
FisherFaceRecognizer
LBPHFaceRecognizer
2.1 人脸识别分类器训练
- 样本归一化,即图像大小一致、灰度化、直方图均衡化等。
Ptr<FaceRecognizer> face = EigenFaceRecognizer::create()
。- 创建样本和标签向量
std::vector<Mat> images
std::vector<int> labels
并push_back
加入样本和标签。 - 进行训练
face->train(images,labels)
。 - 保存训练的分类器
face->save("face.xml")
。
2.2 人脸识别分类器加载和使用
- 加载训练好的分类器
face->load(face.xml)
。 - 待识别图像预处理
resize
cvtColor
等。 - 预测输入图像获取标签值
int label = face->predict(Mat src)
,当然也可以获取置信度
来调整阈值
。 - 根据标签值,绘制
putText
对应的角色名。
Note:
1.训练和预测的图像大小必须一样且为灰度图像。
2.使用 FisherFaceRecognizer 标签必须大于2类
Code
//人脸检测
#include "opencv2/opencv.hpp"
#include "opencv2/face.hpp"
#include <iostream>
#include <string>
using namespace cv;
using namespace cv::face;
using namespace std;
void FindFaces(cv::Mat &dst)
{
Mat src = imread("src.jpg");
Mat frame = src.clone();
Mat facesRIO;
//图像缩放,采用双线性插值。
//cv::resize(src,src,Size(128,128),0,0,cv::INTER_LINEAR);
//图像灰度化。
cv::cvtColor(src,src,COLOR_BGR2GRAY);
//直方图均衡化,图像增强,暗的变亮,亮的变暗。
cv::equalizeHist(src,src);
//
String face_cascade_name = "haarcascade_frontalface_alt.xml";
String eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade,eyes_cascade;
if(!face_cascade.load(face_cascade_name))
{
//加载脸部分类器失败!
return;
}
if(!eyes_cascade.load(eyes_cascade_name))
{
//加载眼睛分类器失败!
return;
}
//存储找到的脸部矩形。
std::vector<Rect> faces;
face_cascade.detectMultiScale(src,faces,1.1,2,0|CASCADE_SCALE_IMAGE,Size(30,30));
for(size_t i=0;i<faces.size();++i)
{
//绘制矩形 BGR。
rectangle(frame,faces[i],Scalar(0,0,255),1);
//获取矩形中心点。
//Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );
//绘制圆形。
//ellipse(frame, center, Size( faces[i].width/2, faces[i].height/2 ), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
//获取脸部矩形区域。
//Mat faceROI = src(faces[i]);
//存储找到的眼睛矩形。
//std::vector<Rect> eyes;
//eyes_cascade.detectMultiScale(faceROI,eyes,1.1,2,0 |CASCADE_SCALE_IMAGE,Size(30,30));
//for(size_t j=0;j<eyes.size();++j)
//{
//Point eye_center(faces[i].x + eyes[j].x + eyes[j].width/2,faces[i].y + eyes[j].y + eyes[j].height/2);
//int radius = cvRound((eyes[j].width + eyes[j].height)*0.25);
//circle(frame,eye_center,radius,Scalar( 255, 0, 0 ),4,8,0);
//}
//截取人脸。
facesROI = frame(faces[i]);
//图像缩放。
cv::resize(facesROI,facesROI,Size(128,128),0,0,cv::INTER_LINEAR);
//保存图像。
dst = facesROI;
cv::imwrite("dst.jpg",facesROI);
}
return;
}
//人脸识别
void Distinguish()
{
/*******************************************************
*假定 标签1代表张三 标签2代表李四 标签3代表 王五
******************************************************/
//定义保存图片和标签的向量容器
std::vector<Mat> images;
std::vector<int> labels;
//读取样本
Mat src_1 = imread("src_1.jpg",CV_LOAD_IMAGE_GRAYSCALE);
Mat src_2 = imread("src_2.jpg",CV_LOAD_IMAGE_GRAYSCALE);
Mat src_3 = imread("src_3.jpg",CV_LOAD_IMAGE_GRAYSCALE);
Mat src_4 = imread("src_4.jpg",CV_LOAD_IMAGE_GRAYSCALE);
//预测样本
Mat src_5 = imread("src_5.jpg",CV_LOAD_IMAGE_GRAYSCALE);
//图像大小归一化
cv::resize(src_1,src_1,Size(128,128));
cv::resize(src_2,src_2,Size(128,128));
cv::resize(src_3,src_3,Size(128,128));
cv::resize(src_4,src_4,Size(128,128));
cv::resize(src_5,src_5,Size(128,128));
//加入图像
images.push_back(src_1);
images.push_back(src_2);
images.push_back(src_3);
images.push_back(src_4);
//加入标签
labels.push_back(1);
labels.push_back(1);
labels.push_back(2);
labels.push_back(3);
Ptr<FaceRecognizer> faceClass = EigenFaceRecognizer::create();
Ptr<FisherFaceRecognizer> fisherClass = FisherFaceRecognizer::create();
Ptr<LBPHFaceRecognizer> lpbhClass = LBPHFaceRecognizer::create();
//训练
faceClass->train(images,labels);
fisherClass->train(images,labels);
lpbhClass->train(images,labels);
//保存训练的分类器
faceClass->save("faceClass.xml");
fisherClass->save("fisherClass.xml");
lpbhClass->save("lpbhClass.xml");
//加载分类器
//faceClass->load("faceClass.xml");
//fisherClass->load("fisherClass.xml");
//lpbhClass->load("lpbhClass.xml");
//使用训练好的分类器进行预测。
int faceResult = faceClass->predict(src_5);
switch (faceResult)
{
case 1:
//张三
break;
case 2:
//李四
break;
case 3:
//王五
break;
default:
//未知
break;
}
//预测样本并获取标签和置信度
int fisherResult = -1;
double fisherConfidence = 0.0;
fisherClass->predict(src_5,fisherResult,fisherConfidence);
std::count<<String("标签类别:")<<fisherResult<<String("置信度:")<<fisherConfidence<<std::endl;
int lpbhResult = lpbhClass->predict(src_5);
std::count<<String("标签类别:")<<lpbhResult;
return;
}
更多信息请自行查看官网参考 Opencv 3.3.0 官方教程
转载请注明出处并保持作品的完整性,谢谢