我正在使用BackgroundWorker从相机中提取视频并将其写入WinForms表单上的PictureBox。在BW线程中,我只需从相机中拉出一帧,将其放入PictureBox,休眠,然后继续:
Total runtime: 1564.444 ms
问题是,最终在我的屏幕上调整或移动表单会抛出异常while (CaptureThreadRunning)
{
Thread.Sleep(5);
Image tmp = Camera.GetFrame(500);
pbCameraFeed.Image = tmp;
//this.BeginInvoke(new MethodInvoker(delegate { pbCameraFeed.Image = Camera.GetFrame(500); }));
}
,并在System.InvalidOperationException
Additional information: Object is currently in use elsewhere.
我假设该库试图在我的while循环的同时绘制与PictureBox有关的东西,所以我切换到上面注释掉的pbCameraFeed.Image = tmp;
实现。不幸的是,这显着降低了我的帧率。我在非常慢的Mini PC上运行此代码,这可能导致了这个问题。
我真正想要的是一种用可靠的图像更新我的GUI的方法,这种方法不会使我的帧率降低近一半。还有其他标准方法吗? BW线程似乎非常适合这个应用程序,但我错过了什么?
由于
答案 0 :(得分:3)
If I were you I would definitely check out the AForge.NET Framework. No need to reinvent the wheel ;)
http://www.aforgenet.com/framework/samples/video.html
AForge.NET is an open source C# framework designed for developers and researchers in the fields of Computer Vision and Artificial Intelligence - image processing, neural networks, genetic algorithms, fuzzy logic, machine learning, robotics, etc.
The framework is comprised by the set of libraries and sample applications, which demonstrate their features:
AForge.Imaging - library with image processing routines and filters;
AForge.Vision - computer vision library;
AForge.Video - set of libraries for video processing;
...
答案 1 :(得分:0)
我建议不要使用PictureBox,而是直接绘制到UserControl表面。这可以通过addig代码轻松完成UserControl的Paint和Invalidate事件。
下面的示例创建了一个用户控件,该控件具有BitMap属性,每次控件失效时,它都会绘制到其表面。 因此,例如,要从文件夹D:\ MyPictures中随机渲染JPG图像,您可以执行以下操作:
using System.Windows.Forms;
using System.Drawing;
void Main()
{
var pictures = Directory.GetFiles(@"D:\MyPictures", "*.jpg");
var rnd = new Random();
var form = new Form();
var control = new MyImageControl() { Dock = DockStyle.Fill };
form.Controls.Add(control);
var timer = new System.Windows.Forms.Timer();
timer.Interval = 50;
timer.Tick += (sender, args) =>
{
if (control.BitMap != null)
control.BitMap.Dispose();
control.BitMap = new Bitmap(pictures[rnd.Next(0, pictures.Length)]);
control.Invalidate();
};
timer.Enabled = true;
form.ShowDialog();
}
public class MyImageControl : UserControl // or PictureBox
{
public Bitmap BitMap { get; set; }
public MyImageControl()
{
this.Paint += Graph_Paint;
this.Resize += Graph_Resize;
}
private void Graph_Paint(object sender, PaintEventArgs e)
{
if (this.BitMap != null)
{
lock (this.BitMap)
{
Graphics g = e.Graphics;
g.DrawImage(this.BitMap, this.ClientRectangle);
}
}
}
private void Graph_Resize(object sender, System.EventArgs e)
{
this.Invalidate();
}
}
我认为可以轻松更改以渲染相机图像而不是图片文件。
代码在LinqPad
上进行了测试