You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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中显示的图像没有变化,且初始化相机时已经关闭了自动曝光功能。

疑问

  1. 是否遗漏了关键步骤?
  2. 能否同时将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 21:44:54