- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试在 QML 图像中显示 OpenCV Mat。
我使用 OpenCV 从相机抓取帧,帧在 QML 中成功显示,但内存使用量随着时间的推移而增加。我该如何解决?这是我的代码:
主要.cpp
#include <QGuiApplication>
#include "videoprovider.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
VideoProvider videoProvider;
return app.exec();
}
VideoProvider.h
#ifndef VIDEOPROVIDER_H
#define VIDEOPROVIDER_H
#include <QObject>
#include <QFuture>
#include <QImage>
#include <QQmlApplicationEngine>
#include <QQuickImageProvider>
#include <opencv2/opencv.hpp>
class VideoProvider : public QObject, public QQuickImageProvider
{
Q_OBJECT
public:
explicit VideoProvider();
QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize);
signals:
void frameChanged();
public slots:
void framePainted();
private:
QQmlApplicationEngine engine;
bool readyfor;
cv::Mat mat;
QImage outputImage;
void process();
};
#endif // VIDEOPROVIDER_H
VideoProvider.cpp
#include <QQmlContext>
#include <QtConcurrent/QtConcurrent>
#include <QDebug>
#include <QThread>
#include "videoprovider.h"
#include <QQuickImageProvider>
VideoProvider::VideoProvider() : QQuickImageProvider (QQuickImageProvider :: Pixmap)
{
engine.rootContext()->setContextProperty("videoProvider", this);
engine.addImageProvider(QLatin1String ("videoCapture"), this);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
readyfor = true;
QtConcurrent::run(this, VideoProvider::process);
}
void VideoProvider::framePainted()
{
readyfor = true;
}
void VideoProvider::process()
{
cv::VideoCapture capture(0);
while(true){
QThread::currentThread()->msleep(80);
if(!readyfor) continue;
mat.release();
capture >> mat;
if(mat.empty())
{
qDebug()<<"disconnect";
}
else
{
readyfor = false;
cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB);
outputImage = QImage((uchar*)mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
emit frameChanged();
}
}
capture.release();
}
QPixmap VideoProvider::requestPixmap(const QString &id, QSize *size, const QSize& requestedSize)
{
return QPixmap::fromImage(outputImage);
}
主.qml
import QtQuick 2.6
import QtQuick.Window 2.2
Window
{
visible: true
width: 640
height: 480
title: qsTr("Hello World")
id: root
Image{
id: videoLayer
anchors.fill: parent
cache: false
onSourceChanged:{
videoProvider.framePainted();
}
}
Connections
{
target: videoProvider
property int frameCounter: 0
onFrameChanged:
{
videoLayer.source = "image://videoCapture/hoge" + frameCounter;
frameCounter ^= 1;
}
}
}
我发现它发生在我向 QML 发送信号 (emit frameChanged();) 时。
更新:
Valgrind 日志:
==18038== Memcheck, a memory error detector
==18038== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==18038== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==18038== Command: ./prog
==18038==
QML debugging is enabled. Only use this in a safe environment.
==18038== Warning: noted but unhandled ioctl 0x30000001 with no size/direction hints.
==18038== This could cause spurious value errors to appear.
==18038== See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
==18038== Warning: noted but unhandled ioctl 0x27 with no size/direction hints.
==18038== This could cause spurious value errors to appear.
==18038== See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
==18038== Warning: noted but unhandled ioctl 0x7ff with no size/direction hints.
==18038== This could cause spurious value errors to appear.
==18038== See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
==18038== Warning: noted but unhandled ioctl 0x25 with no size/direction hints.
==18038== This could cause spurious value errors to appear.
==18038== See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
==18038== Warning: noted but unhandled ioctl 0x17 with no size/direction hints.
==18038== This could cause spurious value errors to appear.
==18038== See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
==18038== Warning: set address range perms: large range [0x200000000, 0x500000000) (noaccess)
==18038== Warning: set address range perms: large range [0x500000000, 0x700000000) (noaccess)
==18038== Warning: noted but unhandled ioctl 0x19 with no size/direction hints.
==18038== This could cause spurious value errors to appear.
==18038== See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
==18038== Warning: noted but unhandled ioctl 0x21 with no size/direction hints.
==18038== This could cause spurious value errors to appear.
==18038== See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
==18038== Warning: noted but unhandled ioctl 0x1b with no size/direction hints.
==18038== This could cause spurious value errors to appear.
==18038== See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper.
==18038== Thread 8 Thread (pooled):
==18038== Invalid read of size 4
==18038== at 0xAF682D0: QImage::~QImage() (in /home/dmytro/Qt/5.9.1/gcc_64/lib/libQt5Gui.so.5.9.1)
==18038== by 0x40570F: VideoProvider::process() (videoprovider.cpp:50)
==18038== by 0x406AEB: QtConcurrent::VoidStoredMemberFunctionPointerCall0<void, VideoProvider>::runFunctor() (qtconcurrentstoredfunctioncall.h:205)
==18038== by 0x405FC6: QtConcurrent::RunFunctionTask<void>::run() (qtconcurrentrunbase.h:136)
==18038== by 0xBC44BA2: ??? (in /home/dmytro/Qt/5.9.1/gcc_64/lib/libQt5Core.so.5.9.1)
==18038== by 0xBC48849: ??? (in /home/dmytro/Qt/5.9.1/gcc_64/lib/libQt5Core.so.5.9.1)
==18038== by 0xCE456B9: start_thread (pthread_create.c:333)
==18038== by 0xC9773DC: clone (clone.S:109)
==18038== Address 0x23d1b260 is 0 bytes inside a block of size 128 free'd
==18038== at 0x4C2F24B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18038== by 0xAF682F3: QImage::~QImage() (in /home/dmytro/Qt/5.9.1/gcc_64/lib/libQt5Gui.so.5.9.1)
==18038== by 0x4047CB: VideoProvider::~VideoProvider() (videoprovider.h:11)
==18038== by 0x403A34: main (main.cpp:8)
==18038== Block was alloc'd at
==18038== at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18038== by 0xAF656BE: QImageData::create(unsigned char*, int, int, int, QImage::Format, bool, void (*)(void*), void*) (in /home/dmytro/Qt/5.9.1/gcc_64/lib/libQt5Gui.so.5.9.1)
==18038== by 0xAF65971: QImage::QImage(unsigned char*, int, int, int, QImage::Format, void (*)(void*), void*) (in /home/dmytro/Qt/5.9.1/gcc_64/lib/libQt5Gui.so.5.9.1)
==18038== by 0x4056E2: VideoProvider::process() (videoprovider.cpp:50)
==18038== by 0x406AEB: QtConcurrent::VoidStoredMemberFunctionPointerCall0<void, VideoProvider>::runFunctor() (qtconcurrentstoredfunctioncall.h:205)
==18038== by 0x405FC6: QtConcurrent::RunFunctionTask<void>::run() (qtconcurrentrunbase.h:136)
==18038== by 0xBC44BA2: ??? (in /home/dmytro/Qt/5.9.1/gcc_64/lib/libQt5Core.so.5.9.1)
==18038== by 0xBC48849: ??? (in /home/dmytro/Qt/5.9.1/gcc_64/lib/libQt5Core.so.5.9.1)
==18038== by 0xCE456B9: start_thread (pthread_create.c:333)
==18038== by 0xC9773DC: clone (clone.S:109)
最佳答案
I grab frames from camera with OpenCV, the frames are displayed successfully in QML, but memory usage increases with time. How can I fix it?
下面的前提条件是视频捕获处理图像的速度不超过每帧 1000 毫秒/80 毫秒 = 每秒 12.5 帧(实际上由于处理时间而更少),而标准相机速率在 25 到 80 的范围内。那这就是为什么图像帧卡在 OpenCV 等的内部缓冲区中的原因。只要操作系统仍然能够放弃其他线程的时间片,在这里等待 1 到 5 毫秒(必须足够)不会有什么坏处。我个人使用 C++ 11 中的条件变量或来自 Qt而不是“ sleep ”。使用条件变量,我们可以更优雅地中断等待等。
while(true){
QThread::currentThread()->msleep(80); // too much wait
// also just do QThread::msleep instead
if(!readyfor) continue;
mat.release();
capture >> mat
关于c++ - 内存泄漏(OpenCV + QML),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47071828/
如果下一个元素的宽度超过指定布局的宽度,是否有 QML 布局或某些配置会自动将 QML 项目包装到下一行? 当我使用 QML GridLayout ,项目刚好离开窗口的边缘并被剪裁: GridLayo
如果下一个元素的宽度超过指定布局的宽度,是否有 QML 布局或某些配置会自动将 QML 项目包装到下一行? 当我使用 QML GridLayout ,项目刚好离开窗口的边缘并被剪裁: GridLayo
如何在 qml 文件之间发送变量或信号? http://i.stack.imgur.com/MChCG.png Mainwindow -> 创建组件Item2.qml MainWindow -> 创建
我正在做一些事情,我有一个名为“FloatingMenu”的类(它应该在 C++ 中管理菜单)及其在文件 FloatingMenu.qml 中用于 GUI 的 QML alter-ego。我有一个文件
我正在尝试做一些看似简单的事情,但失败了:定义一个简单的内联文本格式组件,然后用不同的文本多次实例化它。这是代码 Item { . . . Component { id: favButtonL
我可以在页面中使用 InvokeActionItem 轻松共享项目,但我需要能够在 ListView 项目中调用它。我设法触发了一个调用,但我不知道如何在触发它时添加数据。我不断收到错误消息 Invo
我如何在 QML 中检测 Window {} 之外的点击? Rectangle { id: topLevel height: 400; width: 400 Window {
我试过 : var child = grid.children[slot1]; grid.children[slot1] = grid.children[slot2]; grid.children[s
例如,我希望创建一个包含 100 个文本编辑器的 qml 窗口,如何在循环中创建它?那可能吗? 最佳答案 循环是命令式代码,所以它不是 QML,而是 Javascript 或 C++。所以当然,你可以
这是我的 QML 文件,其中包含一个文本组件: import QtQuick 2.0 Item { id: idItmWrapText Text { id: idTxt
我正在寻找一种方法来显示一个文本提示,说明预期的输入作为对用户的建议。以谷歌搜索栏为例: 是否有我缺少的属性,或者这是必须通过脚本来实现的? 最佳答案 Qt Quick 输入项上不存在该属性。您可以为
为 qml 项设置背景的最简单方法是让子矩形的 anchor 完全填满父项: Item { width: 320 height: 240 Rectangle {
我想将属性动态添加到 QML 元素: Item { id: dynamicProperty; property int first; Component.onCompleted: { /*
我用 PySide 和 QML 编写了某种安装程序。按照设计,它必须是多页的。而且我想将要从 QML 表单调用的插槽划分为不同的对象(理想情况下,划分为模块,但据我了解,带有插槽的对象必须继承 QOb
QML 中有没有办法用 opacity: 0 创建一个矩形?仍然有可见的边界?如果没有,有关如何解决它的任何建议? 谢谢 最佳答案 不,不透明度适用于项目的完整视觉方面(并且不透明度:0 使项目完全不
属性变体 a:{}似乎不起作用。 a 最终未定义,而不是一个空字典。 我对 Javascript 不是很有经验...初始化属性以保存空字典的正确方法是什么? 以下 qml 在控制台上打印“qrc:/m
我在 SO 上查看了大量关于 QML 内容边距的问题,但所有答案都指向缺少 spacing: 0 属性。我已经完成了所有这些,但仍然有一些我无法消除的奇怪空间。任何人都可以解释为什么这个 QML 代码
我有一个用于样式定义的 QML 单例,定义如下: pragma Singleton import QtQuick 2.2 import QtQuick.Controls 1.1 import QtQu
这是以下代码的结果: 主.qml import QtQuick 2.8 Item { Reusable { index: 1234 // reusable with
属性变体 a:{}似乎不起作用。 a 最终未定义,而不是一个空字典。 我对 Javascript 不是很有经验...初始化属性以保存空字典的正确方法是什么? 以下 qml 在控制台上打印“qrc:/m
我是一名优秀的程序员,十分优秀!