OpenCV + QML(从另一个线程抓取帧)
OpenCV + QML (grabbing frame from another thread)
我从其他线程读取OpenCv Mat并在QML中显示它时遇到问题。
首先,我在其他线程中创建 Mat 并阻止更新它,直到 QML 不显示它:
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;
}
}
}
在qDebug() << "!!!! = " << outMat.data;
我看到 outMat 有数据!!!! = 0x38824980
在这里,我尝试在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;
}
}
但是当我尝试在这里阅读 Mat 时:
if(frameReady)
qDebug() << "ddd = " << outMat.data;
它显示此 outMat:ddd = 0x0
中没有数据
而且我无法显示来自另一个线程的帧。这是我的代码:
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();
};
桌面视频制作人.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;
}
}
主.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();
}
主.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;
}
}
我该怎么办?
这段代码可能不正确,并暗示在执行转换时覆盖了源:
cv::cvtColor(outMat, outMat, cv::COLOR_BGR2BGRA);
转换应该我更像:
cv::Mat outFrame;
cvtColor(inFrame, outFrame, conversionType); // cvtColor makes copy
相关文章:
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 如何将元素添加到数组的线程安全函数?
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 异常属于C++中的线程还是进程
- C++中的线程安全删除
- C++使用params创建线程函数会导致转换错误
- 类与私有变量的其他类之间的线程安全性
- CoInitialize()在单独的线程上崩溃而不返回
- c++中的线程池
- 线程之间的布尔停止信号
- 为什么std::async使用同一个线程运行函数
- 如何抓取指向Qt中弹出对话框的指针,该对话框阻止了QTest中的UI线程
- C++生产者使用者中,同一使用者线程会抓取所有任务
- OpenCV + QML(从另一个线程抓取帧)