diff --git a/BrainATUMtome/BrainATUMtome.pro b/BrainATUMtome/BrainATUMtome.pro index 5066ebb..935a9ea 100644 --- a/BrainATUMtome/BrainATUMtome.pro +++ b/BrainATUMtome/BrainATUMtome.pro @@ -32,7 +32,8 @@ SOURCES += \ microtome.cpp \ syringe.cpp \ serialport.cpp \ - serialpackage.cpp + serialpackage.cpp \ + videoproducer.cpp HEADERS += \ mainwindow.h \ @@ -41,7 +42,8 @@ HEADERS += \ microtome.h \ syringe.h \ serialport.h \ - serialpackage.h + serialpackage.h \ + videoproducer.h FORMS += \ mainwindow.ui @@ -56,6 +58,12 @@ win32: LIBS += -L$$PWD/../libs/epos/lib/ -lEposCmd64 INCLUDEPATH += $$PWD/../libs/epos/include DEPENDPATH += $$PWD/../libs/epos/include -macx: INCLUDEPATH += $$PWD/../libs/epos/macx -macx: LIBS += -L$$PWD/../libs/epos/macx -lepos +macx{ + INCLUDEPATH += $$PWD/../libs/epos/macx + LIBS += -L$$PWD/../libs/epos/macx -lepos + # link opencv via pkg-config + QT_CONFIG -= no-pkg-config + CONFIG += link_pkgconfig + PKGCONFIG += opencv4 +} diff --git a/BrainATUMtome/mainwindow.cpp b/BrainATUMtome/mainwindow.cpp index ca3261b..65733ec 100644 --- a/BrainATUMtome/mainwindow.cpp +++ b/BrainATUMtome/mainwindow.cpp @@ -7,6 +7,8 @@ MainWindow::MainWindow(QWidget *parent) : m_driverEpos(nullptr), m_driverMicrotome(nullptr), m_driverSyringe(nullptr), + m_driverVideo(nullptr), + m_thread_driverVideo(nullptr), m_timerEpos(new QTimer(this)), m_settings(nullptr), m_epos_ticks(0), @@ -25,6 +27,7 @@ MainWindow::MainWindow(QWidget *parent) : m_settings = new QSettings(fileIni, QSettings::IniFormat); configure_logs(); + configure_video(); configure_epos(); configure_microtome(); configure_syringe(); @@ -32,6 +35,12 @@ MainWindow::MainWindow(QWidget *parent) : MainWindow::~MainWindow() { + if (m_thread_driverVideo != nullptr) { + m_thread_driverVideo->quit(); + m_thread_driverVideo->wait(); + } + + if (m_timerEpos->isActive()) m_timerEpos->stop(); @@ -54,6 +63,26 @@ void MainWindow::configure_logs() } +void MainWindow::configure_video() +{ + m_driverVideo = new VideoProducer(this); + m_thread_driverVideo = new QThread(this); + m_driverVideo->moveToThread(m_thread_driverVideo); + connect(m_thread_driverVideo, &QThread::finished, m_driverVideo, &VideoProducer::deleteLater); + m_thread_driverVideo->start(); + + connect(m_driverVideo, &VideoProducer::log, ui->widget_board, &EventLog::on_log); + connect(m_driverVideo, &VideoProducer::frameView, + [this](const QImage &frame) { + ui->label_viewer_frame->setPixmap(QPixmap::fromImage(frame)); + ui->label_viewer_frame->show(); + } + ); + connect(ui->pushButton_camera_record, &QPushButton::clicked, m_driverVideo, &VideoProducer::start); + connect(ui->pushButton_camera_snap, &QPushButton::clicked, m_driverVideo, &VideoProducer::stop); +} + + void MainWindow::configure_epos() { if (m_settings->value("epos/deviceName").isNull()) { diff --git a/BrainATUMtome/mainwindow.h b/BrainATUMtome/mainwindow.h index c8ce540..e02d7f1 100644 --- a/BrainATUMtome/mainwindow.h +++ b/BrainATUMtome/mainwindow.h @@ -6,11 +6,13 @@ #include #include #include +#include #include #include "epos.h" #include "microtome.h" #include "syringe.h" +#include "videoproducer.h" namespace Ui { class MainWindow; @@ -30,6 +32,8 @@ class MainWindow : public QMainWindow Epos *m_driverEpos; Microtome *m_driverMicrotome; Syringe *m_driverSyringe; + VideoProducer *m_driverVideo; + QThread *m_thread_driverVideo; QTimer *m_timerEpos; QSettings *m_settings; @@ -42,6 +46,7 @@ class MainWindow : public QMainWindow void drive_epos_motor(int motorid, int velocity); void configure_logs(); + void configure_video(); void configure_epos(); void configure_microtome(); void configure_syringe(); diff --git a/BrainATUMtome/videoproducer.cpp b/BrainATUMtome/videoproducer.cpp new file mode 100644 index 0000000..6fcabbb --- /dev/null +++ b/BrainATUMtome/videoproducer.cpp @@ -0,0 +1,80 @@ +#include "videoproducer.h" + +VideoProducer::VideoProducer(QObject *parent) : QObject(parent), + m_videoCapture(nullptr), + m_producer(new QStateMachine(this)), + m_viewerTimer(new QTimer(this)), + m_viewerFlag(false) +{ + qRegisterMetaType(); + + // configure video capture + m_videoCapture = new cv::VideoCapture(0); + if (!m_videoCapture->isOpened()) { + emit log(Qt::red, "VideoProducer :: failed to open video capture device"); + return; + } + emit log(Qt::black, "VideoProducer :: camera is initialized"); + + // configure state machine + QState *stateIdle = new QState(m_producer); + QState *stateAcquire = new QState(m_producer); + stateIdle->addTransition(this, &VideoProducer::start, stateAcquire); + stateAcquire->addTransition(this, &VideoProducer::frameReady, stateAcquire); + stateAcquire->addTransition(this, &VideoProducer::stop, stateIdle); + connect(stateAcquire, &QState::entered, this, &VideoProducer::on_acquire); + m_producer->setInitialState(stateIdle); + m_producer->start(); + + // configure viewer timer + m_viewerTimer->setInterval(70); + connect(m_viewerTimer, &QTimer::timeout, [this](){m_viewerFlag = true;}); + connect(this, &VideoProducer::start, m_viewerTimer, QOverload<>::of(&QTimer::start)); + connect(this, &VideoProducer::stop, m_viewerTimer, &QTimer::stop); + +} + + +VideoProducer::~VideoProducer() +{ + if (m_viewerTimer->isActive()) + m_viewerTimer->stop(); + + if (m_producer->isRunning()) + m_producer->stop(); + + if (m_videoCapture != nullptr) { + if (m_videoCapture->isOpened()) + m_videoCapture->release(); + delete m_videoCapture; + } +} + + +void VideoProducer::on_acquire() +{ + cv::Mat frame; + + QCoreApplication::processEvents(); + + if (!m_videoCapture->read(frame)) { + emit log(Qt::red, "VideoProducer :: failed to read next frame"); + m_producer->stop(); + return; + } + + if (m_viewerFlag) { + cv::Mat frame_cv = frame; + cv::resize(frame_cv, frame_cv, cv::Size(), 0.5, 0.5, cv::INTER_AREA); + cv::cvtColor(frame_cv, frame_cv, cv::COLOR_BGR2RGB); + const QImage frame_qt(frame_cv.data, + frame_cv.cols, + frame_cv.rows, + static_cast(frame_cv.step), + QImage::Format_RGB888); + emit frameView(frame_qt); + } + + m_viewerFlag = false; + emit frameReady(frame); +} diff --git a/BrainATUMtome/videoproducer.h b/BrainATUMtome/videoproducer.h new file mode 100644 index 0000000..9401f69 --- /dev/null +++ b/BrainATUMtome/videoproducer.h @@ -0,0 +1,39 @@ +#ifndef VIDEOPRODUCER_H +#define VIDEOPRODUCER_H + +#include +#include +#include +#include +#include +#include + +class VideoProducer : public QObject +{ + Q_OBJECT + +public: + explicit VideoProducer(QObject *parent = nullptr); + ~VideoProducer(); + +private: + cv::VideoCapture *m_videoCapture; + QStateMachine *m_producer; + QTimer *m_viewerTimer; + bool m_viewerFlag; + +private slots: + void on_acquire(); + +signals: + void log(const Qt::GlobalColor &color, const QString &message); + void frameReady(const cv::Mat &frame); + void frameView(const QImage &frame); + void start(); + void stop(); + +}; + +Q_DECLARE_METATYPE(cv::Mat); + +#endif // VIDEOPRODUCER_H