使用 Qt 显示图像流

2024-03-07

当前的解决方案如下所示:

//paintlabel.h
class PaintLabel : public QWidget
{
    Q_OBJECT

public:
    explicit PaintLabel(QWidget *parent = 0);

public slots:
    void setImage(char *img_ptr, QSize img_size, int pitch);

protected:
    void paintEvent(QPaintEvent *event) override;

private:
    QImage image;

}

//paintlabel.cpp

PaintLabel::PaintLabel(QWidget *parent) : QWidget(parent)
{
    setAttribute(Qt::WA_NoSystemBackground, true);
}

void PaintLabel::setImageLive(char *img_ptr, QSize img_size, int pitch)
{
    image = QImage((uchar *)img_ptr, img_size.width(), img_size.height(), pitch, QImage::Format_RGB32).scaled(this->size());
    update();  
}

void PaintLabel::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter;
    painter.begin(this);
    if (!image.isNull()) {
        const QPoint p = QPoint(0,0);
        painter.drawImage(p, image);
    }
    painter.end();
}

我预计每秒 20-40 帧。问题是,性能随大小的变化非常糟糕。当尺寸约为全高清时,绘制需要 1-2 毫秒。但如果我将其大小调整为 4k,它会变得非常滞后(绘制 16 毫秒)。有没有什么方法可以实现相同的功能但消耗更少的资源?

理论上,如果我将父类更改为 QOpenGLWidget,QPainter 将使用硬件加速运行。但这样做,它运行得更慢。


首先,代码中的限制因素之一似乎是scaled()功能。尝试将其取出,您应该会看到一些加速。

另一个问题就是 QImage 的性能限制。请参阅此问题以获取更多信息。如何提高 QPainter 的性能? https://stackoverflow.com/questions/6512155

QPainter 将使用软件光栅器来绘制 QImage 实例。

refer http://doc.qt.io/qt-5/topics-graphics.html http://doc.qt.io/qt-5/topics-graphics.html了解更多信息。

你不能去QPixmap因为你的整个缓冲区也会改变每一帧。

您可以尝试使用QOpenGLPaintDevice使QPainter使用硬件加速。您尝试过的另一种方法是QOpenGLWidget.

QOpenGLWidget - 画家也可以在 QOpenGLWidget 上打开。这样做是为了方便,因为从技术上讲,这与使用 QOpenGLPaintDevice 没有什么不同。

请参阅上面相同的 qt 链接。

所以是的,这在技术上应该更快,但是因为您正在调整大小Widget从而调整大小OpenGL Viewport,每次都会重新制作下面的缓冲区。因此,放缓幅度更大。请注意,QOpenGLWidget 处理一些功能,例如glViewport()通过它自己。当您尝试优化性能时,这没有用。

这里有一些建议

  1. 我认为主要问题是 QImage 的处理。我建议您设置自己的 OpenGL 场景,只需使用一个四边形来渲染纹理,并尝试每一帧写入纹理。缩放将在 GPU 上处理,因此肯定会更快。

  2. 或者你可以使用glDrawPixels()将图像从主机内存 (RAM) 渲染到帧缓冲区。尽管这不会为您处理缩放问题。参考https://www.opengl.org/sdk/docs/man2/xhtml/glDrawPixels.xml https://www.opengl.org/sdk/docs/man2/xhtml/glDrawPixels.xml了解更多信息。

我目前正在使用 QGLWidget 和自定义 OpenGL 纹理和绘制调用来实现快速更新(> 60 FPS)。我观察到这比 QImage / Qpixmap 方法快大约 8 到 10 倍。请注意,我的纹理尺寸从未超过 700x700。此外,我的图像始终存储在 GPU 内存中,并由映射的 CUDA 内核更新。

