Ich habe ein Problem OpenCv Mat von anderen Thread zu lesen und es in QML anzuzeigen.OpenCV + QML (Rahmen von einem anderen Thread)
Zunächst erstelle ich Mat in anderen Thread und verhindern, dass es aktualisieren, bis QML wird es nicht angezeigt werden:
void DesktopVideoProducer::process(){
while(true){
if(!camera.isOpened())
camera.open("http://192.168.43.1:8080/video");
camera >> mat;
if(!frameReady && !mat.empty()){
outMat = cv::Mat(10, 10, 1);
qDebug() << "!!!! = " << outMat.data;
frameReady = true;
}
}
}
In qDebug() << "!!!! = " << outMat.data;
ich sehe, dass outMat Daten hat !!!! = 0x38824980
Hier versuche ich, diese Matte angezeigt werden in QML:
void DesktopVideoProducer::timerEvent(QTimerEvent*)
{
if (!_surface) return;
if(frameReady)
qDebug() << "ddd = " << outMat.data;
if(frameReady && !outMat.empty())
{
cv::cvtColor(outMat, outMat, cv::COLOR_BGR2BGRA);
QImage screenImage((uchar*)outMat.data, outMat.cols, outMat.rows, outMat.step, QImage::Format_RGB32);
if(QSize(winWidth, winHeight) != _format.frameSize())
{
qDebug() << "newSize";
closeSurface();
_format = QVideoSurfaceFormat(QSize(winWidth, winHeight), QVideoFrame::PixelFormat::Format_RGB32);
_surface->start(_format);
}
_surface->present(QVideoFrame(screenImage));
frameReady = false;
}
}
Aber wenn ich versuche Mat hier zu lesen:
if(frameReady)
qDebug() << "ddd = " << outMat.data;
es zeigt, dass keine Daten in diesem outMat: ddd = 0x0
Und ich kann nicht ohne einen Frame von einem anderen Thread angezeigt werden soll. Hier ist mein Code:
DesktopVideoProducer.h
#include <QQmlApplicationEngine>
#include <QAbstractVideoSurface>
#include <QVideoSurfaceFormat>
#include <QTimer>
#include <QTime>
#include <opencv2/opencv.hpp>
class DesktopVideoProducer : public QObject
{
Q_OBJECT
Q_PROPERTY(QAbstractVideoSurface* videoSurface READ videoSurface WRITE setVideoSurface)
public:
explicit DesktopVideoProducer(QObject *parent = 0);
~DesktopVideoProducer();
QAbstractVideoSurface* videoSurface() const;
void setVideoSurface(QAbstractVideoSurface* s);
void Initialization();
public slots:
void timerEvent(QTimerEvent*);
private:
void closeSurface();
private:
QAbstractVideoSurface* _surface;
QVideoSurfaceFormat _format;
QQmlApplicationEngine engine;
cv::VideoCapture camera;
cv::Mat mat;
cv::Mat outMat;
QImage screenImage;
void process();
};
DesktopVideoProducer.cpp
#include "DesktopVideoProducer.h"
#include <QApplication>
#include <QtConcurrent/QtConcurrent>
#include <QDebug>
#include <QMutex>
QMutex mutex;
int winWidth, winHeight;
bool isInit = false;
bool frameReady = false;
DesktopVideoProducer::DesktopVideoProducer(QObject *parent)
: QObject(parent), _surface(nullptr)
{
startTimer(1000/15); //15 fps
}
DesktopVideoProducer::~DesktopVideoProducer()
{
closeSurface();
}
QAbstractVideoSurface* DesktopVideoProducer::videoSurface() const
{
return _surface;
}
void DesktopVideoProducer::Initialization(){
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
QtConcurrent::run(this, DesktopVideoProducer::process);
winWidth = engine.rootObjects()[0]->property("width").toInt();
winHeight = engine.rootObjects()[0]->property("height").toInt();
}
void DesktopVideoProducer::process(){
while(true){
if(!camera.isOpened())
camera.open("http://192.168.43.1:8080/video");
camera >> mat;
if(!frameReady && !mat.empty()){
outMat = cv::Mat(10, 10, 1);
qDebug() << "!!!! = " << outMat.data;
frameReady = true;
}
}
}
void DesktopVideoProducer::setVideoSurface(QAbstractVideoSurface* s)
{
closeSurface();
_surface = s;
}
void DesktopVideoProducer::closeSurface()
{
if(_surface && _surface->isActive())
_surface->stop();
}
void DesktopVideoProducer::timerEvent(QTimerEvent*)
{
if (!_surface) return;
if(frameReady)
qDebug() << "ddd = " << outMat.data;
if(frameReady && !outMat.empty())
{
cv::cvtColor(outMat, outMat, cv::COLOR_BGR2BGRA);
QImage screenImage((uchar*)outMat.data, outMat.cols, outMat.rows, outMat.step, QImage::Format_RGB32);
if(QSize(winWidth, winHeight) != _format.frameSize())
{
qDebug() << "newSize";
closeSurface();
_format = QVideoSurfaceFormat(QSize(winWidth, winHeight), QVideoFrame::PixelFormat::Format_RGB32);
_surface->start(_format);
}
_surface->present(QVideoFrame(screenImage));
frameReady = false;
}
}
Main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
#include"DesktopVideoProducer.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
qmlRegisterType<DesktopVideoProducer>("DesktopVideoProducer", 0, 1, "DesktopVideoProducer");
DesktopVideoProducer videoProvider;
videoProvider.Initialization();
return app.exec();
}
main.qml
import QtQuick 2.2
import QtQuick.Window 2.1
import QtMultimedia 5.0
import DesktopVideoProducer 0.1
Window {
visible: true
visibility: "Maximized"
id: root
DesktopVideoProducer {
id: videoProducer;
}
VideoOutput {
anchors.fill: parent
source: videoProducer;
}
}
Was soll ich tun?
Natürlich kann es die Debug-Sitzung usw. wert Der Zweck von SO besteht jedoch darin, Codierungshinweise zu finden. Versuchen Sie ein funktionierendes Beispiel und führen Sie es aus und beginnen Sie, es Stück für Stück zu ändern, schätze ich. 'QtConcurrent' wird hier vielleicht nicht benötigt. Es ist keine massive Parallelverarbeitung. Verwende 'QThread'. – AlexanderVX
Wirklich, ich fand, dass diese Methode 'cv :: Mat outFrame; cvtColor (inFrame, outFrame, conversionType); 'arbeiten schneller als das' cv :: cvtColor (outMat, outMat, cv :: COLOR_BGR2BGRA); '. Vielen Dank! – DYY
M ... also nicht sicher, wie die Konvertierung dieses "in-place" outMat -> outMat überhaupt überhaupt funktioniert hat. Das ist ein Geheimnis. – AlexanderVX