我想在Qt3D中(通过纹理)显示来自捕获设备的图像流。
所以我将QPaintedTextureImage
归为子类:
#include <Qt3DRender/QPaintedTextureImage>
#include <QPainter>
#include <QImage>
#include <QPaintDevice>
#include <opencv2/opencv.hpp>
class OpenCVCaptureImage : public Qt3DRender::QPaintedTextureImage
{
public:
explicit OpenCVCaptureImage(Qt3DCore::QNode *parent = nullptr);
void paint(QPainter *painter) override;
private:
cv::VideoCapture cap_;
};
OpenCVCaptureImage::OpenCVCaptureImage(Qt3DCore::QNode *parent)
: Qt3DRender::QPaintedTextureImage(parent),
cap_(0)
{
}
void OpenCVCaptureImage::paint(QPainter *painter)
{
cv::Mat frame;
cap_ >> frame;
QImage im(static_cast<uchar *>(frame.data), frame.cols, frame.rows, int(frame.step), QImage::Format_RGB888);
if(im.isNull()) return;
setSize(im.size());
//int w = painter->device()->width();
//int h = painter->device()->height();
painter->drawImage(0, 0, im);
}
必须QPaintedTextureImage的子类,并且必须实现虚拟paint()函数。每次在QPaintedTextureImage上调用update()时,都会调用paint()函数并上传结果图像。
因此我在场景树中添加了Timer
,并在onTriggered
插槽中调用了capImage.update()
,但是在运行时出现了问题:
2019-01-31 22:48:54.865282 + 0100 Qt3DOpenCV [50001:4569220] qrc:/MyScene.qml:57:TypeError:Object Qt3DRender :: QPaintedTextureImage(0x106ef6bf0的属性'update' )不是功能
main.cpp:
#include <QGuiApplication>
#include <Qt3DQuickExtras/qt3dquickwindow.h>
#include "opencvcaptureimage.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
qmlRegisterType<OpenCVCaptureImage>("OpenCVCaptureImage", 1, 0, "OpenCVCaptureImage");
QGuiApplication app(argc, argv);
Qt3DExtras::Quick::Qt3DQuickWindow view;
view.setSource(QUrl("qrc:/MyScene.qml"));
view.show();
return app.exec();
}
MyScene.qml:
import Qt3D.Core 2.0
import Qt3D.Render 2.0
import Qt3D.Input 2.0
import Qt3D.Extras 2.0
import OpenCVCaptureImage 1.0
import QtQml 2.12
Entity {
id: sceneRoot
RenderSettings {
id: renderSettings
activeFrameGraph: ForwardRenderer {
clearColor: Qt.rgba(0, 0.5, 1, 1)
camera: Camera {
id: objectsCamera
projectionType: CameraLens.PerspectiveProjection
fieldOfView: 45
aspectRatio: 16/9
nearPlane : 0.1
farPlane : 1000.0
position: Qt.vector3d( 0.0, 0.0, -40.0 )
upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
}
}
}
InputSettings {
id: inputSettings
}
components: [renderSettings, inputSettings]
PlaneMesh {
id: planeMesh
width: 2
height: 2
}
TextureMaterial {
id: planeMaterial
texture: Texture2D {
id: planeTexture
textureImages: [
OpenCVCaptureImage {
id: capImage
}
]
}
}
Timer {
interval: 500
running: true
repeat: true
onTriggered: capImage.update()
}
Transform {
id: planeTransform
rotationX: 90
}
Entity {
id: planeEntity
components: [ planeMesh, planeMaterial, planeTransform ]
}
}
编辑:我还尝试将计时器放入C ++构造函数中
OpenCVCaptureImage::OpenCVCaptureImage(Qt3DCore::QNode *parent)
: Qt3DRender::QPaintedTextureImage(parent),
cap_(0)
{
QTimer::singleShot(2500, [=] {
auto t = new QTimer(this);
connect(t, &QTimer::timeout, [=] {
this->update();
});
t->setInterval(200);
t->start();
});
}
在这种情况下,程序在QPainter::drawImage
中崩溃,并且此错误被打印到控制台:
2019-02-01 11:15:45.754907 + 0100 Qt3DOpenCV [55788:4839633] QPaintDevice:无法销毁正在绘制的绘制设备
答案 0 :(得分:0)
我不太确定自己在做什么错,但是我在this example中成功使用了QPaintedTextureImage
并添加了一个计时器,该计时器可以定期更新纹理。 Qt3D不会直接调用它,但是您可以像您在问题中建议的那样进行调用。也许尝试清理项目,然后运行qmake并随后进行构建。