Артефакты параллельной обработки изображений

Я захватываю изображения с веб-камеры, выполняю их тяжелую обработку, а затем показываю результат. Чтобы поддерживать высокую частоту кадров, я хочу, чтобы обработка разных кадров выполнялась параллельно.

Итак, у меня есть «Продюсер», который захватывает изображения и добавляет их в «inQueue»; также он берет изображение из 'outQueue' и отображает его:

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

    public Producer(Emgu.CV.UI.ImageBox screen, Capture capture, Queue> inQueue, Queue> 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> inQueue;
    Queue> outQueue;
    Object lockObject;
    string name;

    Image image;

    public Consumer(Queue> inQueue, Queue> 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> inQueue = new Queue>();
        Queue> outQueue = new Queue>();

        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();
    }

Распараллеливание на самом деле работает нормально, я получаю линейное увеличение скорости с каждым добавленным потоком (до определенного момента, конечно ). Проблема в том, что я получаю артефакты на выходе, даже если работает только один поток. Артефакты выглядят так, будто часть изображения находится не в том месте.

Пример артефакта (без какой-либо обработки для ясности, но эффект тот же)

Любые идеи, что вызывает это? Спасибо

16
задан m00se 23 July 2012 в 11:56
поделиться