OpenCV还有一个广泛的用途就是识别人脸,由于它的内部集成了最新的图片视觉智能识别技术,故识别率可以做到非常精准。本例我们用一张女模特的图片作为程序识别的对象。
1. 加载视觉识别分类器
创建一个Qt桌面应用程序项目,项目名称为“OpencvFace”,在做人脸识别功能之前需要将OpenCV库内置的计算机视觉识别分类器文件复制到项目目录下,这些文件位于〇penCV的安装文件夹,路径为“D:\OpenCV\Opencv_4.5.4-Build\install\etc\haarcascades”(安装方法见我的前面文章:Qt编程进阶(33):OpenCV环境搭建详细过程,避免踩坑)。
本例选用其中的“haarcascade_eye_tree_eyeglasses.xml”(用于人双眼位置识别)和“haarcascade_frontalface_alt.xml”(用于人正脸识别)这两个文件。当然,有兴趣的用户也可以自己写程序测试其他一些类型的分类器。从分类器的文件名就可以大致猜出它的功能,有的单独用于识别左眼或右眼,还有的用于识别身体的上半身、下半身等。
2. 程序界面
设计程序界面如下图所示。
3. 全局变量及方法
为了提高程序代码的使用效率,通常建议将程序中公用的图片对象的句柄声明为全局变量,通用的方法声明为公有(public)方法,定义在项目上头文件中。
“mainwindow.h”头文件,代码如下:
#include <QMainWindow>
#include "opencv2/opencv.hpp" //OpenCV文件包含
#include <vector> //包含向量类动态数组功能
using namespace cv; //OpenCV命名空间
using namespace std;//使用vector必须声明该名称空间
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void initMainWindow(); //界面初始化
void imgProc(); //处理图片
void imgShow(); //显示图片
private slots:
void on_btnDetect_clicked();
private:
Ui::MainWindow *ui;
Mat myImg;//缓存图片(供程序代码引用和处理)
QImage myQImg;//保存图片(可转为文件存盘或显示)
};
4. 初始化显示
首先在Qt界面上显示待处理的图片,在构造方法中添加代码如下:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
initMainWindow();
}
初始化方法initMainWindow()的代码为:
void MainWindow::initMainWindow()
{
QString imgPath = "baby.jpg"; //本地路径(将图片直接存放在项目目录下)
Mat imgData = imread (imgPath.toLatin1().data()); //读取图片数据
cvtColor(imgData, imgData, COLOR_BGR2RGB); //图片格式转换(避免图片颜色失真)
myImg = imgData;
myQImg=QImage((const unsigned char*)(imgData.data),imgData.cols, imgData.rows,
QImage::Format_RGB888);
imgShow(); //显不图片
}
显示图片的imgShow()方法中只有一句:
void MainWindow::imgShow()
{
ui->labView->setPixmap(QPixmap::fromImage(myQImg.scaled(ui->labView->size(),
Qt::KeepAspectRatio)));//在Qt界面上显示图片
}
5. 检测识别功能
检测识别功能写在imgProc()方法中,实现代码为
void MainWindow::imgProc()
{
CascadeClassifier face_detector; // 定义人脸识别分类器类
CascadeClassifier eyes_detector; // 定义人脸识别分类器类
string fDetectorPath = "haarcascade_frontalface_alt.xml";
face_detector.load(fDetectorPath);
string eDetectorPath = "haarcascade_eye_tree_eyeglasses.xml";
eyes_detector.load(eDetectorPath); // (a)
vector<Rect> faces;
Mat imgSrc = myImg;
Mat imgGray;
cvtColor(imgSrc, imgGray, COLOR_RGB2GRAY);
equalizeHist(imgGray, imgGray);
face_detector.detectMultiScale(imgGray, faces, 1.1, 2,
0 | CASCADE_SCALE_IMAGE, Size(30, 30)); //多尺寸检测人脸
for(int i = 0; i < faces.size(); i++)
{
Point center(faces[i].x + faces[i].width * 0.5,
faces[i].y + faces[i].height * 0.5);
ellipse(imgSrc, center, Size(faces[i].width * 0.5, faces[i].height * 0.5),
0, 0, 360, Scalar(255, 0, 255), 4, 8, 0);
Mat faceROI = imgGray(faces[i]);
vector<Rect> eyes;
eyes_detector.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | CASCADE_SCALE_IMAGE,
Size(30, 30)) ; //再在每张人脸上检测双眼
for(int j = 0; j < eyes.size (); j++)
{
Point center(faces[i].x + eyes[j].x + eyes[j].width * 0.5,
faces[i].y + eyes[j].y + eyes[j].height * 0.5);
int radius = cvRound((eyes[j].width + eyes[i].height) * 0.25);
circle(imgSrc, center, radius, Scalar(255, 0, 0), 4, 8, 0);
}
}
Mat imgDst = imgSrc;
myQImg = QImage((const unsigned char*)(imgDst.data), imgDst.cols, imgDst.rows,
QImage::Format_RGB888);
imgShow();
}
其中,
- (a) eyes_detector.load(eDetectorPath): load()方法用于加载一个XML分类器文件,OpenCV既支持Haar特征算法也支持LBP特征算法的分类器。关于各种人脸检测识别的智能算法,有兴趣的读者可以查阅相关的计算机视觉类刊物和论文,本文就不展开了。
6.界面事件响应
最后编写“识别”按钮的单击事件过程,在其中调用人脸识别的处理方法:
void MainWindow::on_btnDetect_clicked()
{
imgProc();
}
7. 运行效果
程序运行后,在界面上显示初始的图片。
单击“识别”按钮,程序执行完分类器算法自动识别出图片上的人脸,用粉色圆圈圈出;并且进一步辨别出她的双眼所在的位置,用红色圆圈圈出,如下图所示。
OpenCV还有很多十分奇妙的功能,限于篇幅,本系列文章不再展开,有兴趣的同学可以结合官方文档自己去尝试。
————————————————
觉得有用的话请关注点赞,谢谢您的支持!
对于本系列文章相关示例完整代码有需要的朋友,可关注并在评论区留言!