1

我正在 Qt 中构建一个简单的 GUI 来在 OpenCV 中执行一些图像处理。我想使用多线程,以便即使处理变得非常密集,GUI 也能做出响应。为此,我参考以下章节来构建我的框架:

http://www.informit.com/articles/article.aspx?p=1405551&seqNum=3

首先,我有 2 个按钮,一个用于加载图像,另一个用于处理图像。

我有 2 个标签,一个用于显示输入图像,一个用于显示处理后的图像。

到目前为止,我正在使用主线程中的插槽和信号机制加载我的输入图像,并且我正在为图像翻转创建一个新线程。

但是,当我构建代码时,出现错误

架构 x86_64 的未定义符号:
“FlipTransaction::FlipTransaction(int)”,引用自:mainwindow.o ld 中的 MainWindow::flipHorizo​​ntally():未找到架构 x86_64 的符号

当我注释掉插槽 flipHorizo​​ntally() 时,我的代码构建良好并且能够加载图像。

因此我的处理没有被执行。

下面是我的代码。任何帮助表示赞赏

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFileDialog>
#include <QStatusBar>

// OpenCV Headers
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>   // for cvtColor

// Multi-Threading Headers
#include <QThread>
#include <QMutex>
#include <QQueue>
#include <QWaitCondition>


namespace Ui {
class MainWindow;
}

class Transaction
{
public:
    virtual ~Transaction() {}

    virtual QImage apply(const cv::Mat source_image, cv::Mat dest_image) = 0;

    virtual QString message() = 0;
};

class TransactionThread : public QThread
{
    Q_OBJECT

public:
    TransactionThread();
    ~TransactionThread();

    void addTransaction(Transaction *transact);
    void setImage(const QImage &image);
    QImage image();

signals:
    void transactionStarted(const QString &message);
    void allTransactionsDone();

protected:
    void run();

private:
    QImage currentImage;
    Transaction *EndTransaction;
    QQueue<Transaction *> transactions;
    QWaitCondition transactionAdded;
    QMutex mutex;
    cv::Mat source_image;
    cv::Mat dest_image;
};


class FlipTransaction : public Transaction
{
public:
    FlipTransaction(int orientation);

    QImage apply(const cv::Mat source_image, cv::Mat dest_image);
    QString message();

private:
    int orientation;
};


class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    void addTransaction(Transaction *transact);
    void drawOut(QImage qimg);


private slots:
    void on_pushButton_clicked();

public slots:
    void flipHorizontally();
    void allTransactionsDone();

private:
    Ui::MainWindow *ui;

public:
    TransactionThread thread;
    cv::Mat source_image;       // Input Image Variable
    cv::Mat dest_image;         // Output Image Variable
};

#endif // MAINWINDOW_H

主窗口.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

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

    statusBar()->showMessage(tr("Ready"), 2000);

    connect(&thread, SIGNAL(transactionStarted(const QString &)),
            statusBar(), SLOT(showMessage(const QString &)));

    connect(&thread, SIGNAL(allTransactionsDone()),
            this, SLOT(allTransactionsDone()));

}

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


void MainWindow::drawOut(QImage qimg)
{
    // Display on Label
    ui->outputLabel->setPixmap(QPixmap::fromImage(qimg));

    // Resize the label to fit the image
    ui->outputLabel->resize(ui->outputLabel->pixmap()->size());
}


void MainWindow::addTransaction(Transaction *transact)
{
      MainWindow::thread.addTransaction(transact);
}


void MainWindow::on_pushButton_clicked()
{
    QString filename = QFileDialog::getOpenFileName(this,
    tr("Open Image"), ".",tr("Image Files (*.png *.jpg *.jpeg *.bmp *.gif)"));

    // Read Image
    source_image = cv::imread(filename.toAscii().data());

    // Resize Image
    cv::resize(source_image, source_image, cv::Size(128,128) , 0, 0);

    // Change to RGB format
    cv::cvtColor(source_image,source_image,CV_BGR2RGB);

    // Convert to QImage
    QImage qimg = QImage((const unsigned char*) source_image.data, source_image.cols, source_image.rows, QImage::Format_RGB888); // convert to QImage

    // Display on Input Label
    ui->inputLabel->setPixmap(QPixmap::fromImage(qimg));

    // Resize the label to fit the image
    ui->inputLabel->resize(ui->inputLabel->pixmap()->size());
}


void MainWindow::flipHorizontally()
{
    MainWindow::thread.addTransaction(new FlipTransaction(int(1)));
}


void MainWindow::allTransactionsDone()
{
    statusBar()->showMessage(tr("Ready"), 2000);
}

TransactionThread::TransactionThread()
{
    start();
}

TransactionThread::~TransactionThread()
{
    {
        QMutexLocker locker(&mutex);
        while(!transactions.isEmpty())
            delete transactions.dequeue();
        transactions.enqueue(EndTransaction);
        transactionAdded.wakeOne();
    }
    wait();
}

void TransactionThread::addTransaction(Transaction *transact)
{
    QMutexLocker locker(&mutex);
    transactions.enqueue(transact);
    transactionAdded.wakeOne();
}

void TransactionThread::setImage(const QImage &image)
{
    QMutexLocker locker(&mutex);
    currentImage = image;
}

QImage TransactionThread::image()
{
    QMutexLocker locker(&mutex);
    return currentImage;
}

void TransactionThread::run()
{
    Transaction *transact = 0;
    QImage oldImage;

    forever {
        {
            QMutexLocker locker(&mutex);

            if (transactions.isEmpty())
                transactionAdded.wait(&mutex);
            transact = transactions.dequeue();
            if (transact == EndTransaction)
                break;

            oldImage = currentImage;
        }

        emit transactionStarted(transact->message());

        QImage newImage = transact->apply(source_image, dest_image);

     //   QImage newImage = transact->apply(oldImage);
        delete transact;

        {
            QMutexLocker locker(&mutex);
            currentImage = newImage;
            if (transactions.isEmpty())
                emit allTransactionsDone();
        }

    }
}

QImage FlipTransaction::apply(const cv::Mat source_image, cv::Mat dest_image)
{
    // Process Image
    cv::flip(source_image, dest_image, orientation);

    // Change to RGB format
    cv::cvtColor(dest_image,dest_image,CV_BGR2RGB);

    // Convert to QImage
    QImage qimg = QImage((const unsigned char*) dest_image.data, dest_image.cols, dest_image.rows, QImage::Format_RGB888);

    return qimg;
}


QString FlipTransaction::message()
{
    if (orientation == 1) {
        return QObject::tr("Flipping image horizontally...");
    } else {
        return QObject::tr("Flipping image vertically...");
    }
}
4

0 回答 0