我想使用我的相机捕获网络摄像头.为此,我使用了2个参考:AForge.Video.dll和AForge.Video.DirectShow.dll.
Here’s我发现一个片段:
public FilterInfoCollection CamsCollection; public VideoCaptureDevice Cam = null; void Cam_NewFrame(object sender,NewFrameEventArgs eventArgs) { frameholder.Source = (Bitmap)eventArgs.Frame.Clone(); /* ^ * Here it cannot convert implicitly from System.Drawing.Bitmap to * System.Windows.Media.ImageSource */ } private void startcam_Click(object sender,RoutedEventArgs e) { CamsCollection = new FilterInfoCollection(FilterCategory.VideoInputDevice); Cam = new VideoCaptureDevice(CamsCollection[1].MonikerString); Cam.NewFrame += new NewFrameEventHandler(Cam_NewFrame); Cam.Start(); } private void stopcam_Click(object sender,RoutedEventArgs e) { Cam.Stop(); }
}
他们使用PictureBox来显示帧.当我在WPF工作时,我使用了this
总结一下这里我的代码看起来像现在.
public FilterInfoCollection CamsCollection; public VideoCaptureDevice Cam = null; void Cam_NewFrame(object sender,NewFrameEventArgs eventArgs) { System.Drawing.Image imgforms = (Bitmap)eventArgs.Frame.Clone(); BitmapImage bi = new BitmapImage(); bi.BeginInit (); MemoryStream ms = new MemoryStream (); imgforms.Save(ms,ImageFormat.Bmp); ms.Seek(0,SeekOrigin.Begin); bi.StreamSource = ms; frameholder.Source = bi; /* ^ runtime error here because `bi` is occupied by another thread. */ bi.EndInit(); } private void startcam_Click(object sender,RoutedEventArgs e) { CamsCollection = new FilterInfoCollection(FilterCategory.VideoInputDevice); Cam = new VideoCaptureDevice(CamsCollection[1].MonikerString); Cam.NewFrame += new NewFrameEventHandler(Cam_NewFrame); Cam.Start(); } private void stopcam_Click(object sender,RoutedEventArgs e) { Cam.Stop(); }
解决方法
编辑1:详细解释我的
blogpost在同一主题.
我将Dispatcher类的错误修正为互斥体:
void Cam_NewFrame(object sender,NewFrameEventArgs eventArgs) { System.Drawing.Image imgforms = (Bitmap)eventArgs.Frame.Clone(); BitmapImage bi = new BitmapImage(); bi.BeginInit(); MemoryStream ms = new MemoryStream(); imgforms.Save(ms,ImageFormat.Bmp); ms.Seek(0,SeekOrigin.Begin); bi.StreamSource = ms; bi.EndInit(); //Using the freeze function to avoid cross thread operations bi.Freeze(); //Calling the UI thread using the Dispatcher to update the 'Image' WPF control Dispatcher.BeginInvoke(new ThreadStart(delegate { frameholder.Source = bi; /*frameholder is the name of the 'Image' WPF control*/ })); }
现在它按预期运行,我获得了良好的性能,没有任何下降的fps.