close
First, set up OpenCV building environments
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.
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.
mainwindow.h
#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
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.
add #include <QCloseEvent>
and also closeEvent(QCloseEvent *event)
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?
全站熱搜
留言列表