Hello everyone,
It's been a while that I am trying to come up with a method to do some image processing and displaying results in a Widget, that is a child of MainWindow, on frames that I get from a camera (maybe at rate of 25 frames/sec). So, I started by reading tones of documents and forums and etc to find the method, and so far I have been able to implement this application. Since image processing algorithms are computationally intensive, I thought it would be a good idea to use QThread in my project. I found mandelbrot example extremely useful for my purpose.
http://doc.qt.io/qt-5/qtcore-threads...t-example.html
Like the example:
- I created a class to display image (mQtPaintWidget). Then I added a Widget to my central widget in mainwindow.ui and promoted to this class and called it Screen. I also added a Text Edit to my central widget and called it Console.
- I created a class to assign a thread for my image processing algorithms (RenderThread).
Before writing a class to handle my camera, I wanted to test if I can display noise using qrand() function but it does not run the way I expect. I got it to work till the paintevent checks the pixmap to see if it is NULL and draws a text on Screen.
I copied my codes down here. I would appreciate if any body can suggest any solution.
cheers
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
MainWindow w;
w.show();
return app.exec();
}
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.show();
return app.exec();
}
To copy to clipboard, switch view to plain text mode
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QWidget>
namespace Ui {
class MainWindow;
}
{
Q_OBJECT
public:
explicit MainWindow
(QWidget *parent
= 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QWidget>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
To copy to clipboard, switch view to plain text mode
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow
::MainWindow(QWidget *parent
) : ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->Console->setPalette(p);
}
MainWindow::~MainWindow()
{
delete ui;
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPalette p = palette();
p.setColor(QPalette::Base, Qt::black);
p.setColor(QPalette::Text, Qt::green);
ui->Console->setPalette(p);
}
MainWindow::~MainWindow()
{
delete ui;
}
To copy to clipboard, switch view to plain text mode
renderthread.h
#ifndef RENDERTHREAD_H
#define RENDERTHREAD_H
#include <QWidget>
#include <QMutex>
#include <QThread>
#include <QWaitCondition>
QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
class RenderThread
: public QThread{
Q_OBJECT
public:
~RenderThread();
void render();
signals:
void renderedImage
(const QImage &image
);
protected:
void run() Q_DECL_OVERRIDE;
private:
bool restart;
bool abort;
};
#endif // RENDERTHREAD_H
#ifndef RENDERTHREAD_H
#define RENDERTHREAD_H
#include <QWidget>
#include <QMutex>
#include <QThread>
#include <QWaitCondition>
QT_BEGIN_NAMESPACE
class QImage;
QT_END_NAMESPACE
class RenderThread : public QThread
{
Q_OBJECT
public:
RenderThread(QObject *parent = 0);
~RenderThread();
void render();
signals:
void renderedImage(const QImage &image);
protected:
void run() Q_DECL_OVERRIDE;
private:
QMutex mutex;
QWaitCondition condition;
QSize frameSize;
bool restart;
bool abort;
};
#endif // RENDERTHREAD_H
To copy to clipboard, switch view to plain text mode
renderthread.cpp
#include "renderthread.h"
RenderThread
::RenderThread(QObject *parent
){
restart = false;
abort = false;
}
RenderThread::~RenderThread()
{
mutex.lock();
abort = true;
condition.wakeOne();
mutex.unlock();
wait();
}
void RenderThread::render()
{
if (!isRunning()) {
start(LowPriority);
} else {
restart = true;
condition.wakeOne();
}
}
void RenderThread::run()
{
forever
{
mutex.lock();
if (restart || abort)
return;
mutex.unlock();
uint imWidth = 600;
uint imHeight = 480;
QSize frameSize
(imWidth,imHeight
);
for(uint i = 0; i < imHeight; ++i)
{
uint *scanLine = reinterpret_cast<uint *>(image.scanLine(i));
for(uint j = 0; j < imWidth; ++j)
*scanLine++ = (qrand() > RAND_MAX/2) * 255;
}
if (!restart)
emit renderedImage(image);
mutex.lock();
if (!restart)
condition.wait(&mutex);
restart = false;
mutex.unlock();
}
}
#include "renderthread.h"
RenderThread::RenderThread(QObject *parent)
: QThread(parent)
{
restart = false;
abort = false;
}
RenderThread::~RenderThread()
{
mutex.lock();
abort = true;
condition.wakeOne();
mutex.unlock();
wait();
}
void RenderThread::render()
{
QMutexLocker locker(&mutex);
if (!isRunning()) {
start(LowPriority);
} else {
restart = true;
condition.wakeOne();
}
}
void RenderThread::run()
{
forever
{
mutex.lock();
if (restart || abort)
return;
mutex.unlock();
uint imWidth = 600;
uint imHeight = 480;
QSize frameSize(imWidth,imHeight);
QImage image(frameSize,QImage::Format_Indexed8);
for(uint i = 0; i < imHeight; ++i)
{
uint *scanLine = reinterpret_cast<uint *>(image.scanLine(i));
for(uint j = 0; j < imWidth; ++j)
*scanLine++ = (qrand() > RAND_MAX/2) * 255;
}
if (!restart)
emit renderedImage(image);
mutex.lock();
if (!restart)
condition.wait(&mutex);
restart = false;
mutex.unlock();
}
}
To copy to clipboard, switch view to plain text mode
mqtpaintwidget.h
#ifndef MQTPAINTERWIDGET_H
#define MQTPAINTERWIDGET_H
#include <QWidget>
#include <QPixmap>
#include <QPainter>
#include "renderthread.h"
class mQtPainterWidget
: public QWidget{
Q_OBJECT
public:
explicit mQtPainterWidget
(QWidget *parent
= 0);
protected:
private slots:
void updatePixmap
(const QImage &image
);
private:
RenderThread thread;
};
#endif // MQTPAINTERWIDGET_H
#ifndef MQTPAINTERWIDGET_H
#define MQTPAINTERWIDGET_H
#include <QWidget>
#include <QPixmap>
#include <QPainter>
#include "renderthread.h"
class mQtPainterWidget : public QWidget
{
Q_OBJECT
public:
explicit mQtPainterWidget(QWidget *parent = 0);
protected:
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
private slots:
void updatePixmap(const QImage &image);
private:
RenderThread thread;
QPixmap pixmap;
};
#endif // MQTPAINTERWIDGET_H
To copy to clipboard, switch view to plain text mode
mqtpaintwidget.cpp
#include "mqtpainterwidget.h"
mQtPainterWidget
::mQtPainterWidget(QWidget *parent
) :{
connect(&thread,
SIGNAL(renderedImage
(QImage)),
this,
SLOT(updatePixmap
(QImage)));
//thread.render();
}
{
Q_UNUSED(event);
painter.fillRect(rect(), Qt::black);
if (pixmap.isNull()) {
painter.setPen(Qt::green);
painter.drawText(rect(), Qt::AlignCenter, tr("Rendering initial image, please wait..."));
return;
}
painter.drawPixmap(0,0,pixmap);
}
void mQtPainterWidget
::updatePixmap(const QImage &image
) {
pixmap
= QPixmap::fromImage(image
);
update();
}
#include "mqtpainterwidget.h"
mQtPainterWidget::mQtPainterWidget(QWidget *parent) :
QWidget(parent)
{
connect(&thread, SIGNAL(renderedImage(QImage)), this, SLOT(updatePixmap(QImage)));
//thread.render();
}
void mQtPainterWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
painter.fillRect(rect(), Qt::black);
if (pixmap.isNull()) {
painter.setPen(Qt::green);
painter.drawText(rect(), Qt::AlignCenter, tr("Rendering initial image, please wait..."));
return;
}
painter.drawPixmap(0,0,pixmap);
}
void mQtPainterWidget::updatePixmap(const QImage &image)
{
pixmap = QPixmap::fromImage(image);
update();
}
To copy to clipboard, switch view to plain text mode
screenshot.jpg
Bookmarks