如何实时可视化来自不同线程的图像?

Posted

技术标签:

【中文标题】如何实时可视化来自不同线程的图像?【英文标题】:How to vizualize Images from different threads in real time? 【发布时间】:2018-09-21 10:20:35 【问题描述】:

我有 4 个相机对象。每个相机对象独立刷新帧。我想在我的视频墙类上可视化这些帧。基本上,我的拼接墙只是一个带有 draw Widget 方法的 gridlayout 子项。

每个相机对象都有 imageHolder 小部件。 ImageHolder 小部件是 qOpenglWidget 的子部件,带有

void OpenGLImageHolder::display(const QImage* img)

    m_image = img;
    this->update();


void OpenGLImageHolder::paintEvent(QPaintEvent*)


    QPainter painter(this);
    painter.drawImage(this->rect(), *m_image);

每个 Image Holder 都有一个 QTimer,并且 QTimer::timeOut() 连接到 OpenGLImageHolder::display()。

不幸的是,通过这种设置,我只能同时可视化 3 个摄像头。如果我添加第四台摄像机,三个(或两个)之一会冻结。我知道调用了显示,因为当我调整大小小部件时,我得到了正确的图像更新。

制作拼接墙的正确方法是什么?要不要自己做一个openglWidget,自己的窗口,然后直接在这个openglWidget上画图? 我可以使用哪些工具来分析行为(似乎标准的 msvs 分析器还不够)。

【问题讨论】:

我曾经给SO: Qt C++ Displaying images outside the GUI thread (Boost thread) 写过一个答案,有点相似,但我不确定它是否适用于您的问题。你可以看看它(例如,如果你没有想法)。 ;-) 通过指向OpenGLImageHolder::display 的指针传递的QImage 的所有权是什么?每当我看到这样的代码没有任何伴随的 new/delete 时,它就会引发各种警钟。另外,您是否在代码的其他地方使用OpenGL?如果不是,那么从QOpenGLWidget 继承似乎有点过分——同样的工作可以用QWidget 轻松完成。 【参考方案1】:

我的设计:

每个相机都使用一个准备图像的线程。图像在需要时或由计时器创建。当它准备好时,线程向主线程发出信号。

主线程处理信号。将图像作为纹理加载到 GPU 并通过简单的四边形进行绘制。

诀窍是使用一个独特的窗口,但为每个摄像头使用不同的glViewport


其他解决方案是为整个窗口使用纹理并更新每个相机使用的矩形。

【讨论】:

所以调用 gpu 进行渲染需要时间,是吗?为什么标准方法(更新其线程中的每个小部件)不起作用? 我回答了如何使用 OpenGL。使用 OS/Qt API 绘图也是有效的。两种方法的渲染图像速度相似。更新窗口最好在主线程中完成,在每个线程更新其屏幕部分时可能会出现一些问题。 @hagor 在多个线程中进行 GUI 更新通常是个坏主意。这对于 Qt 以及其他小部件集都是如此。 (我记得 GTK+/gtkmm V2 也是如此,不相信它在 V3 中发生了变化。)对于 OpenGL 也是如此。关于后者,只有一个(活动的)GL 上下文(AFAIK)。即使通过锁定来保护多个线程对此上下文的访问,多线程也会变得有问题,因为并发访问是不可能的,并且这种锁定将强制进行序列化。

以上是关于如何实时可视化来自不同线程的图像?的主要内容,如果未能解决你的问题,请参考以下文章

PyQt5学习笔记--摄像头实时视频展示多线程处理视频编解码

50 行代码,看 Python + OpenCV 玩转实时图像处理!

iOS:如何阅读播放实时音乐?

opencv&mediapipe 人脸检测+摄像头实时

数据实时可视化——实时交互(websocketSSE)

R语言ggplot2可视化图像设置不同的字体实战