Qt OpenCV 学习(二):两个简单图片识别案例

1. 寻找匹配物体

1.1 mainwindow.h

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <opencv2/opencv.hpp>

#include <QImage>
#include <QString>
#include <QPixmap>

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_pushButton_clicked();

private:
    Ui::MainWindow *ui;

    cv::Mat myImg;  // 缓存图片:用于代码引用和处理
    QImage myQImg;  // 保存图片,可转为文件存盘或显示
};
#endif // MAINWINDOW_H

1.2 mainwindow.cpp

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
    ui->setupUi(this);

    initMainWindow();
}

MainWindow::~MainWindow() {
    delete ui;
}

// 界面初始化
void MainWindow::initMainWindow() {
    // 读取图片
    cv::Mat imgData = cv::imread("D:\\BaiduNetdiskDownload\\search_pic\\search_pic\\mermaid.jpg");
    // 图片格式转换
    cv::cvtColor(imgData, imgData, cv::COLOR_BGR2RGB);
    myImg = imgData;
    myQImg = QImage((const unsigned char*)(imgData.data), imgData.cols, imgData.rows, QImage::Format_RGB888);

    imgShow();  // 显示图片
}

// 处理图片
void MainWindow::imgproc() {
    // CV_TM_CCOEFF 相关匹配,把原图像素对其均值的相对值与待匹配子图像素对其均值的相对值进行比较,计算数值越接近 1,表示匹配度越高
    int METHOD = CV_TM_CCOEFF;
    cv::Mat imgSrc = myImg;  // 将被显示的原图
    // 待匹配的子图
    cv::Mat imgTmp = cv::imread("D:\\BaiduNetdiskDownload\\search_pic\\search_pic\\fish.jpg");
    cv::cvtColor(imgTmp, imgTmp, cv::COLOR_BGR2RGB);

    cv::Mat imgRes;
    cv::Mat imgDisplay;
    imgSrc.copyTo(imgDisplay);
    int rescols = imgSrc.cols - imgTmp.cols + 1;
    int resrows = imgSrc.rows - imgTmp.rows + 1;
    imgRes.create(rescols, resrows, CV_32FC1);  // 创建输出结果的矩阵
    cv::matchTemplate(imgSrc, imgTmp, imgRes, METHOD);  // 进行匹配
    cv::normalize(imgRes, imgRes, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());  // 进行标准化

    double minVal;
    double maxVal;
    cv::Point minLoc;
    cv::Point maxLoc;
    cv::Point matchLoc;
    // 通过函数 minMaxLoc 定位最匹配的位置
    cv::minMaxLoc(imgRes, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat());

    if (METHOD == CV_TM_SQDIFF || METHOD == CV_TM_SQDIFF_NORMED) {
        matchLoc = minLoc;
    } else {
        matchLoc = maxLoc;
    }

    // 将匹配结果用举行框圈出来
    cv::rectangle(imgDisplay, matchLoc, cv::Point(matchLoc.x + imgTmp.cols, matchLoc.y + imgTmp.rows), cv::Scalar::all(0), 2, 8, 0);
    cv::rectangle(imgRes, matchLoc, cv::Point(matchLoc.x + imgTmp.cols, matchLoc.y + imgTmp.rows), cv::Scalar::all(0), 2, 8, 0);

    myQImg = QImage((const unsigned char*)(imgDisplay.data), imgDisplay.cols, imgDisplay.rows, QImage::Format_RGB888);

    imgShow();
}

// 显示图片
void MainWindow::imgShow() {
    // 在 Qt 界面上显示图片
    ui->label->setPixmap(QPixmap::fromImage(myQImg.scaled(ui->label->size(), Qt::KeepAspectRatio)));
}

void MainWindow::on_pushButton_clicked() {
    imgproc();
}

2. 人脸识别实例

2.1 mainwindow.h

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <opencv2/opencv.hpp>

#include <vector>
#include <QImage>
#include <QString>
#include <QPixmap>

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_pushButton_clicked();

private:
    Ui::MainWindow *ui;

    cv::Mat myImg;
    QImage myQImg;
};
#endif // MAINWINDOW_H

2.2 mainwindow.cpp

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
    ui->setupUi(this);

    initMainWindow();
}

MainWindow::~MainWindow() {
    delete ui;
}

