c# - 并行图像处理伪影

标签 c# image parallel-processing emgucv

我从网络摄像头捕捉图像,对它们进行大量处理,然后显示结果。为了保持高帧率,我希望并行运行不同帧的处理。

所以,我有一个“Producer”,它捕获图像并将它们添加到“inQueue”;它还从“outQueue”中获取图像并显示它:

public class Producer
{
    Capture capture;
    Queue<Image<Bgr, Byte>> inQueue;
    Queue<Image<Bgr, Byte>> outQueue;
    Object lockObject;
    Emgu.CV.UI.ImageBox screen;
    public int frameCounter = 0;

    public Producer(Emgu.CV.UI.ImageBox screen, Capture capture, Queue<Image<Bgr, Byte>> inQueue, Queue<Image<Bgr, Byte>> outQueue, Object lockObject)
    {
        this.screen = screen;
        this.capture = capture;
        this.inQueue = inQueue;
        this.outQueue = outQueue;
        this.lockObject = lockObject;
    }

    public void produce()
    {
        while (true)
        {
            lock (lockObject)
            {
                inQueue.Enqueue(capture.QueryFrame());

                if (inQueue.Count == 1)
                {
                    Monitor.PulseAll(lockObject);
                }
                if (outQueue.Count > 0)
                {
                    screen.Image = outQueue.Dequeue();                      
                }
            }
            frameCounter++;
        }           
    }
}

有不同的“消费者”从 inQueue 中获取图像,进行一些处理,然后将它们添加到 outQueue:

public class Consumer
{
    Queue<Image<Bgr, Byte>> inQueue;
    Queue<Image<Bgr, Byte>> outQueue;
    Object lockObject;
    string name;

    Image<Bgr, Byte> image;

    public Consumer(Queue<Image<Bgr, Byte>> inQueue, Queue<Image<Bgr, Byte>> outQueue, Object lockObject, string name)
    {
        this.inQueue = inQueue;
        this.outQueue = outQueue;
        this.lockObject = lockObject;
        this.name = name;
    }

    public void consume()
    {
        while (true)
        {
            lock (lockObject)
            {
                if (inQueue.Count == 0)
                {
                    Monitor.Wait(lockObject);
                    continue;
                }                
                image = inQueue.Dequeue();   
            }

            // Do some heavy processing with the image

            lock (lockObject)
            {
                outQueue.Enqueue(image);
            }

        }
    }
}

剩下的重要代码是这部分:

    private void Form1_Load(object sender, EventArgs e)
    {
        Consumer[] c = new Consumer[consumerCount];
        Thread[] t = new Thread[consumerCount];

        Object lockObj = new object();
        Queue<Image<Bgr, Byte>> inQueue = new Queue<Image<Bgr, Byte>>();
        Queue<Image<Bgr, Byte>> outQueue = new Queue<Image<Bgr, Byte>>();

        p = new Producer(screen1, capture, inQueue, outQueue, lockObj);

        for (int i = 0; i < consumerCount; i++)
        {
            c[i] = new Consumer(inQueue, outQueue, lockObj, "c_" + Convert.ToString(i));
        }
        for (int i = 0; i < consumerCount; i++)
        {
            t[i] = new Thread(c[i].consume);
            t[i].Start();
        }

        Thread pt = new Thread(p.produce);
        pt.Start();
    }

并行化实际上工作正常,每个添加的线程(当然达到某个点)我确实获得了线性速度增加。问题是我在输出中得到了伪影,即使只运行一个线程也是如此。这些瑕疵看起来像是图片的一部分不在正确的位置。

Example of the artifact (this is without any processing to keep it clear, but the effect is the same)

知道是什么原因造成的吗? 谢谢

最佳答案

免责声明:这篇文章不应该完整地描述一个答案,而是给出一些关于为什么显示工件的提示。

快速分析表明,actifact 实际上是帧的部分垂直镜像片段。我复制它,镜像,然后将它放回图像上,并添加了一个糟糕的标记来显示它的位置:

enter image description here

有两件事立即引起注意:

  • 工件大致定位在“正确”的位置,只是该位置也是垂直镜像的;
  • 图像略有不同,表明它可能属于不同的框架。

自从我玩原始捕获并遇​​到类似问题以来已经有一段时间了,但我记得这取决于驱动程序的实现方式(或设置 - 在为隔行捕获设置特定成像设备时发生了这个特定问题) 它可能会在“自上而下”和“自下而上”扫描之间交替填充其帧缓冲区 - 一旦帧已满,“光标”就会恢复方向。

在我看来,您遇到了竞争条件/缓冲区欠载情况,在这种情况下,从帧缓冲区到您的应用程序的传输发生在设备传输完整帧之前。

在那种情况下,您会收到部分图像,并且仍未刷新的区域会显示一些先前传输的帧。

如果我不得不打赌,我会说工件可能按顺序出现,不是在同一位置,而是在特定方向(向上或向下)上“波动”,但总是作为镜像位出现。

关于c# - 并行图像处理伪影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11612046/

相关文章:

python - Python中微分方程的并行求解

multithreading - 共享内存计算机上的多线程 FFTW 3.1.2

c# - .Net Core 中的 Oracle Bulk

c# - 负载均衡系统中的 Protobuf-net 动态类型

c# - 公共(public)无效方法不起作用。无法将类型 'void' 隐式转换为 'object'

iphone - 如何从 gif 文件中获取每秒的帧数?

c# - Xamarin Forms 图像未显示在 ListView 中

php - 如何在 PHP/MySQL 中组织和构建用户图像相册

javascript - 从引导模式获取图像 URL 到 javascript

jquery - .each() jquery 中的并行选项