C3031
2026-03-06 8db52bc296f662691a17aabeeabebd713e3b576d
LB_VisionProcesses/Alogrithms/Halcon/2D/HImageEnhancementTool/HImageEnhancementToolEdit.cs
@@ -1,4 +1,11 @@
using System;
using HalconDotNet;
using LB_SmartVisionCommon;
using LB_VisionControl;
using LB_VisionProcesses.Alogrithms.Halcon;
using Microsoft.VisualBasic.ApplicationServices;
using OpenCvSharp;
using Sunny.UI.Win32;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
@@ -7,14 +14,561 @@
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace LB_VisionProcesses.Alogrithms.Halcon._2D.HEdgeExtractionTool
namespace LB_VisionProcesses.Alogrithms.Halcon
{
    public partial class HImageEnhancementToolEdit : UserControl
    public partial class HImageEnhancementToolEdit : TAlgorithmEdit
    {
        public HImageEnhancementToolEdit()
        List<RecordImageEnhancementData> recordImageEnhancementDatas = new List<RecordImageEnhancementData>();
        private int rowriginalHeight;
        public HImageEnhancementToolEdit(HImageEnhancementTool subject = null)
        {
            if (subject != null && subject is HImageEnhancementTool)
                Subject = subject;
            else
                Subject = new HImageEnhancementTool();
            //if (!(Subject.Params.ROI is HSegment))
            //    Subject.Params.ROI = new HSegment(0, 0, 250, 250);
            this.Dock = DockStyle.Fill;
            InitializeComponent();
            // 保存原始行高度
            rowriginalHeight = (int)tableLayoutPanel4.RowStyles[1].Height;
            InitializeComboBox();
            InitializeDataGridView();
            recordImageEnhancementDatas = ImageEnhancementManager.Instance.GetAllUsers();
            this.dataGridViewIE.DataSource = recordImageEnhancementDatas;
            this.dataGridViewIE.AutoGenerateColumns = true;
        }
        private void InitializeComboBox()
        {
            // 添加权限选项
            foreach (var item in Enum.GetValues(typeof(ImageEnhancementDataType)))
            {
                cmbImageEnhancement.Items.Add(item.ToString());
            }
            // 设置默认选择项
            cmbImageEnhancement.SelectedIndex = 2;
        }
        #region 算法选择下拉框
        private void cmbImageEnhancement_SelectedIndexChanged(object sender, EventArgs e)
        {
            System.Windows.Forms.ComboBox cb = sender as System.Windows.Forms.ComboBox;
            if (cb.SelectedIndex == 0)
            {
                ShowRow();
            }
            else if (cb.SelectedIndex == 1)
            {
                HideRow();
            }
            else
            {
                HideRow();
            }
        }
        private void ShowRow()
        {
            // 显示Row2(恢复高度)
            tableLayoutPanel4.RowStyles[1].SizeType = SizeType.Absolute;
            tableLayoutPanel4.RowStyles[1].Height = rowriginalHeight;
            // 显示Row2中的控件
            foreach (Control ctrl in tableLayoutPanel4.Controls)
            {
                int row = tableLayoutPanel4.GetRow(ctrl);
                if (row == 1)
                    ctrl.Visible = true;
            }
        }
        private void HideRow()
        {
            // 显示Row2(恢复高度)
            tableLayoutPanel4.RowStyles[1].SizeType = SizeType.Absolute;
            tableLayoutPanel4.RowStyles[1].Height = 0;
            // 显示Row2中的控件
            foreach (Control ctrl in tableLayoutPanel4.Controls)
            {
                int row = tableLayoutPanel4.GetRow(ctrl);
                if (row == 1)
                    ctrl.Visible = false;
            }
        }
        #endregion
        private void InitializeDataGridView()
        {
            this.dataGridViewIE.DataSource = recordImageEnhancementDatas;
            // 设置DataGridView列宽
            dataGridViewIE.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
        }
        /// <summary>
        /// 控件加载事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HImageEnhancementToolEdit_Load(object sender, EventArgs e)
        {
            pnlInputImage.Controls.Add(inputImageHSmartWindowControl);
            inputImageHSmartWindowControl.Dock = DockStyle.Fill;
            pnlRecordImage.Controls.Add(recordImageHSmartWindowControl);
            recordImageHSmartWindowControl.Dock = DockStyle.Fill;
            //遍历可以选择的Roi类型枚举
            foreach (var value in Enum.GetValues(typeof(RoiType)))
                cmbTypeRoi.Items.Add(value.ToString());
            //遍历可以选择的图像增强类型枚举
            //foreach (var value in Enum.GetValues(typeof(ImageEnhancementType)))
            //    cmbImageEnhancement.Items.Add(value.ToString());
            //遍历可以选择的Fixture枚举
            cmbFixture.Items.Add("");
            foreach (string value in IProcess.dicFixtures.Keys)
                cmbFixture.Items.Add(value.ToString());
            ckbDrawRoi.Checked = true;
            cmbTypeRoi.Text = RoiType.Segment.ToString();
            cmbImageEnhancement.Text = ImageEnhancementType.ScaleMax.ToString();
            LoadParas();
            if (Subject.Result)
            {
                lblResult.BackColor = Color.Green;
                lblResult.Text = "True";
            }
            else
            {
                lblResult.BackColor = Color.Red;
                lblResult.Text = "False";
            }
            lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
            lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
            lblRunTime.Text = $"{Subject.RunTime}ms";
        }
        private void ClearInputFields()
        {
            txtMaskWidth.Clear();
            txtMaskHeight.Clear();
            txtFactor.Clear();
            cmbImageEnhancement.SelectedIndex = 0;
        }
        private void btnAdd_Click(object sender, EventArgs e)
        {
            // 验证输入
            if (cmbImageEnhancement.SelectedIndex == 0)
            {
                if (string.IsNullOrWhiteSpace(txtMaskWidth.Text) || string.IsNullOrWhiteSpace(txtMaskHeight.Text) || string.IsNullOrWhiteSpace(txtFactor.Text))
                {
                    MessageBox.Show("请填写所有必填字段!", "提示",
                        MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
            }
            RecordImageEnhancementData filter = new RecordImageEnhancementData();
            filter.MaskWidth = this.txtMaskWidth.Text;
            filter.MaskHight = this.txtMaskHeight.Text;
            filter.Factor = this.txtFactor.Text;
            filter.FilterName = (ImageEnhancementDataType)this.cmbImageEnhancement.SelectedIndex;
            // 添加到 UserManager
            bool success = ImageEnhancementManager.Instance.AddUser(filter);
            if (success)
            {
                recordImageEnhancementDatas.Add(filter);
                //MessageBox.Show("用户添加成功!", "提示",
                //    MessageBoxButtons.OK, MessageBoxIcon.Information);
                // 清空输入框
                ClearInputFields();
            }
            else
            {
                MessageBox.Show("添加用户失败!", "错误",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            recordImageEnhancementDatas = ImageEnhancementManager.Instance.GetAllUsers();
            this.dataGridViewIE.DataSource = recordImageEnhancementDatas;
            this.dataGridViewIE.AutoGenerateColumns = true;
        }
        private void btnDel_Click(object sender, EventArgs e)
        {
            // 检查是否有选中的滤波类型
            if (cmbImageEnhancement.SelectedIndex < 0)
            {
                MessageBox.Show("请选择要删除的滤波类型!", "提示",
                    MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            try
            {
                DataGridViewRow selectedRow = dataGridViewIE.SelectedRows[0];
                string filterToDel = selectedRow.Cells[0].Value?.ToString();
                ImageEnhancementDataType filterToDelete = (ImageEnhancementDataType)cmbImageEnhancement.SelectedIndex;
                // 查找对应的记录
                RecordImageEnhancementData filterToRemove = null;
                // 从本地列表中查找
                foreach (var filter in recordImageEnhancementDatas)
                {
                    if (filter.FilterName.ToString() == filterToDel)
                    {
                        filterToRemove = filter;
                        break;
                    }
                }
                if (filterToRemove == null)
                {
                    MessageBox.Show("未找到对应的记录!", "提示",
                        MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
                // 确认删除
                DialogResult result = MessageBox.Show(
                    $"确定要删除 '{filterToDel}' 记录吗?",
                    "确认删除",
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question,
                    MessageBoxDefaultButton.Button2); // 默认选择"否"
                if (result == DialogResult.No)
                    return;
                // 从管理器中删除
                bool success = ImageEnhancementManager.Instance.DeleteUser(filterToRemove);
                if (success)
                {
                    // 从本地列表中删除
                    recordImageEnhancementDatas.Remove(filterToRemove);
                    MessageBox.Show("删除成功!", "提示",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    MessageBox.Show("删除失败!", "错误",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                recordImageEnhancementDatas = ImageEnhancementManager.Instance.GetAllUsers();
                this.dataGridViewIE.DataSource = recordImageEnhancementDatas;
                this.dataGridViewIE.AutoGenerateColumns = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("请选择要删除的算子");
            }
        }
        /// <summary>
        /// 更新运行参数
        /// </summary>
        public override void UpdataInputs()
        {
            //设置运行参数
            double dResult = 0;
            int iResult = 0;
            if (cmbFixture.Text == "")
                Subject.Params.Fixture = new Fixture();
            else if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
                Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
            Type type = inputImageHSmartWindowControl.oRoi?.GetType();
            switch (type)
            {
                case Type t when t == typeof(HRectangle2):
                    HRectangle2 hRectangle2 = (HRectangle2)inputImageHSmartWindowControl.oRoi;
                    Subject.Params.ROI
                        = new HRectangle2(hRectangle2.X - Subject.Params.Fixture.X, hRectangle2.Y - Subject.Params.Fixture.Y
                        , hRectangle2.Phi - Subject.Params.Fixture.Phi, hRectangle2.Width, hRectangle2.Height);
                    break;
                case Type t when t == typeof(HCircle):
                    HCircle hCircle = (HCircle)inputImageHSmartWindowControl.oRoi;
                    Subject.Params.ROI
                        = new HCircle(hCircle.X - Subject.Params.Fixture.X, hCircle.Y - Subject.Params.Fixture.Y, hCircle.Radius);
                    break;
                case Type t when t == typeof(HSegment):
                    HSegment hSegment = (HSegment)inputImageHSmartWindowControl.oRoi;
                    Subject.Params.ROI
                        = new HSegment(hSegment.StartX - Subject.Params.Fixture.X, hSegment.StartY - Subject.Params.Fixture.Y
                        , hSegment.EndX - Subject.Params.Fixture.X, hSegment.EndY - Subject.Params.Fixture.Y);
                    break;
                default:
                    Subject.Params.ROI = new ROI();
                    break;
            }
        }
        /// <summary>
        /// 加载运行参数
        /// </summary>
        public override void LoadParas()
        {
            this.BeginInvoke(new Action(() =>
            {
                if (Subject.InputImage != null && Subject.InputImage is HObject)
                    inputImageHSmartWindowControl.ShowHoImage((HObject)Subject.InputImage);
                Type type = Subject.Params.ROI?.GetType();
                if (Subject.Params.ROI != null)
                {
                    switch (type)
                    {
                        case Type t when t == typeof(HRectangle2):
                            cmbTypeRoi.Text = RoiType.Rectangle2.ToString();
                            break;
                        case Type t when t == typeof(HCircle):
                            cmbTypeRoi.Text = RoiType.Circle.ToString();
                            break;
                        case Type t when t == typeof(HSegment):
                            cmbTypeRoi.Text = RoiType.Segment.ToString();
                            break;
                        default:
                            cmbTypeRoi.Text = RoiType.None.ToString();
                            break;
                    }
                    if (cmbTypeRoi.Text.ToString() != "None")
                        ckbDrawRoi.Checked = true;
                    else
                        ckbDrawRoi.Checked = false;
                    inputImageHSmartWindowControl.oRoi = Subject.Params.ROI;
                }
                if (Subject.Params.Fixture != null)
                    cmbFixture.Text = Subject.Params.Fixture.strName;
                else
                    cmbFixture.Text = "";
                switch (type)
                {
                    case Type t when t == typeof(HRectangle2):
                        inputImageHSmartWindowControl.oRoi
                             = new HRectangle2(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
                             , Subject.Params.ROI.Phi + Subject.Params.Fixture.Phi, ((HRectangle2)Subject.Params.ROI).Width, ((HRectangle2)Subject.Params.ROI).Height);
                        break;
                    case Type t when t == typeof(HCircle):
                        inputImageHSmartWindowControl.oRoi
                        = new HCircle(Subject.Params.ROI.X + Subject.Params.Fixture.X, Subject.Params.ROI.Y + Subject.Params.Fixture.Y
                        , ((HCircle)Subject.Params.ROI).Radius);
                        break;
                    case Type t when t == typeof(HSegment):
                        inputImageHSmartWindowControl.oRoi
                        = new HSegment(((HSegment)Subject.Params.ROI).StartX + Subject.Params.Fixture.X, ((HSegment)Subject.Params.ROI).StartY + Subject.Params.Fixture.Y
                        , ((HSegment)Subject.Params.ROI).EndX + Subject.Params.Fixture.X, ((HSegment)Subject.Params.ROI).EndY + Subject.Params.Fixture.Y);
                        break;
                    default:
                        inputImageHSmartWindowControl.oRoi = null;
                        break;
                }
            }));
        }
        #region 工具栏按钮事件
        /// <summary>
        /// 点击运行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public override void btnRun_Click(object sender, EventArgs e)
        {
            if (Subject.InputImage != null)
                InputImage = Subject.InputImage;
            DateTime StartTime = DateTime.Now;
            Run();
            //更新日志与结果
            this.BeginInvoke(new Action(() =>
            {
                if (Subject.Result)
                {
                    lblResult.BackColor = Color.Green;
                    lblResult.Text = "True";
                    recordImageHSmartWindowControl.SetColor("green");
                }
                else
                {
                    lblResult.BackColor = Color.Red;
                    lblResult.Text = "False";
                    recordImageHSmartWindowControl.SetColor("red");
                }
                lblMsg.Text = Msg.Length > 50 ? Msg.Substring(0, 50) : Msg;
                lblMsgToolTip.SetToolTip(BtmStatusStrip, Msg);
                lblRunTime.Text = $"{(DateTime.Now - StartTime).TotalMilliseconds}ms";
                UpdataOutputs();
                imgTabControl.SelectedTab = tabPageRecordImage;
                if (Subject.InputImage != null && Subject.InputImage is HObject)
                {
                    HOperatorSet.GetImageSize((HObject)Subject.InputImage, out HTuple ho_ImageWidth, out HTuple ho_ImageHeight);
                    recordImageHSmartWindowControl.ShowHoImage((HObject)Subject.InputImage);
                }
                //先判断子类再判断父类
                if (Subject.Record != null && Subject.Record is MsgRecord msgRecord)
                {
                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_OK, true);
                    recordImageHSmartWindowControl.DispObj(msgRecord.RecordObject_NG, false);
                    for (int i = 0; i < msgRecord.Msg.Length; i++)
                        recordImageHSmartWindowControl.ShowMsg(msgRecord.Msg[i]
                            , 1 == msgRecord.Result[i] ? true : false, msgRecord.Column[i], msgRecord.Row[i]);
                }
                else if (Subject.Record != null && Subject.Record is ObjectRecord objRecord)
                {
                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_OK, true);
                    recordImageHSmartWindowControl.DispObj(objRecord.RecordObject_NG, false);
                }
                GC.Collect();
            }));
        }
        /// <summary>
        /// 工具栏“导图”
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public override void btnLoadImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            // 设置文件对话框的属性
            openFileDialog.Multiselect = false; // 不允许多选
            // 设置文件过滤器,支持多种文件类型
            openFileDialog.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|All Files (*.*)|*.*";
            // 显示文件对话框
            DialogResult result = openFileDialog.ShowDialog();
            // 处理对话框返回结果
            if (result == DialogResult.OK)
            {
                // 获取用户选择的文件名
                string[] selectedFiles = openFileDialog.FileNames;
                if (selectedFiles.Length > 0)
                {
                    HOperatorSet.ReadImage(out HObject ho_Image, selectedFiles[0]);
                    //判断是否为灰度图
                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
                    {
                        HOperatorSet.CountChannels(ho_Image, out HTuple hv_Channels);
                        if (hv_Channels.TupleInt() != 1)
                        {
                            HOperatorSet.Rgb1ToGray(ho_Image, out ho_Image);
                            //更新日志与结果
                            this.BeginInvoke(new Action(() =>
                            {
                                lblMsg.Text = "导入图片非灰度图,自动转换为灰度图";
                            }));
                        }
                        InputImage = ho_Image;
                        imgTabControl.SelectedTab = tabPageInputImage;
                        inputImageHSmartWindowControl.oRoi = inputImageHSmartWindowControl.oRoi;
                    }
                }
            }
        }
        /// <summary>
        /// 工具栏“保存”
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public override void btnSaveParas_Click(object sender, EventArgs e) { base.btnSaveParas_Click(sender, e); }
        #endregion
        #region ROI功能
        /// <summary>
        /// 是否启用ROI
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public override void ckbDrawRoi_CheckedChanged(object sender, EventArgs e)
        {
            if (ckbDrawRoi.Checked)
            {
                inputImageHSmartWindowControl.bAollowDraw = true;
                imgTabControl.SelectedTab = tabPageInputImage;
            }
            else
            {
                inputImageHSmartWindowControl.bAollowDraw = false;
                Subject.Params.ROI = new ROI();
            }
        }
        /// <summary>
        /// ROI下拉框改变事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public override void cmbTypeRoi_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (Enum.TryParse(cmbTypeRoi.Text.ToString(), out RoiType type))
                {
                    HTuple hv_imageWidth = 0;
                    HTuple hv_imageHeight = 0;
                    if (InputImage != null && InputImage is HObject)
                        HOperatorSet.GetImageSize((HObject)InputImage, out hv_imageWidth, out hv_imageHeight);
                    switch (type)
                    {
                        case RoiType.Rectangle2:
                            inputImageHSmartWindowControl.oRoi
                                = new HRectangle2(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, 0
                                , hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
                            break;
                        case RoiType.Circle:
                            inputImageHSmartWindowControl.oRoi
                                = new HCircle(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2, hv_imageWidth.TupleReal() / 4);
                            break;
                        case RoiType.Segment:
                            inputImageHSmartWindowControl.oRoi
                                = new HSegment(0, 0, hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4);
                            break;
                        case RoiType.None:
                        default:
                            inputImageHSmartWindowControl.oRoi = null;
                            break;
                    }
                }
            }
            catch { }
        }
        public override void cmbFixture_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
                    Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
                else
                    Subject.Params.Fixture = new Fixture();
            }
            catch { }
        }
        #endregion
    }
}