C#,每 5 秒从网络摄像头连续保存帧
C#, Saving frames from webcam continuously every 5s
当 运行 基于 GUI 的代码实际上打开网络摄像头提要并每 5 秒保存一次帧时,在 运行dom 运行 时间(可能是 5 分钟)之后或 20 分钟)发生异常“'Object in use by another process'”,可能与当前帧的保存有关。任何想法导致问题的原因以及应该进行哪些代码修改?
public partial class Form1 : Form
{
private FilterInfoCollection CaptureDevices;
private VideoCaptureDevice videoSource;
bool blncapturing;
public Form1()
{
InitializeComponent();
timer1.Enabled = false;
timer1.Interval = 5000;
blncapturing = false;
}
private void button1_Click(object sender, EventArgs e)
{
videoSource = new VideoCaptureDevice(CaptureDevices[comboBox1.SelectedIndex].MonikerString);
videoSource.NewFrame += new NewFrameEventHandler(VideoSource_NewFrame);
videoSource.Start();
timer1.Enabled = true;
}
private void VideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
if (pictureBox1.Image != null)
((IDisposable)pictureBox1.Image).Dispose();
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
}
private void Form1_Load_1(object sender, EventArgs e)
{
CaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo Device in CaptureDevices)
{
comboBox1.Items.Add(Device.Name);
}
comboBox1.SelectedIndex = 0;
videoSource = new VideoCaptureDevice();
}
private void button2_Click(object sender, EventArgs e)
{
videoSource.Stop();
pictureBox1.Image = null;
pictureBox1.Invalidate();
pictureBox2.Image = null;
pictureBox2.Invalidate();
}
private void button3_Click(object sender, EventArgs e)
{
Capturing();
}
private void button4_Click(object sender, EventArgs e)
{
if (videoSource.IsRunning == true)
{
videoSource.Stop();
}
Application.Exit(null);
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
Capturing();
timer1.Start();
}
private void Capturing()
{
try
{
if (blncapturing == false)
{
blncapturing = true;
pictureBox2.Image = (Bitmap)pictureBox1.Image.Clone();
string strGrabFileName = String.Format("C:\Users\echristo\Desktop\trial\Snapshot_{0:yyyyMMdd_hhmmss.fff}.bmp", DateTime.Now);
pictureBox2.Image.Save(strGrabFileName, System.Drawing.Imaging.ImageFormat.Jpeg) ;
blncapturing = false;
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
如果您从不同的线程访问对象,您需要一个锁。
当您从不同线程访问控件时也使用调用。
private readonly object myLock = new object();
private void VideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
lock (myLock) {
this.Invoke((Action)(() => {
if (pictureBox1.Image != null)
((IDisposable)pictureBox1.Image).Dispose();
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
}));
}
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
// you can try with timer1 inside the lock
lock (myLock) {
// you don't need invoke here, because the winforms timer runs on the main thread.
Capturing();
}
timer1.Start();
}
也如@TheGeneral所说,保存后处理pictureBox2.Image。
当 运行 基于 GUI 的代码实际上打开网络摄像头提要并每 5 秒保存一次帧时,在 运行dom 运行 时间(可能是 5 分钟)之后或 20 分钟)发生异常“'Object in use by another process'”,可能与当前帧的保存有关。任何想法导致问题的原因以及应该进行哪些代码修改?
public partial class Form1 : Form
{
private FilterInfoCollection CaptureDevices;
private VideoCaptureDevice videoSource;
bool blncapturing;
public Form1()
{
InitializeComponent();
timer1.Enabled = false;
timer1.Interval = 5000;
blncapturing = false;
}
private void button1_Click(object sender, EventArgs e)
{
videoSource = new VideoCaptureDevice(CaptureDevices[comboBox1.SelectedIndex].MonikerString);
videoSource.NewFrame += new NewFrameEventHandler(VideoSource_NewFrame);
videoSource.Start();
timer1.Enabled = true;
}
private void VideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
if (pictureBox1.Image != null)
((IDisposable)pictureBox1.Image).Dispose();
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
}
private void Form1_Load_1(object sender, EventArgs e)
{
CaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo Device in CaptureDevices)
{
comboBox1.Items.Add(Device.Name);
}
comboBox1.SelectedIndex = 0;
videoSource = new VideoCaptureDevice();
}
private void button2_Click(object sender, EventArgs e)
{
videoSource.Stop();
pictureBox1.Image = null;
pictureBox1.Invalidate();
pictureBox2.Image = null;
pictureBox2.Invalidate();
}
private void button3_Click(object sender, EventArgs e)
{
Capturing();
}
private void button4_Click(object sender, EventArgs e)
{
if (videoSource.IsRunning == true)
{
videoSource.Stop();
}
Application.Exit(null);
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
Capturing();
timer1.Start();
}
private void Capturing()
{
try
{
if (blncapturing == false)
{
blncapturing = true;
pictureBox2.Image = (Bitmap)pictureBox1.Image.Clone();
string strGrabFileName = String.Format("C:\Users\echristo\Desktop\trial\Snapshot_{0:yyyyMMdd_hhmmss.fff}.bmp", DateTime.Now);
pictureBox2.Image.Save(strGrabFileName, System.Drawing.Imaging.ImageFormat.Jpeg) ;
blncapturing = false;
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
如果您从不同的线程访问对象,您需要一个锁。
当您从不同线程访问控件时也使用调用。
private readonly object myLock = new object();
private void VideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
lock (myLock) {
this.Invoke((Action)(() => {
if (pictureBox1.Image != null)
((IDisposable)pictureBox1.Image).Dispose();
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
}));
}
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
// you can try with timer1 inside the lock
lock (myLock) {
// you don't need invoke here, because the winforms timer runs on the main thread.
Capturing();
}
timer1.Start();
}
也如@TheGeneral所说,保存后处理pictureBox2.Image。