如何处理不同线程中的视频帧(C#)

时间:2015-04-06 03:51:08

标签: c# .net multithreading image-processing video-processing

背景

我正在处理一个需要对视频流进行图像处理并同时显示原始视频和处理过的视频的应用程序。

Situtation

以下是从相机收到新帧时的事件处理程序。 pictureBox1是原始视频的显示位置。 GetInputImage()函数将从pictureBox1中窃取一个,以便可以在该帧上执行某些图像处理。

private void camera_NewFrame(object sender, ref Bitmap image)
{
    if (!isReadingPictureBox)
    {
       if (pictureBox1.Image != null)
           pictureBox1.Image.Dispose();
       pictureBox1.Image = (Bitmap)image.Clone();
    }
}

private void GetInputImage()
{
    if (inputImage != null)
        inputImage.Dispose();

    isReadingPictureBox = true;
    if (pictureBox1.Image != null)
        inputImage = new Bitmap(pictureBox1.Image);
    isReadingPictureBox = false;
}

图像处理很重,需要时间来处理单个图像。因此,预计输出视频的帧速率将远低于原始帧速率。

应用程序必须显示原始视频而不受图像处理的影响。所以我想在不同的线程中执行图像处理。

private void ProcessThread(some args)
{
    GetInputImage();
    if (inputImage != null) {
        // Do Image Processing on "inputImage"
        // Show result in pictureBox2
    }
}

问题

[1] 是抓取框架的方法(上图),好吗?或者下面的那个更好?

private void camera_NewFrame(object sender, ref Bitmap image)
{
    pictureBox1.Image = image; // picturBox1's image will not be read for processing

    if(!isReadingInputImage) {
        if (inputImage != null)
            inputImage.Dispose();
        inputImage = (Bitmap)image.Clone(); // GetInputImage() is not required now.
    }
}

[2] 如何制作ProcessMyThread(),为每一个运行 前一帧完成处理时可用的帧?这(下面)方法好吗?

private void ProcessMyThread(some args)
{
    do {
        GetInputImage();
        if (inputImage != null) {
            // Do Image Processing on inputImage;
            // Show result in pictureBox2
        }
    }while(someCondition);
}

或者我应该在camera_NewFrame() func?

中触发每个帧的处理事件

1 个答案:

答案 0 :(得分:1)

我自己使用后台工作者解决了这个问题。

private void camera_NewFrame(object sender, ref Bitmap image)
{
    pictureBox1.Image = image;

    if (backgroundWorker1.IsBusy != true)
    {
        lock (locker)
        {
            if (inputImage != null)
                inputImage.Dispose();
            inputImage = (Bitmap)image.Clone();
        }
        backgroundWorker1.RunWorkerAsync();
    }
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    lock (locker)
    {
         baseImage = (Bitmap)inputImage.Clone();
    }
    // Do Image processing here on "baseImage"
    // show result in pictureBox2
}