void MainWindow::initMainWindow() {
    cv::Mat imgData = cv::imread("D:\\download\\qt_test\\OpencvFace\\model.jpg");
    cv::cvtColor(imgData, imgData, cv::COLOR_BGR2RGB);
    myImg = imgData;
    myQImg = QImage((const unsigned char*)(imgData.data), imgData.cols, imgData.rows, QImage::Format_RGB888);

    imgShow();
}

void MainWindow::imgProc() {
    cv::CascadeClassifier face_detector;  // 定义人脸识别分类器类
    cv::CascadeClassifier eyes_detector;  // 定义人眼识别分类器类

    // 加载视觉识别分类器
    // 下述两个 xml 文件在 D:\OpenCV-MinGW-Build-OpenCV-3.4.9\etc\haarcascades
    face_detector.load("D:\\download\\qt_test\\OpencvFace\\haarcascade_frontalface_alt.xml");
    eyes_detector.load("D:\\download\\qt_test\\OpencvFace\\haarcascade_eye_tree_eyeglasses.xml");

    std::vector<cv::Rect> faces;
    cv::Mat imgSrc = myImg;
    cv::Mat imgGray;
    cv::cvtColor(imgSrc, imgGray, cv::COLOR_BGR2GRAY);

    cv::equalizeHist(imgGray, imgGray);
    // 多尺寸检测人脸
    face_detector.detectMultiScale(imgGray, faces, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));

    for (uint64 i = 0; i < faces.size(); i++) {
        cv::Point center(faces[i].x + faces[i].width * 0.5, faces[i].y + faces[i].height * 0.5);
        cv::ellipse(imgSrc, center, cv::Size(faces[i].width * 0.5, faces[i].height * 0.5), 0, 0, 360, cv::Scalar(255, 0, 255), 4, 8, 0);

        cv::Mat faceROI = imgGray(faces[i]);
        std::vector<cv::Rect> eyes;
        // 在每张人脸基础上多尺寸检测人眼
        eyes_detector.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));

        for (uint64 j = 0; j < eyes.size(); j++) {
            cv::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[j].height) * 0.25);
            cv::circle(imgSrc, center, radius, cv::Scalar(255, 0, 0), 4, 8, 0);
        }
    }

    cv::Mat imgDst = imgSrc;
    myQImg = QImage((const unsigned char*)(imgDst.data), imgDst.cols, imgDst.rows, QImage::Format_RGB888);

    imgShow();
}

void MainWindow::imgShow() {
    ui->label->setScaledContents(true);  // 当图像大于控件大小时,将自动缩放以适应控件的大小
    // Qt::KeepAspectRatio:保持图像的纵横比例不变
    ui->label->setPixmap(QPixmap::fromImage(myQImg.scaled(ui->label->size(), Qt::KeepAspectRatio)));
}

void MainWindow::on_pushButton_clicked() {
    imgProc();
}
相关推荐
koi77u22 分钟前
嵌入式学习————————TCP并发服务器(1)
linux·学习
小淮AI8 小时前
从“刷题”到“追问”:AI课堂正在重塑哪些学习旧习惯?
人工智能·学习
wixzjsh10 小时前
TCP通信与HTTP协议学习笔记:粘包、三次握手、四次挥手与C/S、B/S模型
学习·tcp/ip·http
ZhiMuZhiLing10 小时前
拓客软件学习成本实测方法论:从注册到出第一批名单要多久
学习·流量运营·用户运营
程序员大雄学编程10 小时前
微积分46. 无穷级数四大核心性质:从理论到实践的全方位解析
python·学习·微积分·学习工具
指针常量12 小时前
【RL系列文章】难样本学习等
学习·大语言模型·rl·后训练
wuyk55513 小时前
从零吃透Modbus通信|第7章:终极工程整合(模块化架构、双模式主机从机、RTOS适配、量产级模板)
c语言·stm32·学习·架构
一条破秋裤14 小时前
STM32 学习笔记:PWM 驱动 LED 呼吸灯与舵机代码
笔记·stm32·学习
kyrie_sakura16 小时前
python学习笔记11 -- 进程和线程
笔记·python·学习
qq_4017004116 小时前
Qt TCP 心跳到底应该怎么设计?
qt·tcp/ip