close

First, set up OpenCV building environments

image

INCLUDEPATH += C:\OpenCV\OpenCV4.2.0DNN\include
LIBS += -LC:\OpenCV\OpenCV4.2.0DNN\lib \
-lopencv_world420

Since Qt doesn’t recognise Mat data type that we have to register it 
before we start using signal and slot mechanics.

image

Syntax: qRegisterMetaType<T>("typeName");

qRegisterMetaType helps us to register a new typeName called “cv::Mat&”
and its Type is corresponding to <T>, ie. <cv::Mat> 
Besides, followed by a while loop, we notify ui to receive two inputs, 
including frame and m_counter. The observer(ui) is notified by a singalFrameGrabbed
whenever there are new incoming frame and counter, both of which are emitted by m_capImg.
 

image

mainwindow.h

image

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
#include <captureimage.h>
#include <QtConcurrent/QtConcurrent>
#include <QCloseEvent>
#include <QMessageBox>
 
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
 
private:
    Ui::MainWindow *ui;
    CaptureImage *m_capImg;
    void StartCamera();
 
public slots:
    void slotFrameGrabbed(cv::Mat& frame, int counter);
 
private slots:
    void on_pushButton_start_clicked();
    void on_pushButton_stop_clicked();
    void closeEvent(QCloseEvent *event);
};
#endif // MAINWINDOW_H


mainwindow.cpp

image

The above shows connection between signalFrameGrabbed and slotFrameGrabbed is established.

Besides we want to run StartCamera in a sperate thread by using QtConcurrent::run().

#include "mainwindow.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
//Q_DECLARE_METATYPE(cv::Mat)
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
 
    ui->setupUi(this);
 
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
 
void MainWindow::slotFrameGrabbed(cv::Mat& frame, int counter)
{
    auto w = ui->label_image->width();
    auto h = ui->label_image->height();
    ui->label_image->setPixmap(
       QPixmap::fromImage(
       QImage(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_BGR888)
       ).scaled(w, h, Qt::KeepAspectRatio)
    );
    ui->label_counter->setText(QString::number(counter));
}
 
 
 
 
void MainWindow::on_pushButton_start_clicked()
{
     //m_capImg->Start();
    m_capImg = new CaptureImage();
    connect(m_capImg, SIGNAL(signalFrameGrabbed(cv::Mat&, int)), this, SLOT(slotFrameGrabbed(cv::Mat&, int)));
    QtConcurrent::run(this, &MainWindow::StartCamera);
 
}
void MainWindow::StartCamera()
{
     m_capImg->Start();
}
 
void MainWindow::on_pushButton_stop_clicked()
{
    m_capImg->Stop();
}
 
void MainWindow::closeEvent (QCloseEvent *event)
{
    QMessageBox::StandardButton resBtn =
            QMessageBox::question( this, "CaptureApp",
                                   tr("Are you sure?\n"),
                                   QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes, QMessageBox::Yes);
       if (resBtn != QMessageBox::Yes) {
           event->ignore();
       } else {
           event->accept();
           if(m_capImg!=nullptr)
           {
               m_capImg->Stop();
               delete m_capImg;
           }
       }
 
}
 

You can drag the windows form to any place and the picture keeps refreshing, because the frame acquistion of m_capImg is running in a separate thread.


image

image


image







References:

1. How to run a function in a separate thread in Qt Window App

2. How to load and display an image on Qt GUI with OpenCV 4.2.0

3. Qt: How do I handle the event of the user pressing the 'X' (close) button?

arrow
arrow
    全站熱搜

    me1237guy 發表在 痞客邦 留言(0) 人氣()