5ddadba291ea2d9dba78259973594a4664b94f57..e33a8aa1dd7b9d0a29cc38a38f40d0308aa9dcf4
2026-01-09 C3032
冲突解决
e33a8a 对比 | 目录
2026-01-08 C3032
添加增益选择下拉框并优化相机初始化逻辑
37aff9 对比 | 目录
已修改2个文件
234 ■■■■ 文件已修改
LB_VisionProcesses/Cameras/2DCameraForm.cs 165 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_VisionProcesses/Cameras/LBCameras/LBCamera.cs 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LB_VisionProcesses/Cameras/2DCameraForm.cs
@@ -80,9 +80,23 @@
        private System.Windows.Forms.Timer updateTimer;
        Total total = new Total { iImageCount = 0, iScanCount = 0 };
        DateTime startGrabtime = DateTime.Now;
        // 动态添加的增益下拉框
        private ComboBox cmbGain;
        private void CameraForm_Load(object sender, EventArgs e)
        {
            // 初始化增益下拉框
            cmbGain = new ComboBox();
            cmbGain.Visible = false; // 默认隐藏
            cmbGain.DropDownStyle = ComboBoxStyle.DropDownList;
            cmbGain.Size = txtGain.Size;
            cmbGain.Location = txtGain.Location;
            cmbGain.Font = txtGain.Font;
            cmbGain.SelectedIndexChanged += CmbGain_SelectedIndexChanged;
            this.txtGain.Parent.Controls.Add(cmbGain);
            cmbGain.BringToFront();
            // 设置一个定时器,每 100 毫秒触发一次
            updateTimer = new System.Windows.Forms.Timer();
            updateTimer.Interval = 1000;  // 设置定时器间隔为 1000 毫秒
@@ -124,6 +138,16 @@
                if (camConfig.OutputImage != null && camConfig.OutputImage is Bitmap bitmap)
                    onlinePictureBox.Image = bitmap;
                lblCapTime.Text = $"{camConfig.RunTime}ms";
            }
        }
        private void CmbGain_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (camera != null && camera is LBCamera && cmbGain.Visible)
            {
                // LBCamera SetGain expects double which is cast to int for enum value
                // ComboBox index corresponds directly to EnumAnalogGain value (0-4)
                camera.SetGain((double)cmbGain.SelectedIndex);
            }
        }
@@ -232,34 +256,71 @@
            // 尝试将输入字符串转换为枚举值
            if (Enum.TryParse(cmbBrand.Text, true, out CameraBrand brand))
            {
                if (camera != null)
                string selectedSN = cmbSN.Text.ToString();
                bool isReusingExisting = false;
                // 1. 尝试从现有字典中查找已初始化的相机
                if (dicCameras != null && dicCameras.ContainsKey(selectedSN))
                {
                    var existingCamera = dicCameras[selectedSN];
                    // 确保品牌匹配
                    if (existingCamera.Brand == brand)
                    {
                        camera = existingCamera;
                        isReusingExisting = true;
                    }
                }
                // 2. 如果没有复用现有相机,且当前camera对象不是我们要复用的对象,则清理旧对象
                if (!isReusingExisting && camera != null)
                {
                    camera.ImageGrabbed -= GetImageBllComplete;
                    camera.Dispose();
                    camera = null;
                }
                // 使用 switch 语句来判断枚举值
                switch (brand)
                // 3. 如果没有复用,则创建新实例
                if (!isReusingExisting)
                {
                    case CameraBrand.LBCamera:
                        camera = new LBCamera();
                        break;
                    case CameraBrand.HRCamera:
                        camera = new HRCamera();
                        break;
                    default:
                        Debug.WriteLine($"【{DateTime.Now:HH:mm:ss.fff}】未知品牌");
                        return;
                    // 使用 switch 语句来判断枚举值
                    switch (brand)
                    {
                        case CameraBrand.LBCamera:
                            camera = new LBCamera();
                            break;
                        case CameraBrand.HRCamera:
                            camera = new HRCamera();
                            break;
                        default:
                            Debug.WriteLine($"【{DateTime.Now:HH:mm:ss.fff}】未知品牌");
                            return;
                    }
                }
                IntPtr displayHandle = onlinePictureBox.Handle;
                onlinePictureBox.Visible = true;
                if (cmbSN.Items.Count > 0 && camera.InitDevice(cmbSN.Text.ToString(), displayHandle))
                bool initSuccess = false;
                if (isReusingExisting)
                {
                    // 复用时不需要再次InitDevice,但可能需要更新显示句柄(视具体SDK实现而定,LBCamera通常不需要)
                    initSuccess = true;
                    MessageBox.Show(camera.SN + "已连接 (复用)");
                }
                else
                {
                    if (cmbSN.Items.Count > 0 && camera.InitDevice(selectedSN, displayHandle))
                    {
                        initSuccess = true;
                        MessageBox.Show(camera.SN + "打开成功");
                    }
                }
                if (initSuccess)
                {
                    // 重新绑定显示回调
                    camera.ImageGrabbed -= GetImageBllComplete;
                    camera.ImageGrabbed += GetImageBllComplete;
                    MessageBox.Show(camera.SN + "打开成功");
                    this.btnEdit.Enabled = true;
                }
            }
