diff --git a/BrainATUMtome/BrainATUMtome.pro b/BrainATUMtome/BrainATUMtome.pro
index 8631ba4..99a9f10 100644
--- a/BrainATUMtome/BrainATUMtome.pro
+++ b/BrainATUMtome/BrainATUMtome.pro
@@ -29,14 +29,22 @@ SOURCES += \
driverepos.cpp \
driverserialport.cpp \
driversyringe.cpp \
- drivermicrotome.cpp
+ drivermicrotome.cpp \
+ videoproducer.cpp \
+ videoconverter.cpp \
+ videoviewer.cpp \
+ videowriter.cpp
HEADERS += \
mainwindow.h \
driverepos.h \
driverserialport.h \
driversyringe.h \
- drivermicrotome.h
+ drivermicrotome.h \
+ videoproducer.h \
+ videoconverter.h \
+ videoviewer.h \
+ videowriter.h
FORMS += \
mainwindow.ui
diff --git a/BrainATUMtome/mainwindow.cpp b/BrainATUMtome/mainwindow.cpp
index 6b98bf4..c3a89e3 100644
--- a/BrainATUMtome/mainwindow.cpp
+++ b/BrainATUMtome/mainwindow.cpp
@@ -108,6 +108,36 @@ MainWindow::MainWindow(QWidget *parent) :
connect(ui->pushButton_dsy_pump, &QPushButton::clicked, m_driverSyringe, &DriverSyringe::on_uirequest_pump);
+ /* --- configure VideoProducer --- */
+ m_videoProducer = new VideoProducer(nullptr);
+ m_thread_videoProducer = new QThread(this);
+ m_videoProducer->moveToThread(m_thread_videoProducer);
+ connect(m_thread_videoProducer, &QThread::finished, m_videoProducer, &VideoProducer::deleteLater);
+ m_thread_videoProducer->start();
+
+
+ /* --- configure VideoConverter --- */
+ m_videoConverter = new VideoConverter(nullptr);
+ m_thread_videoConverter = new QThread(this);
+ m_videoConverter->moveToThread(m_thread_videoConverter);
+ connect(m_thread_videoConverter, &QThread::finished, m_videoConverter, &VideoConverter::deleteLater);
+ m_thread_videoConverter->start();
+
+ /* --- configure VideoWriter --- */
+ m_videoWriter = new VideoWriter(nullptr);
+ m_thread_videoWriter = new QThread(this);
+ m_videoWriter->moveToThread(m_thread_videoWriter);
+ connect(m_thread_videoWriter, &QThread::finished, m_videoWriter, &VideoWriter::deleteLater);
+ m_thread_videoWriter->start();
+
+ /* --- connect Video Signal/Slots --- */
+ connect(ui->pushButton_dvs_record, &QPushButton::clicked, m_videoProducer, &VideoProducer::start);
+ connect(ui->pushButton_dvs_snap, &QPushButton::clicked, m_videoProducer, &VideoProducer::stop);
+ connect(m_videoProducer, &VideoProducer::frameReady, m_videoConverter, &VideoConverter::on_convertFrame);
+ connect(m_videoConverter, &VideoConverter::pixmapReady, ui->widget_videoViewer, &VideoViewer::on_pixmapReady);
+
+ //connect(m_videoProducer, &VideoProducer::error, this, &MainWindow::on_error_throw);
+ //connect(m_videoWriter, &VideoWriter::error, this, &MainWindow::on_error_throw);
}
@@ -125,6 +155,18 @@ MainWindow::~MainWindow()
m_thread_driverSyringe->quit();
m_thread_driverSyringe->wait();
+ // destroy VideoProducer thread
+ m_thread_videoProducer->quit();
+ m_thread_videoProducer->wait();
+
+ // destroy VideoConverter thread
+ m_thread_videoConverter->quit();
+ m_thread_videoConverter->wait();
+
+ // destroy VideoWriter thread
+ m_thread_videoWriter->quit();
+ m_thread_videoWriter->wait();
+
delete ui;
}
@@ -202,3 +244,9 @@ void MainWindow::on_lineEdit_dep_velocity_returnPressed()
command_DriverEpos(true);
}
+
+
+void MainWindow::on_error_throw(const QString &errorSource, const QString &errorMessage)
+{
+ qDebug() << errorSource << "::Error, " << errorMessage;
+}
diff --git a/BrainATUMtome/mainwindow.h b/BrainATUMtome/mainwindow.h
index 19591e9..fd91415 100644
--- a/BrainATUMtome/mainwindow.h
+++ b/BrainATUMtome/mainwindow.h
@@ -9,6 +9,10 @@
#include "driverepos.h"
#include "drivermicrotome.h"
#include "driversyringe.h"
+#include "videoproducer.h"
+#include "videoconverter.h"
+#include "videowriter.h"
+#include "videoviewer.h"
namespace Ui {
class MainWindow;
@@ -28,20 +32,23 @@ class MainWindow : public QMainWindow
DriverEpos *m_driverEpos;
DriverMicrotome *m_driverMicrotome;
DriverSyringe *m_driverSyringe;
+ VideoProducer *m_videoProducer;
+ VideoConverter *m_videoConverter;
+ VideoWriter *m_videoWriter;
QThread *m_thread_driverEpos;
QThread *m_thread_driverMicrotome;
QThread *m_thread_driverSyringe;
-
-
-
+ QThread *m_thread_videoProducer;
+ QThread *m_thread_videoConverter;
+ QThread *m_thread_videoWriter;
void command_DriverEpos(bool state);
private slots:
+ void on_error_throw(const QString &errorSource, const QString &errorMessage);
void on_pushButton_dep_run_clicked();
void on_pushButton_dmt_cut_clicked();
-
void on_lineEdit_dep_velocity_returnPressed();
signals:
diff --git a/BrainATUMtome/mainwindow.ui b/BrainATUMtome/mainwindow.ui
index a4890de..4b41879 100644
--- a/BrainATUMtome/mainwindow.ui
+++ b/BrainATUMtome/mainwindow.ui
@@ -191,7 +191,7 @@
-
-
+
-
@@ -481,6 +481,14 @@
+
+
+ VideoViewer
+ QWidget
+
+ 1
+
+
diff --git a/BrainATUMtome/videoconverter.cpp b/BrainATUMtome/videoconverter.cpp
new file mode 100644
index 0000000..683e47e
--- /dev/null
+++ b/BrainATUMtome/videoconverter.cpp
@@ -0,0 +1,26 @@
+#include "videoconverter.h"
+
+VideoConverter::VideoConverter(QObject *parent) : QObject(parent)
+{
+
+}
+
+void VideoConverter::on_convertFrame(const cv::Mat &frame)
+{
+ cv::Mat frame_cv = frame;
+ QPixmap pixmap;
+
+ cv::resize(frame_cv, frame_cv, cv::Size(), 0.5, 0.5, cv::INTER_AREA);
+ cv::cvtColor(frame_cv, frame_cv, CV_BGR2RGB);
+ const QImage frame_qt(frame_cv.data,
+ frame_cv.cols,
+ frame_cv.rows,
+ static_cast(frame_cv.step),
+ QImage::Format_RGB888);
+
+
+ pixmap = QPixmap::fromImage(frame_qt);
+
+ //emit imageReady(frame_qt);
+ emit pixmapReady(pixmap);
+}
diff --git a/BrainATUMtome/videoconverter.h b/BrainATUMtome/videoconverter.h
new file mode 100644
index 0000000..2e88751
--- /dev/null
+++ b/BrainATUMtome/videoconverter.h
@@ -0,0 +1,25 @@
+#ifndef VIDEOCONVERTER_H
+#define VIDEOCONVERTER_H
+
+#include
+#include
+#include
+#include
+
+class VideoConverter : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit VideoConverter(QObject *parent = nullptr);
+
+public slots:
+ void on_convertFrame(const cv::Mat &frame);
+
+signals:
+ //void imageReady(const QImage &frame);
+ void pixmapReady(const QPixmap &pixmap);
+
+};
+
+#endif // VIDEOCONVERTER_H
diff --git a/BrainATUMtome/videoproducer.cpp b/BrainATUMtome/videoproducer.cpp
new file mode 100644
index 0000000..ec86091
--- /dev/null
+++ b/BrainATUMtome/videoproducer.cpp
@@ -0,0 +1,69 @@
+#include "videoproducer.h"
+
+VideoProducer::VideoProducer(QObject *parent) : QObject(parent),
+ m_frameIndex(0),
+ m_frameWidth(0),
+ m_frameHeight(0),
+ m_fps(0.0)
+{
+ qRegisterMetaType();
+
+ // configure state machine
+ m_producer = new QStateMachine(this);
+ QState *state_idle = new QState(m_producer);
+ QState *state_acquire = new QState(m_producer);
+ state_idle->addTransition(this, &VideoProducer::start, state_acquire);
+ state_acquire->addTransition(this, &VideoProducer::stop, state_idle);
+ state_acquire->addTransition(this, &VideoProducer::frameReady, state_acquire);
+ connect(state_acquire, &QState::entered, this, &VideoProducer::on_readFrame);
+ m_producer->setInitialState(state_idle);
+ m_producer->start();
+
+ // configure video capture
+ m_videoCapture = new cv::VideoCapture(0);
+ if (!m_videoCapture->isOpened())
+ {
+ m_producer->stop();
+ error("VideoProducer", "failed to open video capture device");
+ return;
+ }
+
+ // share frame properties
+ m_fps = m_videoCapture->get(CV_CAP_PROP_FPS);
+ m_frameWidth = static_cast(m_videoCapture->get(CV_CAP_PROP_FRAME_WIDTH));
+ m_frameHeight = static_cast(m_videoCapture->get(CV_CAP_PROP_FRAME_HEIGHT));
+ connect(this, &VideoProducer::start, [this](){emit frameProperties(m_fps, m_frameWidth, m_frameHeight);});
+}
+
+
+
+VideoProducer::~VideoProducer()
+{
+ if (m_producer->isRunning())
+ m_producer->stop();
+
+ if (m_videoCapture->isOpened())
+ m_videoCapture->release();
+ delete m_videoCapture;
+}
+
+
+
+void VideoProducer::on_readFrame()
+{
+ cv::Mat frame;
+
+ QCoreApplication::processEvents();
+
+ if (!m_videoCapture->read(frame))
+ {
+ m_producer->stop();
+ error("VideoProducer", "failed to read next frame");
+ return;
+ }
+
+ m_frameIndex++;
+
+ emit frameIndex(m_frameIndex);
+ emit frameReady(frame);
+}
diff --git a/BrainATUMtome/videoproducer.h b/BrainATUMtome/videoproducer.h
new file mode 100644
index 0000000..dd24bf3
--- /dev/null
+++ b/BrainATUMtome/videoproducer.h
@@ -0,0 +1,40 @@
+#ifndef VIDEOPRODUCER_H
+#define VIDEOPRODUCER_H
+
+#include
+#include
+#include
+#include
+#include
+
+class VideoProducer : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit VideoProducer(QObject *parent = nullptr);
+ ~VideoProducer();
+
+private:
+ quint32 m_frameIndex;
+ qint32 m_frameWidth;
+ qint32 m_frameHeight;
+ double m_fps;
+ cv::VideoCapture *m_videoCapture;
+ QStateMachine *m_producer;
+
+private slots:
+ void on_readFrame();
+
+signals:
+ void start();
+ void stop();
+ void frameIndex(quint32 index);
+ void frameReady(const cv::Mat &frame);
+ void frameProperties(double fps, int width, int height);
+ void error(const QString &errorSource, const QString &errorMessage);
+};
+
+Q_DECLARE_METATYPE(cv::Mat)
+
+#endif // VIDEOPRODUCER_H
diff --git a/BrainATUMtome/videoviewer.cpp b/BrainATUMtome/videoviewer.cpp
new file mode 100644
index 0000000..b23896e
--- /dev/null
+++ b/BrainATUMtome/videoviewer.cpp
@@ -0,0 +1,15 @@
+#include "videoviewer.h"
+
+VideoViewer::VideoViewer(QWidget *parent) : QGraphicsView (parent)
+{
+ m_scene = new QGraphicsScene(this);
+ m_pixmap = new QGraphicsPixmapItem();
+ this->setScene(m_scene);
+ m_scene->addItem(m_pixmap);
+}
+
+void VideoViewer::on_pixmapReady(const QPixmap &pixmap)
+{
+ m_pixmap->setPixmap(pixmap);
+ this->fitInView(m_pixmap, Qt::KeepAspectRatio);
+}
diff --git a/BrainATUMtome/videoviewer.h b/BrainATUMtome/videoviewer.h
new file mode 100644
index 0000000..5b4a3f0
--- /dev/null
+++ b/BrainATUMtome/videoviewer.h
@@ -0,0 +1,26 @@
+#ifndef VIDEOVIEWER_H
+#define VIDEOVIEWER_H
+
+#include
+#include
+#include
+#include
+#include
+
+class VideoViewer : public QGraphicsView
+{
+ Q_OBJECT
+
+public:
+ explicit VideoViewer(QWidget *parent = nullptr);
+
+private:
+ QGraphicsScene *m_scene;
+ QGraphicsPixmapItem *m_pixmap;
+
+public slots:
+ void on_pixmapReady(const QPixmap &image);
+
+};
+
+#endif // VIDEOVIEWER_H
diff --git a/BrainATUMtome/videowriter.cpp b/BrainATUMtome/videowriter.cpp
new file mode 100644
index 0000000..746ba1c
--- /dev/null
+++ b/BrainATUMtome/videowriter.cpp
@@ -0,0 +1,41 @@
+#include "videowriter.h"
+
+VideoWriter::VideoWriter(QObject *parent) : QObject(parent),
+ m_flag(false)
+{
+ m_videoWriter = new cv::VideoWriter();
+
+ // construct file name based on current date and time
+}
+
+VideoWriter::~VideoWriter()
+{
+ if (m_videoWriter->isOpened())
+ m_videoWriter->release();
+ delete m_videoWriter;
+}
+
+
+void VideoWriter::on_open(double fps, int width, int height)
+{
+ if (!m_flag)
+ return;
+
+ QString filePath = QStandardPaths::displayName(QStandardPaths::DataLocation);
+ QString fileName = QDateTime::currentDateTime().toString("BrainATUMtome_yyyyMMdd-hhmmss");
+
+ QString fileFull = QString("%1%2.%3").arg(filePath, fileName, "avi");
+ qDebug() << "Export file name " << fileFull;
+ m_videoWriter->open(fileFull.toStdString(), CV_FOURCC('M','J','P','G'), fps, cv::Size(width, height));
+}
+
+
+void VideoWriter::on_export(bool flag)
+{
+ m_flag = flag;
+}
+
+void VideoWriter::on_write(const cv::Mat &frame)
+{
+ m_videoWriter->write(frame);
+}
diff --git a/BrainATUMtome/videowriter.h b/BrainATUMtome/videowriter.h
new file mode 100644
index 0000000..79d3b13
--- /dev/null
+++ b/BrainATUMtome/videowriter.h
@@ -0,0 +1,32 @@
+#ifndef VIDEOWRITER_H
+#define VIDEOWRITER_H
+
+#include
+#include
+#include
+#include
+#include
+
+class VideoWriter : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit VideoWriter(QObject *parent = nullptr);
+ ~VideoWriter();
+
+private:
+ bool m_flag;
+ cv::VideoWriter *m_videoWriter;
+
+public slots:
+ void on_export(bool flag);
+ void on_open(double fps, qint32 width, qint32 height);
+ void on_write(const cv::Mat &frame);
+
+signals:
+ void error(const QString &errorSource, const QString &errorMessage);
+
+};
+
+#endif // VIDEOWRITER_H