概述
C++:opencv 人脸五官识别
实践课,老师布置的作业。
代码是从网上找的,但是他的只识别了人脸和人眼,我经过更改可以识别出部分照片的嘴巴和鼻子,这在我看来已经很不错了,因为我找了很久也没找到几个有关嘴巴识别的,鼻子识别的也很少。这是我参的那篇博客。(10条消息) C++:opencv 人脸检测_timbrist的博客-CSDN博客_c++ opencv 人脸识别
因为是刚开始接触,代码写的很简单,而且,代码的泛化性能不是很好,以后会再更新的,刚开始学的同学可以参考下,希望对你有所帮助。
代码:
#include<opencv2opencv.hpp>
#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
using namespace std;
using namespace cv;
/** Global variables */
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
CascadeClassifier nose_cascade;
CascadeClassifier mouth_cascade;
string Path1 = "D:\LenovoSoftstore\opencv\opencv\build\etc\haarcascades\haarcascade_frontalface_default.xml";//检测人脸
string Path2 = "D:\LenovoSoftstore\opencv\opencv\build\etc\haarcascades\haarcascade_eye_tree_eyeglasses.xml";//检测戴眼镜后的眼睛,不带眼镜也可以检测出来
string Path3 = "D:\LenovoSoftstore\opencv\opencv\build\etc\haarcascades\haarcascade_mcs_nose.xml";//检测鼻子
string Path4 = "D:\LenovoSoftstore\opencv\opencv\build\etc\haarcascades\haarcascade_mcs_mouth.xml";//检测嘴巴
//注意到这里的路径是绝对路径,即'\',如果用''则会出现'.xml'文件加载失败
void detectAndDisplay(Mat frame)
{
Mat frame_gray;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);//直方图均衡化,增强对比
//-- Detect faces
std::vector<Rect> faces;
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 5); //面部检测
for (size_t i = 0; i < faces.size(); i++)
{
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);
Mat faceROI = frame_gray(faces[i]);
//-- In each face, detect eyes
std::vector<Rect> eyes;
eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 7, 0);
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 eyes_radius = cvRound((eyes[j].width + eyes[j].height) * 0.25);
circle(frame, eye_center, eyes_radius, Scalar(255, 0, 155), 4);
}
//-- In each face, detect nose
std::vector<Rect> nose;
nose_cascade.detectMultiScale(faceROI, nose, 1.1, 10, 0);
for (size_t k = 0; k < nose.size(); k++) {
Point nose_center( faces[i].x + nose[k].x + nose[k].width / 2, faces[i].y + nose[k].y + nose[k].height / 2);
int nose_radius = cvRound((nose[k].width + nose[k].height) * 0.25);
circle(frame, nose_center, nose_radius*0.7, Scalar(0, 0, 105), 4);
}
//-- In each face, detect mouth
std::vector<Rect> mouth;
mouth_cascade.detectMultiScale(faceROI, mouth, 1.1, 10, 0);//在将第四个参数minNeighbors由默认值3改为5以后嘴巴检测立即变好了
for (size_t m = 0; m < mouth.size(); m++) {
Point mouth_center(faces[i].x + mouth[m].x + mouth[m].width / 2, faces[i].y + mouth[m].y + mouth[m].height / 2);
int mouth_radius = cvRound((mouth[m].width + mouth[m].height) * 0.25);
cout << "mouth center:" << mouth_center << " mouth width&height: " << mouth[m].width << " " << mouth[m].height << " mouth x&y:" << mouth[m].x << " " << mouth[m].y << endl;
//circle(frame, mouth_center, mouth_radius, Scalar(255, 0, 0), 4);
ellipse(frame, mouth_center, Size(mouth[m].width *0.35, mouth[m].height *0.2), 0, 0, 360, Scalar(255, 0, 0), 4);
}
}
//识别结果显示
namedWindow("Face detection", WINDOW_FREERATIO);
imshow("Face detection", frame);
waitKey(0);
}
int main()
{
if (!face_cascade.load(Path1)) //opencv自带的人脸识别
{
cout << "face.xml文件加载失败" << endl;
return -1;
};
if (!eyes_cascade.load(Path2))
{
cout << "eyes.xml文件加载失败" << endl;
return -1;
};
if (!nose_cascade.load(Path3))
{
cout << "nose.xml文件加载失败" << endl;
return -1;
};
if (!mouth_cascade.load(Path4))
{
cout << "mouth.xml文件加载失败" << endl;
return -1;
};
Mat frame = imread("2.jpg");//输入图片
if (frame.empty())
{
cout << "图片不存在" << endl;
}
detectAndDisplay(frame);
return 0;
}
结果
感悟
其实,鼻子和嘴巴的识别比眼睛有点难,我暂时也不太明白,在其他的博客中,我看到有人说在具体的五官检测时是要分区域的,这一点我成功地应用在了有关我自己的照片识别时。
如果用其他照片进行五官检测时发现同时检测出来好几个位置,那么需要对其中一个*_cascade.detectMultiScale()函数里的参数进行调整。
以嘴巴识别为例:mouth_cascade.detectMultiScale(faceROI, mouth, 1.1, 10, 0, Size(110, 260), Size(220, 390));
我在用我自己的照片识别时第一次用默认参数识别出来了五个嘴巴区域,后来调整了第三个参数也就是minNeighbors,由五个区域变成了两个区域,后来无论如何调整minNeighbors参数,它一直都是两个区域不变,然后开始尝试调整minSize和maxSize这两个参数,尝试了很多次之后终于将两个区域变成了一个区域。这篇文章里的代码没有调整minSize和maxSize这俩参数。
当然了,代码由于很简单地原因,所以适用的图片也不是很多,如果想识别出一个不错的效果的话还是要自己多多调试一下*_cascade.detectMultiScale()里面的参数。
关于detectMultiScale()函数我觉得这篇文章讲的不错。(11条消息) 对OpenCV人脸检测方法detectMultiScale参数“最直白”的理解——Python学习笔记(8)_赵赵赵颖的博客-CSDN博客_detectmultiscale
最后
以上就是闪闪钥匙为你收集整理的人脸五官检测C++:opencv 人脸五官识别的全部内容,希望文章能够帮你解决人脸五官检测C++:opencv 人脸五官识别所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复