【发布时间】:2025-12-04 14:45:02
【问题描述】:
我从网络摄像头捕捉图像,对它们进行一些繁重的处理,然后显示结果。为了保持高帧率,我想让不同帧的处理并行运行。
所以,我有一个“生产者”,它捕获图像并将它们添加到“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();
}
并行化实际上工作得很好,每个添加的线程都会增加线性速度(当然,直到某个点)。问题是我在输出中得到了工件,即使只运行一个线程。工件看起来像是图片的一部分不在正确的位置。
任何想法是什么原因造成的? 谢谢
【问题讨论】:
-
老游戏就是这么制作的。基本上,您正在尝试将旧的技术概念与新的概念混合。这就是它不起作用的原因。你需要使用多个线程(你已经做了什么)。我不是真正的游戏开发者,但我认为你不应该使用 EventQue 或任何 Monitor 锁。您可以简单地过度绘制图像而不会出现死锁。但我不确定。所以,我没有发布任何东西,因为我不完全知道解决方案。但我认为你应该考虑一下我的解决方案建议。
标签: c# image parallel-processing emgucv