如何处理不同线程中的视频帧 [英] How to process video frames in different thread
问题描述
大家好,
背景
我正在努力应用程序需要对视频流进行一些图像处理并并排显示原始视频和处理过的视频。
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.
pictureBox1
is 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 useControl.Invoke
.
You cannot call anything related to UI from non-UI thread. Instead, you need to use the methodInvoke
orBeginInvoke
ofSystem.Windows.Threading.Dispatcher
(for both Forms or WPF) orSystem.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屋!