C#高版本EmguCV中如何将Mat对象转换为Bitmap
问题原因
新版本EmguCV(4.x及以上版本)将Mat转位图的相关逻辑从核心库拆分到了独立NuGet包中,原有的ToBitmap()方法没有被删除,只是作为扩展方法存在,需要单独安装对应包才能调用。另外你当前的代码存在两个额外问题:
- 将
VideoCapture放在点击事件内用using包裹,方法执行完会立刻释放摄像头资源,仅能获取单帧画面,无法持续输出摄像头流 - 你使用的是WPF的
Image控件,其Source属性接收BitmapSource类型,就算引入ToBitmap()返回WinForm下的Bitmap类型,直接赋值也会报类型不匹配错误
解决步骤
1. 安装依赖
右键项目打开NuGet包管理器,搜索安装Emgu.CV.Bitmap,注意包版本必须和你当前安装的EmguCV核心包版本完全一致,避免出现版本兼容问题。
代码文件顶部引入必要命名空间:
using Emgu.CV; using System.Windows.Media.Imaging; using System.Windows.Media;
2. 修正摄像头调用与转换逻辑
不要在点击事件内瞬时创建、释放摄像头对象,将摄像头实例和帧刷新定时器定义为类级别变量,配合Mat转BitmapSource的方法实现画面持续渲染,完整可运行代码如下:
// 类级别变量,避免方法执行完被回收 private VideoCapture _webcamCapture; private System.Windows.Threading.DispatcherTimer _frameRefreshTimer; private void OpenWebcam_Click(object sender, RoutedEventArgs e) { // 防止重复初始化摄像头 if (_webcamCapture != null) return; _webcamCapture = new VideoCapture(0); // 传入0代表调用系统默认摄像头,多设备可修改索引 if (!_webcamCapture.IsOpened) { MessageBox.Show("摄像头启动失败,请检查设备权限与连接状态"); _webcamCapture.Dispose(); _webcamCapture = null; return; } // 定时拉取帧刷新画面,间隔33ms约对应30帧刷新率 _frameRefreshTimer = new System.Windows.Threading.DispatcherTimer(); _frameRefreshTimer.Interval = TimeSpan.FromMilliseconds(33); _frameRefreshTimer.Tick += (s, args) => { using (Mat currentFrame = _webcamCapture.QueryFrame()) { if (currentFrame == null) return; image.Source = ConvertMatToBitmapSource(currentFrame); } }; _frameRefreshTimer.Start(); } /// <summary> /// EmguCV Mat对象转WPF可用的BitmapSource /// </summary> private BitmapSource ConvertMatToBitmapSource(Mat mat) { // 统一转换为Bgr24格式,适配WPF像素格式要求,避免颜色错位、花屏 if (mat.NumberOfChannels == 1) CvInvoke.CvtColor(mat, mat, ColorConversion.Gray2Bgr); else if (mat.NumberOfChannels == 4) CvInvoke.CvtColor(mat, mat, ColorConversion.Bgra2Bgr); return BitmapSource.Create( pixelWidth: mat.Width, pixelHeight: mat.Height, dpiX: 96, dpiY: 96, pixelFormat: PixelFormats.Bgr24, palette: null, buffer: mat.DataPointer, bufferSize: mat.Stride * mat.Height, stride: mat.Stride); } // 窗口关闭时释放资源,避免摄像头被进程长期占用 protected override void OnClosed(EventArgs e) { _frameRefreshTimer?.Stop(); _webcamCapture?.Stop(); _webcamCapture?.Dispose(); base.OnClosed(e); }
补充说明
- 如果你是WinForm开发,只需要拿到
System.Drawing.Bitmap类型,安装完Emgu.CV.Bitmap包、引入Emgu.CV命名空间后,就可以直接调用mat.ToBitmap()扩展方法,不会再出现找不到方法的报错 - 帧刷新间隔可以根据需求调整,设置为16ms约对应60帧刷新率,对性能要求不高的场景设置为50ms(20帧)也可满足基础预览需求
- 摄像头读取、帧渲染建议放在UI线程调度,避免跨线程调用控件的权限报错
内容的提问来源于stack exchange,提问作者Dotnet_Developer10
相关产品推荐
相关产品推荐

