以高帧速率显示图像

时间:2010-10-28 11:58:21

标签: c# wpf multithreading camera frame-rate

问题在于:我有一个自定义硬件设备,我必须在C#/ WPF中从中抓取图像并在一个窗口中显示它们,所有这些都是120+ FPS。

问题在于没有事件表明图像准备就绪,但我必须不断轮询设备并检查是否有新图像然后下载它们。

显然有一些方法可以做到,但我还没有找到合适的方法。

这是我试过的:

  • 一个简单的计时器(或DispatcherTimer) - 适用于较慢的帧速率,但我不能说它超过60 FPS。

  • 单线程无限循环 - 非常快,但我必须在循环中放置DoEvents /它的WPF等效项,以便重新绘制窗口;这有一些其他不必要的(奇怪的)后果,例如来自某些控件的按键事件没有被触发等。

  • 在另一个线程中进行轮询/下载并在UI线程中显示,如下所示:

     new Thread(() =>
            {
                while (StillCapturing)
                {
                    if (Camera.CheckForAndDownloadImage(CameraInstance))
                    {
                        this.Dispatcher.Invoke((Action)this.DisplayImage);
                    }
                }
            }).Start();
    

    嗯,这种方法效果相当好,但是对CPU施加了相当大的负担,当然如果它没有多个CPU /核心就完全杀死了机器,这是不可接受的。另外,我通过这种方式存在大量的线程争用。

问题很明显 - 有没有更好的选择,或者在这种情况下是其中一种方法?

更新
我在某种程度上忘记提及(好吧,在编写这个问题时忘了考虑它),但当然我不需要显示所有帧,但是我仍然需要捕获所有这些帧所以他们可以保存到硬盘上。

UPDATE2: 我发现DispatcherTimer方法并不是因为它不能足够快地处理所有内容,而是因为DispatcherTimer在触发tick事件之前等待下一个垂直同步;这在我的情况下实际上是好的,因为在tick事件中我可以将所有待处理的图像保存到内存缓冲区(用于将图像保存到磁盘)并显示最后一个。

对于通过捕获完全“杀死”的旧计算机,似乎WPF回退到非常慢的软件渲染。我可能无能为力。

感谢所有答案。

2 个答案:

答案 0 :(得分:1)

我认为你正在尝试过于简单化的方法。这就是我要做的。

a)在轮询循环中放置一个Thread.Sleep(5),这样可以让你接近120fps,同时仍然保持CPU时间低。

b)仅每隔5帧左右更新一次显示。这将减少处理量,因为我不确定WPF的处理速度是否超过60fps。

c)使用ThreadPool为每个帧生成一个子任务,然后将其保存到磁盘(每帧单独一个文件中),这样您就不会受到磁盘性能的限制。额外的帧只会堆积在内存中。

我个人会按顺序执行它们。机会是a或b将解决你的问题。

答案 1 :(得分:-1)

您可以执行以下操作(所有伪造的代码): 1.让一个工作线程运行处理捕获过程:

List<Image> _captures = new List<Image>();
 new Thread(() =>
    {
        while (StillCapturing)
        {
            if (Camera.CheckForAndDownloadImage(CameraInstance))
            {
                lock(_locker){_captures.Add(DisplayImage);


            }
        }
    }).Start();
  1. 让调度程序计时器线程获取最新捕获的图像(显然它会丢失自上次打勾后的一些捕获)并显示。因此,UI线程被限制并且尽可能少地执行,它没有完成所有“捕获”,这是由工作线程完成的。抱歉,我无法理解这一点(但你明白了):

    void OnTimerTick(can't remember params)
    

    { 图像imageToDisplay; lock(_locker){imageToDisplay = _captures [k.Count - 1]; DisplayFunction(imageToDisplay); }

  2. 可能是列表是一个队列而另一个线程用于流出队列并写入磁盘或其他任何内容。

相关问题