@@ -267,18 +328,51 @@
            {
                Debug.WriteLine($"【{DateTime.Now:HH:mm:ss.fff}】无效的枚举值!");
            }
            // ... (rest of the UI update logic)
            if (camera != null)
            {
                this.BeginInvoke(new Action(() =>
                {
                    double exp = 0;
                    double gain = 0;
                    camera.GetExpouseTime(out exp);
                    txtExp.Text = exp.ToString();
                    if (camera is LBCamera lbCam)
                    {
                        // 切换到下拉框显示
                        txtGain.Visible = false;
                        cmbGain.Visible = true;
                        // 填充选项 (对应 EnumAnalogGain: Gain_1_0, Gain_1_3, Gain_1_9, Gain_2_8, Gain_5_5)
                        cmbGain.Items.Clear();
                        cmbGain.Items.AddRange(new object[] { "1.0x", "1.3x", "1.9x", "2.8x", "5.5x" });
                    camera.GetGain(out gain);
                    txtGain.Text = gain.ToString();
                        var config = lbCam.GetSensorConfig();
                        txtExp.Text = config.ExposureTime.ToString();
                        // 设置当前选中的增益
                        int gainIndex = (int)config.AnalogGain;
                        if (gainIndex >= 0 && gainIndex < cmbGain.Items.Count)
                        {
                            cmbGain.SelectedIndex = gainIndex;
                        }
                        else
                        {
                            cmbGain.SelectedIndex = 0;
                        }
                    }
                    else
                    {
                        // 恢复文本框显示
                        txtGain.Visible = true;
                        cmbGain.Visible = false;
                        double exp = 0;
                        double gain = 0;
                        camera.GetExpouseTime(out exp);
                        txtExp.Text = exp.ToString();
                        camera.GetGain(out gain);
                        txtGain.Text = gain.ToString();
                    }
                    camera.GetTriggerMode(out TriggerMode mode, out TriggerSource source);
@@ -622,7 +716,8 @@
        private void txtGain_TextChanged(object sender, EventArgs e)
        {
            if (camera == null)
            // 如果正在使用下拉框模式(LBCamera),忽略文本框的变化
            if (camera == null || (cmbGain != null && cmbGain.Visible))
                return;
            double gain = 10;
@@ -724,19 +819,25 @@
            if (camera != null)
            {
                camera.ImageGrabbed -= GetImageBllComplete;
                camera.StopGrabbing();
                // 检查该相机是否由主系统管理
                bool isManagedBySystem = dicCameras != null && dicCameras.ContainsKey(camera.SN);
                camera.GetTriggerMode(out _, out TriggerSource actualSource);
                if (radioButtonSoft.Checked)
                    camera.SetTriggerMode(TriggerMode.On, TriggerSource.Software);
                else
                    camera.SetTriggerMode(TriggerMode.On, actualSource);
                // LBCamera在StartGrabbing时会直接开启激光和采集,因此关闭窗口时不应自动重启采集
                // 其他相机(如2D相机)通常需要保持Grabbing状态以接收触发
                if (camera.Brand != CameraBrand.LBCamera)
                if (!isManagedBySystem)
                {
                    camera.StartGrabbing();
                    // 只有非托管的(临时打开的)相机才停止采集和释放
                    camera.StopGrabbing();
                    camera.GetTriggerMode(out _, out TriggerSource actualSource);
                    if (radioButtonSoft.Checked)
                        camera.SetTriggerMode(TriggerMode.On, TriggerSource.Software);
                    else
                        camera.SetTriggerMode(TriggerMode.On, actualSource);
                    if (camera.Brand != CameraBrand.LBCamera)
                    {
                        camera.StartGrabbing();
                    }
                }
            }
LB_VisionProcesses/Cameras/LBCameras/LBCamera.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
@@ -310,8 +311,8 @@
        public override bool SetExpouseTime(double value) => SetParam(EnumNameId.ExposureTime, (float)value);
        public override bool GetExpouseTime(out double value) { float v; bool r = GetParam(EnumNameId.ExposureTime, out v); value = v; return r; }
        public override bool SetGain(double gain) => SetParam(EnumNameId.AnalogGain, (float)gain);
        public override bool GetGain(out double gain) { float v; bool r = GetParam(EnumNameId.AnalogGain, out v); gain = v; return r; }
        public override bool SetGain(double gain) => SetParam(EnumNameId.AnalogGain, (int)gain);
        public override bool GetGain(out double gain) { int v; bool r = GetParam(EnumNameId.AnalogGain, out v); gain = v; return r; }
        public override bool SetTriggerMode(TriggerMode mode, TriggerSource triggerEnum = TriggerSource.Line0)
        {
@@ -588,13 +589,49 @@
        private void SyncConfigFromCamera()
        {
            foreach (EnumNameId id in Enum.GetValues(typeof(EnumNameId)))
            try
            {
                int iVal = 0; double dVal = 0; int eVal = 0;
                if (PHM6000Profiler.GetProfilerParameter(_cameraHandle, (int)id, ref iVal, ref dVal, ref eVal) == 0)
                if (!_isConnected) return;
                PropertyInfo[] props = _sensorConfig.GetType().GetProperties();
                foreach (PropertyInfo p in props)
                {
                    // Update _sensorConfig values here if needed
                    // 跳过自定义参数
                    var iscustomAttr = p.GetCustomAttribute<IsCustomAttribute>();
                    if (iscustomAttr != null) continue;
                    if (Enum.TryParse(typeof(EnumNameId), p.Name, out object nameIdObj))
                    {
                        EnumNameId nameId = (EnumNameId)nameIdObj;
                        int intValue = 0;
                        double doubleValue = 0;
                        int enumValue = 0;
                        if (PHM6000Profiler.GetProfilerParameter(_cameraHandle, (int)nameId, ref intValue, ref doubleValue, ref enumValue) == 0)
                        {
                            if (p.PropertyType == typeof(int))
                            {
                                p.SetValue(_sensorConfig, intValue);
                            }
                            else if (p.PropertyType == typeof(float))
                            {
                                p.SetValue(_sensorConfig, (float)doubleValue);
                            }
                            else if (p.PropertyType == typeof(double))
                            {
                                p.SetValue(_sensorConfig, doubleValue);
                            }
                            else // Enum or other types
                            {
                                p.SetValue(_sensorConfig, enumValue);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                AsyncLogHelper.Error($"LBCamera: SyncConfigFromCamera error - {ex.Message}");
            }
        }
@@ -602,6 +639,13 @@
        {
            if (!_isConnected) return false;
            return PHM6000Profiler.SetProfilerParameter(_cameraHandle, (int)id, 0, value, 0) == 0;
        }
        private bool SetParam(EnumNameId id, int value)
        {
            if (!_isConnected) return false;
            // 对于枚举类型,通常通过 enumValue (最后一个参数) 传递
            return PHM6000Profiler.SetProfilerParameter(_cameraHandle, (int)id, 0, 0, value) == 0;
        }
        private bool GetParam(EnumNameId id, out float value)
@@ -616,6 +660,19 @@
            }
            return false;
        }
        private bool GetParam(EnumNameId id, out int value)
        {
            value = 0;
            if (!_isConnected) return false;
            int iVal = 0; double dVal = 0; int eVal = 0;
            if (PHM6000Profiler.GetProfilerParameter(_cameraHandle, (int)id, ref iVal, ref dVal, ref eVal) == 0)
            {
                value = eVal; // Assuming it returns in enumValue
                return true;
            }
            return false;
        }
        #endregion
    }
}