您肯定会看到加速,但我不能保证它能满足您的 FPS 要求。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Qt 显示图像流 的相关文章

  • C# AES Rijndael - 检测无效密码

    我正在使用 Rijndael 加密程序中的一些敏感数据 当用户输入错误的密码时 大多数情况下CryptographicException抛出消息 填充无效且无法删除 然而 CryptStream 不会抛出密码错误的异常 而是返回错误解密的流
  • 使用来自本地对象的消息的 std::Exception

    以下代码是否可以安全地抛出带有自定义消息的异常 include
  • C# 中的 Culture 相当于 Java 中的 Locale 吗?

    C 使用文化的概念 这在操作上与 Java 中的 Locale 类似吗 或者底层概念是否存在显着差异 从文化而不是语言环境的角度进行工作是一种寻找正确抽象层次的尝试 从以类似方式做事的人群的角度来考虑事物 而不是谈论地理区域和语言 并有点疯
  • 无法对 ContainsGenericParameters 为 true 的类型或方法执行后期绑定操作

    我有一个适用于所有实体的扩展 public static class EntityBaseExtensions public static T Clone
  • 使用 QTextCursor 选择一段文本

    使用 Qt 框架选择文本片段时遇到问题 例如 如果我有这个文件 没有时间休息 我想选择 ime for r 并从文档中删除这段文本 我应该如何使用 QTextCursor 来做到这一点 这是我的代码 QTextCursor cursor n
  • 当“”可以分配给std::string时,为什么有“clear”方法?

    一个可以用string clear函数清空字符串 也可以使用空双引号 来执行此操作 有什么不同 当您分配一个空字符串时 编译器必须在数据部分存储一个空的 C 字符串 并创建代码以将指向它的指针传递给赋值运算符 然后 赋值运算符必须从数据部分
  • 对相当大的整数的大集合的操作的快速实现

    描述 我实现了以下类 LabSetInt64 参见下面的代码 这里的目标是尽可能快地操作大量大整数 最多 10M 的值 我的主要要求集中在 至关重要 尽快获取集合的大小 基数 重要 能够非常快速地迭代一组集合 所以 从下面的实现开始 我还有
  • 将 LINQ to Entities 查询中的每个项目转换为接口的最佳方法是什么?

    我有一个实现 IUser 的实体对象 User IQueryable
  • 将内核链接到 PTX 函数

    我可以使用 PTX 文件中包含的 PTX 函数作为外部设备函数 将其链接到另一个应调用该函数的 cu 文件吗 这是另一个问题CUDA 将内核链接在一起 https stackoverflow com questions 20636800 c
  • ObservableCollection 上的“Cascade”绑定,包含其他 ObservableCollection

    我有一个项目需要显示合同列表 Class Affaire 每个合约都有一个阶段列表 类别阶段 我使用绑定在 2 个不同的 ListView 中显示它们中的每一个 问题是当我从 ListView 中删除一个 Phase 时 显示 Phases
  • 使用 boost::iterator_facade<>

    我有一个链表结构 struct SomeLinkedList const char bar int lots of interesting stuff in here DWORD foo SomeLinkedList pNext 它是现有
  • CMake - 未定义参考

    我正在尝试将 gtest 包含到我的项目中 问题是我在 GTest 中收到未定义的引用错误 我正在尝试在 Gtest 中测试 Node 类 在节点的构造函数中 我使用类记录器 尽管我已将库记录器添加到 gtest target 中 但我仍然
  • 设置外部应用程序焦点

    在 VB NET 中 您可以使用以下命令将焦点设置到外部应用程序 AppActivate Windows Name or AppActivate processID As Integer 现在 如果您这样做 则效果很好 Dim intNot
  • .NET 中 IEqualityComparer 中 GetHashCode 的作用是什么?

    我试图了解 IEqualityComparer 接口的 GetHashCode 方法的作用 下面的例子取自MSDN using System using System Collections Generic class Example st
  • 整数与双精度算术性能?

    我正在编写一个 C 类来使用整数执行 2D 可分离卷积 以获得比双对应更好的性能 问题是我没有获得真正的性能提升 这是 X 过滤器代码 对于 int 和 double 情况都有效 foreach pixel int value 0 for
  • 让 GCC/Clang 使用 CMOV

    我有一个简单的标记值联合 这些值可以是int64 ts or doubles 我正在对这些联合进行加法 但需要注意的是 如果两个参数都代表int64 t值 那么结果也应该有一个int64 t value 这是代码 include
  • 在标准库中静态链接时如何支持动态插件?

    假设一个应用程序myapp exe是使用构建的g 它使用标志 static libstdc 这样就可以安装在没有环境的情况下libstdc so myapp exe还添加了对某些功能的插件支持plugf可以通过动态加载dlopen来自共享库
  • 如何忽略搜索条件中的空属性

    我有一个不好的要求要做 无论如何 我必须在我的应用程序中实现它 我有一个Track class public class Track public string Name get set public string City get set
  • 带有 Unicode 字符的主机名在 Windows 8 中有效

    Uri CheckHostName 回报UriHostNameType Unknown到处都是 但在 Windows 8 上 它又回来了UriHostNameType Dns 为什么突然间带有 Unicode 西里尔字符的主机名在 Wind
  • C语言中如何将整数转换为字符? [复制]

    这个问题在这里已经有答案了 C语言中如何将整数转换为字符 C 中的字符已经是数字 字符的 ASCII 代码 无需转换 如果要将数字转换为相应的字符 只需添加 0 即可 c i 0 0 是 ASCii 表中的一个字符

随机推荐