优秀的编程知识分享平台

网站首页 > 技术文章 正文

Qt编程进阶(39):OpenCV人脸识别实例

nanyue 2024-08-11 20:42:48 技术文章 9 ℃

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还有很多十分奇妙的功能,限于篇幅,本系列文章不再展开,有兴趣的同学可以结合官方文档自己去尝试。

————————————————

觉得有用的话请关注点赞,谢谢您的支持!

对于本系列文章相关示例完整代码有需要的朋友,可关注并在评论区留言!

Tags:

最近发表
标签列表