使用Emgu.CV设置科研相机曝光/增益时帧未更新的问题
问题描述
环境信息
- 操作系统:Windows 2008 R2
- 相机型号:Sony 20 MP IMX Camera
- Emgu.CV版本:3.1.0.1
- .NET Framework版本:4.7.2
按照nncam相机文档修改曝光参数后,使用Emgu.CV的QueryFrame获取帧时画面并未更新。我的应用依赖手动调节曝光和增益的能力,必须解决这个问题。
目前已确认相机的曝光参数确实已变更,但pictureBox中显示的图像没有变化,且初始化相机时已经关闭了自动曝光功能。
疑问
- 是否遗漏了关键步骤?
- 能否同时将Emgu.CV作为帧抓取器,并使用相机原生的曝光/增益控制(如
cam_.get_ExpoTime)?
相关代码
相机初始化代码
private void InitializeCamera() { Nncam.DeviceV2[] arr = Nncam.EnumV2(); if (arr.Length > 0) { cam_ = Nncam.Open(arr[0].id); // Assign the camera object to the cam_ field // Turn off autoexposure cam_.put_AutoExpoEnable(false); // Set exposure and gain cam_.put_ExpoTime(1001); } else { MessageBox.Show("No Nncam camera found."); } // Initialize Emgu.CV capture capture = new Capture(0); // Assuming the Nncam camera is the default camera }
设置曝光参数代码
private void SetExposureFromTextbox() { if (cam_ == null) { MessageBox.Show("Camera not initialized."); return; } uint newExposure; if (uint.TryParse(exposureTextBox.Text, out newExposure)) { cam_.put_ExpoTime(newExposure); } else { MessageBox.Show("Invalid exposure value."); } }
抓帧显示代码
private void GrabAndDisplayFrame() { using (Mat frame = capture.QueryFrame()) { if (frame != null) { pictureBox1.Image = frame.ToImage<Bgr, byte>().Bitmap; //Retrieve exposure value from the camera uint updatedCameraExposure; cam_.get_ExpoTime(out updatedCameraExposure); currentExposureTextBox.Text = updatedCameraExposure.ToString(); } } }
按钮点击触发代码
private void capture_push_Click(object sender, EventArgs e) { // Dispose of the current capture object if (capture != null) { capture.Dispose(); capture = null; } // Create a new capture object capture = new Capture(0); // nncam is the default camera. SetExposureFromTextbox(); GrabAndDisplayFrame(); }
问题原因及解决方法
核心问题是你同时用了两套独立的相机控制通道:一边通过Nncam原生SDK打开并控制相机(cam_对象),另一边又用Emgu.CV的Capture重新打开了同一个相机设备。两者的控制状态完全独立,Emgu.CV的Capture会使用自己的默认配置,完全无视你通过Nncam SDK设置的曝光参数。
解决步骤
方案一:统一使用Nncam SDK完成控制+抓帧
放弃Emgu.CV的Capture,直接用Nncam原生API抓帧并转换格式显示,确保参数控制和帧抓取共用同一个相机实例:
// 修改抓帧显示方法 private void GrabAndDisplayFrame() { if (cam_ == null) return; IntPtr framePtr; // 调用Nncam的抓帧API(具体方法请参考SDK文档,示例为GetFrame) if (cam_.GetFrame(out framePtr, 1000)) // 1000ms超时时间 { // 根据相机的输出格式创建Mat,需匹配实际分辨率和像素格式 Mat frame = new Mat(cam_.Height, cam_.Width, DepthType.Cv8U, 3, framePtr, cam_.Width * 3); pictureBox1.Image = frame.ToImage<Bgr, byte>().Bitmap; // 更新当前曝光值显示 uint updatedCameraExposure; cam_.get_ExpoTime(out updatedCameraExposure); currentExposureTextBox.Text = updatedCameraExposure.ToString(); } }
同时删除InitializeCamera和capture_push_Click中所有关于Emgu.CV Capture的代码。
方案二:统一使用Emgu.CV完成控制+抓帧
如果想继续用Emgu.CV的Capture抓帧,就直接通过Emgu.CV的API设置曝光参数,放弃Nncam原生SDK的控制:
// 修改设置曝光的方法 private void SetExposureFromTextbox() { if (capture == null) { MessageBox.Show("Camera not initialized."); return; } uint newExposure; if (uint.TryParse(exposureTextBox.Text, out newExposure)) { // 关闭自动曝光 capture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.AutoExposure, 0); // 设置曝光时间(注意参数单位需匹配相机,部分为微秒,部分为毫秒) capture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.Exposure, newExposure); } else { MessageBox.Show("Invalid exposure value."); } }
同时删除InitializeCamera中所有关于Nncam.Open的代码,完全用Emgu.CV初始化相机。
关键注意事项
- 同一台相机不能被多个设备句柄同时打开,否则必然出现控制冲突或状态不同步的问题。
- 不同SDK对曝光参数的单位可能不同,需要对照相机文档确认参数的范围和单位。
内容的提问来源于stack exchange,提问作者lishiyua
相关产品推荐
相关产品推荐

