Событие рисования QGraphicsScene внутри QGraphicsProxyWidget

Я транслирую с веб-камеры, используя OpenCV. Каждый захваченный кадр (тип cv::Mat) передается через пользовательский сигнал в слоты на основе узла QGraphicsScene, Так как у меня есть один тип узла, который на самом деле требует отображения cv::Mat в то время как остальное только для обработки данных, которые я создал зритель виджет, который преобразует cv::Mat данные для QImage данные, а затем с помощью paintEvent() рисует его на своей поверхности:

На основе узла QGraphicsScene - внутренние события рисования

Вот код самого виджета:

qcvn_node_viewer.hpp

#ifndef QCVN_NODE_VIEWER_HPP
#define QCVN_NODE_VIEWER_HPP

#include <QWidget>
#include <QImage>
#include <QSize>
#include <QPaintEvent>
#include <opencv2/core.hpp>

class QCVN_Node_Viewer : public QWidget
{
Q_OBJECT
QImage output;

public:
explicit QCVN_Node_Viewer(QWidget *parent = 0);
~QCVN_Node_Viewer();

QSize sizeHint() const;
QSize minimumSizeHint() const;

// Source: http://stackoverflow.com/a/17137998/1559401
static QImage Mat2QImage(cv::Mat const& frame);
static cv::Mat QImage2Mat(QImage const& src);

protected:
void paintEvent(QPaintEvent *event);

signals:
// Nodes connect to sendFrame(cv::Mat) signal
void sendFrame(cv::Mat);

public slots:
void receiveFrame(cv::Mat frame);
};

#endif // QCVN_NODE_VIEWER_HPP

qcvn_node_viewer.cpp

#include "qcvn_node_viewer.hpp"#include <opencv2/imgproc.hpp>
#include <QPainter>

QCVN_Node_Viewer::QCVN_Node_Viewer(QWidget *parent) :
QWidget(parent)
{
qRegisterMetaType<cv::Mat>("cv::Mat");
}

QCVN_Node_Viewer::~QCVN_Node_Viewer()
{
}

QSize QCVN_Node_Viewer::sizeHint() const
{
return output.size();
}

QSize QCVN_Node_Viewer::minimumSizeHint() const
{
return output.size();
}

QImage QCVN_Node_Viewer::Mat2QImage(cv::Mat const& frame)
{
cv::Mat temp;
cvtColor(frame, temp,CV_BGR2RGB);
QImage dest((const uchar *) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
dest.bits(); // enforce deep copy
return dest;
}

cv::Mat QCVN_Node_Viewer::QImage2Mat(QImage const& frame)
{
cv::Mat tmp(frame.height(),frame.width(),CV_8UC3,(uchar*)frame.bits(),frame.bytesPerLine());
cv::Mat result; // deep copy just in case (my lack of knowledge with open cv)
cvtColor(tmp, result,CV_BGR2RGB);
return result;
}

void QCVN_Node_Viewer::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.drawImage(QPoint(0,0), output);
painter.end();
}

void QCVN_Node_Viewer::receiveFrame(cv::Mat frame)
{
if(frame.empty()) return;

// Pass along the received frame
emit sendFrame(frame);

// Generate
// http://stackoverflow.com/questions/17127762/cvmat-to-qimage-and-back
// Applications crashes sometimes! Conversion seems to be incorrect
output = Mat2QImage(frame);
output.bits();
setFixedSize(output.width(), output.height());

repaint();
}

Как вы можете видеть на скриншоте выше QWidget встроен в QGraphicsScene с помощью QGraphicsProxyWidget вместе с QGraphicsRectItem что я использую для выбора / перемещения узла в сцене.

С помощью QPainter считается более эффективным, чем использование QLabel и настройки его QPixmap в захваченный и преобразованный кадр. Использование области просмотра OpenGL внутри QGraphicsScene насколько я знаю это не вариант. Кажется, что обработка событий рисования в сцене также обрабатывает локальные события внутри QGraphicsItemс и QGraphicsProxyWidgets. Кадр, который зритель краски на его поверхности изменяются только когда вызывается обработчик события рисования сцены (наведение некоторых моих узлов, перемещение их и т. д.).

Есть ли способ это исправить? Я собираюсь пойти на QLabel+QPixmap вариант (хотя я не уверен, что он не будет страдать от той же или другой проблемы), но сначала я хотел бы убедиться, что я ничего не могу сделать, чтобы сохранить свой текущий способ делать вещи.


РЕДАКТИРОВАТЬ: Итак, я изменил мой зритель использовать QLabel вместо события рисования виджета, и он работает как шарм. Вопрос все еще открыт, так как я хотел бы знать, как использовать локальные события рисования.

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]