Qt+多线程实现单幅图像高斯、灰度、边缘处理,调用opencv库导入图片

【QT】多线程+OpenCV的demo

结合最近学的知识自己做了个小demo。可以实现对输入的图片进行图像处理,高斯模糊、灰度处理以及边缘检测,三种处理同时进行。

思路:借助OpenCv库,用Mat读取图片并输出展示在界面上,多线程进行图像处理。这里采用线程池的方法。

ui界面如下

Qt+多线程实现单幅图像高斯、灰度、边缘处理,调用opencv库导入图片

Mythread.h

#pragma once
#include "qobject.h"
#include
#include
#include
#include
#include
#include

using namespace std;
using namespace cv;

class Gaussuianintroduce :public QObject, public QRunnable
{
    Q_OBJECT
public:
    Gaussuianintroduce();
    ~Gaussuianintroduce();

    void run();

    void recvmat(Mat mat);

signals:
    void finish(Mat mat);

private:
    Mat m_mat;
    Mat mat_Gussian;
};

class Grayintroduce :public QObject, public QRunnable
{
    Q_OBJECT
public:
    Grayintroduce();
    ~Grayintroduce();

    void run();

    void recvmat(Mat mat);

signals:
    void finish(Mat mat);

private:
    Mat m_mat2;
    Mat mat_Gray;
};

class Cannyintroduce :public QObject, public QRunnable
{
    Q_OBJECT
public:
    Cannyintroduce();
    ~Cannyintroduce();

    void run();

    void recvmat(Mat mat);

signals:
    void finish(Mat mat);

private:
    Mat m_mat3;
    Mat mat_Canny;
};

Mythread.cpp

#include "Mythread.h"
#include
#include
#include
#include
#include
#include
#include
#include
#pragma execution_character_set("utf-8")
#include
#include
#include
#include
#include

using namespace cv;
using namespace std;

Gaussuianintroduce::Gaussuianintroduce()
{
    setAutoDelete(true);
}

Gaussuianintroduce::~Gaussuianintroduce()
{
}

void Gaussuianintroduce::run()
{
    qDebug() << "高斯模糊处理的线程地址:" << QThread::currentThread();

    QElapsedTimer time;
    time.start();

    GaussianBlur(m_mat, mat_Gussian, Size(29, 29), 0, 0);

    int milsec = time.elapsed();
    qDebug() << "高斯模糊处理用时" << milsec << "毫秒";

    emit finish(mat_Gussian);

}

void Gaussuianintroduce::recvmat(Mat mat)
{
    m_mat = mat;
}

Grayintroduce::Grayintroduce()
{
    setAutoDelete(true);
}

Grayintroduce::~Grayintroduce()
{
}

void Grayintroduce::run()
{
    qDebug() << "灰度处理的线程地址:" << QThread::currentThread();

    QElapsedTimer time;
    time.start();
    cvtColor(m_mat2, mat_Gray, COLOR_BGR2GRAY);
    int milsec = time.elapsed();
    qDebug() << "灰度处理用时" << milsec << "毫秒";

    emit finish(mat_Gray);

}

void Grayintroduce::recvmat(Mat mat)
{
    m_mat2 = mat;
}

Cannyintroduce::Cannyintroduce()
{
    setAutoDelete(true);
}

Cannyintroduce::~Cannyintroduce()
{
}

void Cannyintroduce::run()
{
    qDebug() << "边缘检测的线程地址:" << QThread::currentThread();

    QElapsedTimer time;
    time.start();

    Canny(m_mat3, mat_Canny, 150, 100, 3);

    int milsec = time.elapsed();
    qDebug() << "灰度处理用时" << milsec << "毫秒";

    emit finish(mat_Canny);
}

void Cannyintroduce::recvmat(Mat mat)
{
    m_mat3 = mat;
}

demo_qt_cv_thread.h

#pragma once

#include
#include "ui_demo_qt_cv_thread.h"
#include
#include

using namespace std;
using namespace cv;

class demo_qt_cv_thread : public QMainWindow
{
    Q_OBJECT

public:
    demo_qt_cv_thread(QWidget *parent = Q_NULLPTR);

    QImage MatToImage(Mat &mat);

signals:
    void starting(Mat mat);

private:
    Ui::demo_qt_cv_threadClass *ui;
    Mat image;
};

demo_qt_cv_thread.cpp

#include "demo_qt_cv_thread.h"
#include
#include
#include
#include
#pragma execution_character_set("utf-8")
#include
#include
#include "Mythread.h"
#include
#include
#include

using namespace std;
using namespace cv;

