C++ 使用C++;与3000Hz的线扫描摄像机接口,并处理/显示数据

C++ 使用C++;与3000Hz的线扫描摄像机接口,并处理/显示数据,c++,multithreading,qt,camera,C++,Multithreading,Qt,Camera,几个月前,我开始从事一个项目,开发一种算法来处理从linescan相机设备(例如,每300us一行384像素)获取的数据。因为我是工程师而不是程序员,所以我开始使用Python来最小化学习曲线。在SX的帮助下,我成功地构建了一个Python应用程序(最终超过2000行代码),并成功地创建了一个图像处理算法来处理数据。我给客户留下了深刻印象,他们想把它提升到一个新的水平。现在,我需要它是实时的。。。这意味着C++。我得到了凯尼格和Moo的加速C++,开始阅读。所以,请对我宽容点。我喜欢学习编程,但

几个月前,我开始从事一个项目,开发一种算法来处理从linescan相机设备(例如,每300us一行384像素)获取的数据。因为我是工程师而不是程序员,所以我开始使用Python来最小化学习曲线。在SX的帮助下,我成功地构建了一个Python应用程序(最终超过2000行代码),并成功地创建了一个图像处理算法来处理数据。我给客户留下了深刻印象,他们想把它提升到一个新的水平。现在,我需要它是实时的。。。这意味着C++。我得到了凯尼格和Moo的加速C++,开始阅读。所以,请对我宽容点。我喜欢学习编程,但我没有受过正式培训。我已经尽力了

我现在有一个C++原型GUI(使用Qt)环绕在所有需要通过摄像头连接的相机上的库中。采集代码位于自己的线程中,并向GUI发送信号。所以,我有基本的准备。我可以用我当前的代码获取任意多行数据,但我现在正试图弄清楚如何围绕这一点构建应用程序。甚至还编写了一个与Qt(MOCing等)一起工作的定制makefile

无论如何,对于应用程序,我想要两种模式(以下是问题):

(1) “实时”视图。。。其中,GUI实时显示linescan数据。我正在考虑使用一个循环缓冲区(例如Boost::circular_buffer)来实时保存数据,并通过发出的信号将缓冲区的副本(memcpy?)传递给GUI。这是站得住脚的吗?我觉得缓冲区的副本是必要的,因为循环缓冲区大约每300us就会改变一次,我不知道主事件循环能否保持。同样,数据采集在它自己的线程中。它必须比这更复杂吗?我是否必须在读取数据时从缓冲区弹出数据,而不是使用循环缓冲区?我觉得循环缓冲区是最好的选择,因为这正是我想要显示的图像

(2) 数据处理模式。。。其中,线扫描数据以块(即,384 x 384)像素的形式发射。以300us(~3333Hz)的扫描速率,即每100ms左右一个块或帧。在这100毫秒内,我需要对数据进行规范化、对象检测、阈值设置等。我计划在运行实时内核补丁的Linux机器上运行这个程序。我认为应该保持下去。我需要在数据采集和数据处理线程之间进行通信。。。我需要插座吗

我在这里寻找关于如何开始这两件作品的建议。第二个更重要,但第一个将帮助我想象正在发生的事情。最终,我希望两种模式同时运行。我花了一周的大部分时间来做这件事。。。但我需要确保我的计划走上了正确的道路

至(1):

对我来说有道理。从GUI代码和接收器代码访问同一缓冲区时,必须小心同步问题。一种可能的改进是稍微限制GUI更新的数量。屏幕刷新率通常为50或60Hz,大多数GUI库都假设更新不会比这更频繁

您还可以通过复制屏幕上实际显示的内容来减少复制的数据量。因此,我建议将其反转一点:GUI会获得一个更新计时器(对于您的目的来说,任何看起来足够好的东西),根据需要从循环缓冲区中提取新的显示内容。这样可以减少很多不必要的(即不可见的)屏幕更新和缓冲区拷贝

根据您的需要,您也可以使用为问题第2部分创建的块进行屏幕更新

至(2): 首先,在使用多线程时,通常不需要套接字或类似的东西

我建议您使用类似线程池的方法进行处理:当新块可用时,将它们复制到任务对象(您定义的一个类,它具有处理代码并实现线程池可以理解的接口),然后将其提供给线程池

因为您使用的是Qt,所以我将在这一部分中介绍QThreadPool和QRunnable。如果需要按特定顺序完成块的处理,事情会变得更有趣。基本上,您将拥有一个阻塞队列数据结构,您还将为该数据结构提供QRunnable对象,然后另一个线程将它们从那里抓取,并等待每个对象按照启动顺序完成

此处的通信仅限于数据采集线程将输入切割成块并启动任务。如果您还需要从数据处理任务中控制数据采集线程,则可能需要一些不同的设计

您也可能不使用实时内核补丁就可以逃脱。如果您用来访问行扫描相机的库缓冲其输入,那么如果您错过了更新,您只会一行接一行地得到多个行。同样,这取决于您需要反应的速度,但是您正在对多行高的块进行图像处理,所以我希望您已经能够处理一些延迟

预计到达时间: 我只是重读了你的问题。因此,基本上每100ms只有384x384像素的块。我正要建议使用Qt信号,但在这里您可能会遇到问题:当线程之间通信时,Qt信号在内部使用阻塞队列数据结构。不幸的是,它们的实现不允许您设置大小限制,因此,如果您的GUI线程或处理线程处理它们的速度不够快(例如,用户处于GUI的模式对话框中),它们将被缓冲并耗尽内存

相反,您可以使用如下内容:

Acquisition thread ==> (Blocking Queue) ==> Processing thread
基本上,你的获得