我目前正在与AForge合作,并有一个新的帧事件,将帧作为位图发布到图片框中。它有90%的时间很棒......除非我在winform上捣乱。更改组合框,移动窗口或任何类似的风险会导致Picturebox从视频切换到大红色X.下面的代码示例:
private void connectButton_Click(object sender, EventArgs e)
{
try
{
cam = new VideoCaptureDevice(captureDevices[CameraSelectComboBox.SelectedIndex].MonikerString);
cam.NewFrame -= Handle_New_Frame; //Just to avoid the possibility of a second event handler being put on
cam.NewFrame += new AForge.Video.NewFrameEventHandler(Handle_New_Frame);
cam.Start();
}
catch
{
MessageBox.Show("An error has occured with connecting to the specified webcam. The application will now close!");
Application.Exit();
}
}
private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
try
{
if (bitmap != null)
bitmap.Dispose(); //Without this, memory goes nuts
bitmap = new Bitmap(eventArgs.Frame);
}
catch { }
//Draw some stuff on the images
bitmap = AdjustBrightness(bitmap, brightnessMeter);
bitmap = ApplyContrast(contrastMeter, bitmap);
bitmap = Draw_Top_Line(bitmap);
bitmap = Draw_Bottom_Line(bitmap);
//Set the image into the picturebox
this.Invoke((MethodInvoker)delegate
{
videoPictureBox1.Image = bitmap;
frameRate++; //Keep track of the frame rate
});
GC.Collect(); //Without this, memory goes nuts
this.Invoke((MethodInvoker)delegate {
videoPictureBox1.Refresh(); //NOT NECESSARY. JUST TRYING TO FIX THE BIG RED X!
});
if (videoPictureBox1.Image == videoPictureBox1.ErrorImage)
{
cam.Stop(); //ALSO NOT NECESSARY> AGAIN, JUST TRYING TO FIX THE BIG RED X!
cam.Start();
}
}
我在if(videoPictureBox1.Image == videoPictureBox1.ErrorImage)上休息,即使大红色X上升,它也会评估为false,因为图像实际上是设置为位图。所以cam.Stop()和cam.Start()永远不会运行(不确定这是否会有所帮助,但我想我会尝试一下)。
videoPictureBox1.Refresh()每次都在运行,但同样 - 它没有任何区别。仍有大红色X.
正如我之前所说:如果我开始播放视频并且什么都不触摸,那么大红色X将永远不会发生。但是当我开始更改组合框或者拖动表单本身时,大红色X的几率呈指数上升。有时我可以在它发生之前翻阅组合框10-12次,有时它会在第二次点击组合框时发生。 : - \
任何人都可以解释这里发生的事情,也许可以提出一个关于修复它的最佳方法的建议吗?我还是很新的线程,所以我一直在努力解决这里发生的事情以及解决问题的最佳方法!任何朝着正确方向的推动都将是一个巨大的帮助!
答案 0 :(得分:6)
最后,我在调用Handle_New_Frame中包装了一切。它永久地完全消除了大红色X问题。 > _>
private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
this.Invoke((MethodInvoker)delegate
{
try
{
if (bitmap != null)
{
bitmap.Dispose(); //Without this, memory goes nuts
}
bitmap = new Bitmap(eventArgs.Frame);
}
catch { }
//Draw some stuff on the images
bitmap = AdjustBrightness(bitmap, brightnessMeter);
bitmap = ApplyContrast(contrastMeter, bitmap);
bitmap = Draw_Top_Line(bitmap);
bitmap = Draw_Bottom_Line(bitmap);
//Set the image into the picturebox
this.Invoke((MethodInvoker)delegate
{
videoPictureBox1.Image = bitmap;
frameRate++; //Keep track of the frame rate
});
GC.Collect(); //Without this, memory goes nuts
});
}
答案 1 :(得分:3)
肖恩·哈格里夫斯(Shawn Hargreaves)有一个非常简洁的writeup“大红色的厄运X”。我发现在处理WinForm组件突然显示红色“X”的一般情况下,它非常有用。
总结:
OnPaint
事件中抛出异常引起的。OnPaint.
答案 2 :(得分:1)
尝试在使用位图的地方使用克隆。 的实施例强>:
videoPictureBox1.Image = (Bitmap)bitmap.Clone();
答案 3 :(得分:0)
总而言之,这是一个经过测试的最低限度,即使在调整大小,启动,停止或改变分辨率时也不会显示红叉。
public partial class PictureBoxVideo : Form
{
public PictureBoxVideo()
{
InitializeComponent();
var videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
var videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString);
videoSource.NewFrame += Handle_Very_New_Frame;
videoSource.Start();
}
private void Handle_Very_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
this.Invoke((MethodInvoker)delegate {
pictureBox.Image = new Bitmap(eventArgs.Frame);
});
}
}
请注意,我们称之为videoSource.Start();从GUI-(创建)-thread,但从视频(工作者)线程调用回调处理程序(Handle_Very_New_Frame)。
我认为这就是为什么我们需要Invoke和新的Bitmap,所以新的bmp也将从gui-thread生成。但我只是在这里猜测,因为我无法提出证据。