如何高效地从后台线程向Delphi 6帧或窗体执行图像流预览?

4
我有一个Delphi 6应用程序,从外部相机接收和处理图像流。由于它是CPU密集型的,我将代码放在后台线程中,以免干扰运行在主线程上的用户界面代码。我想使用从相机接收的JPEG帧创建的TBitmap更新表单或框架上的矩形区域。这些帧的接收速率为每秒25帧。
我想知道哪种方法可以给我最佳性能,以及要使用哪些Windows API调用或Delphi调用来实现它。我猜我不应该使用TImage或TPicture等VCL组件,因为它们运行在主线程上,我非常确定通过Synchronize()调用获取任何结果都会很低效,并且有减慢涉及线程的速度的潜力。我还想要一种提供平滑视频显示的技术,就像双缓冲控件一样,没有任何"条纹"效果。此外,任何有关正确Canvas锁定或设备上下文管理等方面的提示,尤其是有关避免释放资源中常见错误的提示,都将不胜感激。
当然,一个做我需要的事情的好的代码示例链接也是非常棒的。

我无法提供任何好的代码示例,但我强烈建议您查看 Graphics32 来实现您想要做的事情。 - iamjoosy
1
你是通过什么方式从外部相机接收图像流的?DirectShow 还是 VFW?除非你有使用 TBitmpas 的特定原因,否则我建议尝试使用其中一个 DirectShow 渲染器,因为这很可能是呈现相机图像流最高效的 CPU 方式。 - iamjoosy
1个回答

3
据我所知,如果您只在其画布上工作,TBitmap是线程安全的。如果您发送GDI消息并需要刷新屏幕,则需要使用Synchronize,但根据我的实验,使用TBitmap.Canvas只是对线程安全的Windows API进行了包装。如果您使用像Scanline这样的像素算法处理位图,并且每个线程只处理唯一的位图,则可以在后台完成操作。
但我怀疑使用TBitmap不是最有效的方法。尝试使用http://graphics32.orghttp://aggpas.org,它们都是非常快速的位图处理方式。
如果可能,正如imajoosy提出的那样,处理输入流的最佳方法是使用直接的X流处理能力。
对于线程安全的处理,如果每个线程将消耗其核心的100%(这对于图像处理非常可能),则通常认为您最好为处理创建NumberOfCPU-1个线程。例如,您可以创建一个线程池,然后让它们从输入流中获取位图进行处理。

为什么是N-1?为什么不是N?将其推向极端,考虑单核机器。那永远无法完成任何任务。协调线程可能会占用-1,但很可能大部分时间都处于空闲状态,为其保留整个核心是浪费的。 - David Heffernan
@DavidHeffernan N-1 在单核 CPU 中意味着 1。这是一个通用规则,引用我见过的一些常见实现模式。留出一个核心未使用是个好主意,让后台系统任务(包括杀毒软件和主 Windows/桌面)无任何问题地工作。你还可以根据每个任务的渲染速度添加一个上限(例如,如果你有一个 8 核 CPU,则最多可达到 4 个线程),因为众所周知,超线程核心不如“本地”核心高效。使用 N 或 >N 个线程,整体处理速度将会降低。 - Arnaud Bouchez
我的经验是,在这种任务中饱和所有N个核心可以最快地完成工作。而且现代的超线程核心也非常好。最新的英特尔版本值得使用。我猜他们上一次受到如此糟糕的评价(实至名归),以至于英特尔甚至不再推广该名称! - David Heffernan
@DavidHeffernan 我认为N或N-1并没有太大的区别,如果它<=N。这将取决于线程的实际处理过程。根据在几个硬件系统上进行基准测试后的实际挂钟时间,由OP猜测什么是最佳参数。 - Arnaud Bouchez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接