如何处理不同线程中的视频帧 [英] How to process video frames in different thread

查看:99
本文介绍了如何处理不同线程中的视频帧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,



背景

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



Situtation

以下是从相机收到新帧时的事件处理程序。

pictureBox1 是显示原始视频的位置。

GetInputImage()函数将从图片盒1 中窃取,以便可以在该帧上执行一些图像处理。

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

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

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



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



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

  private   void  ProcessThread(some args)
{
GetInputImage();
if (inputImage!= null ){
// 对inputImage执行图像处理
// 在pictureBox2中显示结果
}
}





问题



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

  private   void  camera_NewFrame( object  sender, ref 位图图片)
{
pictureBox1 .Image = image; // 不会读取picturBox1的图像进行处理

if (!isReadingInputImage){
if (inputImage!= null
inputImage.Dispose();
inputImage =(Bitmap)image.Clone(); // 现在不需要GetInputImage()。
}
}



[2] 如何制作 ProcessThread(),无限期运行?此(下方)方法是否正常?

  private   void  ProcessThread(some args)
{
do {
GetInputImage();
if (inputImage!= null ){
// 在inputImage上执行图像处理;
// 在pictureBox2中显示结果
}
} while (someCondition);
}



或者我应该在 camera_NewFrame() func中触发每个帧的处理事件?

解决方案

请参阅我对该问题的评论。原则上,你所做的是可能的,但在性能和时间方面却相当可疑。我只想解决主要障碍:它不能像那样工作。在非UI线程中,您需要使用 Control.Invoke



您无法调用与之相关的任何内容来自非UI线程的UI。相反,您需要使用 Invoke System.Windows.Threading的方法。 Dispatcher (对于Forms或WPF)或 System.Windows.Forms.Control (仅限表单)。



您将在我过去的答案中找到有关其工作原理和代码示例的详细说明:

Control.Invoke()与Control.BeginInvoke() [ ^ ],

使用Treeview扫描仪和MD5的问题 [ ^ ]。



另请参阅有关线程的更多参考资料:

如何让keydown事件在不同的操作上运行vb.net中的线程 [ ^ ],

在启用禁用+多线程后控制事件未触发 [ ^ ]。



-SA


我自己使用后台工作者解决了这个问题。在此发布以供参考。

 私人  void  camera_NewFrame( object  sender, ref 位图图片)
{
pictureBox1.Image =图像;
if (backgroundWorker1.IsBusy!= true
{
lock (储物柜)
{
if (inputImage!= null
inputImage.Dispose();
inputImage =(Bitmap)image.Clone();
}
backgroundWorker1.RunWorkerAsync();
}
}

私有 void backgroundWorker1_DoWork( object sender,DoWorkEventArgs e)
{
lock (locker)
{
baseImage =(Bitmap)inputImage.Clone();
}
// 在此处baseImage处理图像
// 在pictureBox2中显示结果
}


Hello Everyone,

Background
I am working on an application that requires some image-processing on video stream and display the original video and processed video side-by-side.

Situtation
Below is the event handler when a new frame is received from camera.
pictureBox1is where the original video is shown.
GetInputImage() function will steal a from pictureBox1,so that some image processing can be performed on that frame.

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


The image processing is heavy and takes time to process a single image. Thus the frame rate of output video is expected to be very less that the original.

Application must show the original video without getting affected by the image processing. So I want to perform the image processing in a different thread.

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



Questions

[1] Is the method of grabbing a frame (above), OK ? Or the one below is better ?

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] How to make the ProcessThread(), run indefinitely ? Is this(below) approach OK ?

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


Or should I trigger a processing event for each frame within camera_NewFrame() func ?

解决方案

Please see my comment to the question. In principle, what you do is possible, but quite questionable in terms of performance and timing. I want just address the main obstacle: it cannot work like that. In a non-UI thread, you need to use Control.Invoke.

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

—SA


I solved the problem myself using background worker. Posting here for reference.

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
}


这篇关于如何处理不同线程中的视频帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