demo_qt_cv_thread::demo_qt_cv_thread(QWidget *parent)
    : QMainWindow(parent)
{
    ui->setupUi(this);

    this->setWindowTitle("多线程图像处理");
    this->setWindowIcon(QPixmap(":/res/b2.jpg"));

    connect(ui->pushButton_2, &QPushButton::clicked, [=]() {
        ui->label->clear();
        ui->label_2->clear();
        ui->label_3->clear();
        ui->label_4->clear();

        QString filename = QFileDialog::getOpenFileName(this,
            tr("open image"), ".", tr("Image file(*.png *.jpg *.bmp)")
        );

        image = imread(filename.toLocal8Bit().data());

        qDebug() << image.data;
        if (image.empty())
        {
            QMessageBox::information(this, tr("提示"), tr("未成功载入图片"), QMessageBox::Ok);
        }

        QPixmap pix;
        pix = QPixmap::fromImage(MatToImage(image).scaled(ui->label->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
        ui->label->setPixmap(pix);
    });

    Gaussuianintroduce *th1 = new Gaussuianintroduce;
    Grayintroduce *th2 = new Grayintroduce;
    Cannyintroduce *th3 = new Cannyintroduce;

    connect(this, &demo_qt_cv_thread::starting, th1, &Gaussuianintroduce::recvmat);
    connect(this, &demo_qt_cv_thread::starting, th2, &Grayintroduce::recvmat);
    connect(this, &demo_qt_cv_thread::starting, th3, &Cannyintroduce::recvmat);

    connect(ui->pushButton, &QPushButton::clicked, [=]() {
        ui->label_2->clear();
        ui->label_3->clear();
        ui->label_4->clear();

        QThreadPool::globalInstance()->start(th1);
        QThreadPool::globalInstance()->start(th2);
        QThreadPool::globalInstance()->start(th3);

        emit starting(image);
    });

    connect(th1, &Gaussuianintroduce::finish, [=](Mat mat_Gussian) {
        QPixmap pix2;
        pix2 = QPixmap::fromImage(MatToImage(mat_Gussian).scaled(ui->label_2->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
        ui->label_2->setPixmap(pix2);
    });

    connect(th2, &Grayintroduce::finish, [=](Mat mat_Gray) {
        QPixmap pix3;
        pix3 = QPixmap::fromImage(MatToImage(mat_Gray).scaled(ui->label_3->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
        ui->label_3->setPixmap(pix3);
    });

    connect(th3, &Cannyintroduce::finish, [=](Mat mat_Canny) {
        QPixmap pix4;
        pix4 = QPixmap::fromImage(MatToImage(mat_Canny).scaled(ui->label_4->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
        ui->label_4->setPixmap(pix4);
    });
    destroyAllWindows();
}

QImage demo_qt_cv_thread::MatToImage(Mat &mat)
{

    if (mat.type() == CV_8UC3)
    {

        const uchar* pSrc = (const uchar*)mat.data;

        QImage image(pSrc, mat.cols, mat.rows,(mat.cols)*3, QImage::Format_RGB888);

        return image.rgbSwapped();
    }

    else if (mat.type() == CV_8UC1)
    {
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);

        image.setColorCount(256);
        for (int i = 0; i < 256; i++)
        {
            image.setColor(i, qRgb(i, i, i));
        }

        uchar *pSrc = mat.data;
        for (int row = 0; row < mat.rows; row++)
        {
            uchar *pDest = image.scanLine(row);

            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }
        return image;
    }

    else if (mat.type() == CV_8UC4)
    {
        qDebug() << "CV_8UC4";

        const uchar *pSrc = (const uchar*)mat.data;

        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
        return image.copy();
    }
    else
    {
        qDebug() << "ERROR:Mat could not be converted to QImage";
        return QImage();
    }
}

运行效果如下:

Qt+多线程实现单幅图像高斯、灰度、边缘处理,调用opencv库导入图片
点击输入图片按钮,弹出一个文件夹,可选取自己想处理的图片
Qt+多线程实现单幅图像高斯、灰度、边缘处理,调用opencv库导入图片
这里我选择了一张狗头的表清包
Qt+多线程实现单幅图像高斯、灰度、边缘处理,调用opencv库导入图片
点击开始处理按钮,成功实现同时输出三种处理图像
Qt+多线程实现单幅图像高斯、灰度、边缘处理,调用opencv库导入图片

通过调试信息可以看到

Qt+多线程实现单幅图像高斯、灰度、边缘处理,调用opencv库导入图片

Original: https://blog.csdn.net/Sca_Lian/article/details/126115868
Author: 我也不太懂她
Title: Qt+多线程实现单幅图像高斯、灰度、边缘处理,调用opencv库导入图片

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/642214/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球