using HalconDotNet; using MvCameraControl; using LB_VisionControls; using Newtonsoft.Json; using SharpCompress.Common; using System.Diagnostics; using System.Reflection; using System.Threading.Tasks; using System.Windows.Forms; using static LB_VisionProcesses.Alogrithms.Halcon.HCaltabTool; namespace LB_VisionProcesses.Alogrithms.Halcon { public partial class HCaltabToolEdit : TAlgorithmEdit { public HCaltabToolEdit(HCaltabTool subject = null) { if (subject != null && subject is HCaltabTool) Subject = subject; else Subject = new HCaltabTool(); this.Dock = DockStyle.Fill; InitializeComponent(); } public UserHSmartWindowControl createModelImageHSmartWindowControl = new UserHSmartWindowControl(); /// /// 控件加载事件 /// /// /// private void HCaltabToolEdit_Load(object sender, EventArgs e) { pnlInputImage.Controls.Add(inputImageHSmartWindowControl); inputImageHSmartWindowControl.Dock = DockStyle.Fill; pnlRecordImage.Controls.Add(recordImageHSmartWindowControl); recordImageHSmartWindowControl.Dock = DockStyle.Fill; pnlCreateModelImage.Controls.Add(createModelImageHSmartWindowControl); createModelImageHSmartWindowControl.Dock = DockStyle.Fill; //遍历可以选择的Roi类型枚举 foreach (var value in Enum.GetValues(typeof(RoiType))) cmbTypeRoi.Items.Add(value.ToString()); //遍历可以选择的Model类型枚举 //foreach (var value in Enum.GetValues(typeof(ModelType))) // cmbModelType.Items.Add(value.ToString()); cmbTypeRoi.Text = RoiType.None.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"; btnClearImage.Click += (sender, e) => { if (Subject is HCaltabTool hCaltabTool) hCaltabTool.ClearCaltbImages(); }; btnCreateCaltb.Click += (sender, e) => { if (Subject is HCaltabTool hCaltabTool) { int XNum = Convert.ToInt32(dtxtInputParam1.Text); int YNum = Convert.ToInt32(dtxtInputParam2.Text); double MarkDist = Convert.ToDouble(dtxtInputParam3.Text); double DiameterRatio = Convert.ToDouble(dtxtInputParam4.Text); if (hCaltabTool.CreateCaltbFile(XNum, YNum, MarkDist, DiameterRatio, out string FilePath)) { // 处理路径中的空格和特殊字符 string escapedPath = FilePath.Trim().Replace("\"", "\"\""); // 使用ProcessStartInfo更可靠 using (Process process = new Process()) { process.StartInfo.FileName = "explorer.exe"; process.StartInfo.Arguments = $"\"{escapedPath}\""; process.StartInfo.UseShellExecute = true; process.StartInfo.CreateNoWindow = true; process.Start(); } } } }; btnGrabImage.Click += (sender, e) => { if (Subject is HCaltabTool hCaltabTool) { if (InputImage != null && InputImage is HObject hObject) hCaltabTool.AddCaltbImage(hObject); else MessageBox.Show("请先导入或采集图像!"); } }; btnStartCaltb.Click += (sender, e) => { if (Subject is HCaltabTool hCaltabTool) { int XNum = Convert.ToInt32(dtxtInputParam1.Text); int YNum = Convert.ToInt32(dtxtInputParam2.Text); double MarkDist = Convert.ToDouble(dtxtInputParam3.Text); double DiameterRatio = Convert.ToDouble(dtxtInputParam4.Text); int Focus = Convert.ToInt32(dtxtInputParam5.Text); int Kappa = Convert.ToInt32(dtxtInputParam6.Text); double Sx = Convert.ToDouble(dtxtInputParam7.Text); double Sy = Convert.ToDouble(dtxtInputParam8.Text); int Width = Convert.ToInt32(dtxtInputParam9.Text); int Height = Convert.ToInt32(dtxtInputParam10.Text); if (!hCaltabTool.Caltb(XNum, YNum, MarkDist, DiameterRatio, Focus, Kappa, Sx, Sy, Width, Height)) MessageBox.Show(hCaltabTool.Msg); else { imgTabControl.SelectedTab = tabPageModelImage; createModelImageHSmartWindowControl.ShowHoImage(hCaltabTool.Image); imgTabControl.SelectedTab = tabPageRecordImage; recordImageHSmartWindowControl.ShowHoImage(hCaltabTool.Image); //先判断子类再判断父类 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); } MessageBox.Show($"畸变矫正成功"); } } }; } /// /// 更新运行参数 /// public override void UpdataInputs() { #region 输入参数 Subject.Params.Inputs["XNum"] = dtxtInputParam1.Text; Subject.Params.Inputs["YNum"] = dtxtInputParam2.Text; Subject.Params.Inputs["MarkDist"] = dtxtInputParam3.Text; Subject.Params.Inputs["DiameterRatio"] = dtxtInputParam4.Text; Subject.Params.Inputs["Focus"] = dtxtInputParam5.Text; Subject.Params.Inputs["Kappa"] = dtxtInputParam6.Text; Subject.Params.Inputs["Sx"] = dtxtInputParam7.Text; Subject.Params.Inputs["Sy"] = dtxtInputParam8.Text; Subject.Params.Inputs["Width"] = dtxtInputParam9.Text; Subject.Params.Inputs["Height"] = dtxtInputParam10.Text; #endregion } private System.Windows.Forms.ToolTip toolTip = new System.Windows.Forms.ToolTip(); private void ShowToolTip(Control control, string message) => toolTip.SetToolTip(control, message); /// /// 加载运行参数 /// public override void LoadParas() { this.BeginInvoke(new Action(() => { #region 恢复输入 this.lblInputParam1.Visible = true; this.lblInputParam2.Visible = true; this.lblInputParam3.Visible = true; this.lblInputParam4.Visible = true; this.lblInputParam5.Visible = true; this.lblInputParam6.Visible = true; this.lblInputParam7.Visible = true; this.lblInputParam8.Visible = true; this.lblInputParam9.Visible = true; this.lblInputParam10.Visible = true; this.dtxtInputParam1.Visible = true; this.dtxtInputParam2.Visible = true; this.dtxtInputParam3.Visible = true; this.dtxtInputParam4.Visible = true; this.dtxtInputParam5.Visible = true; this.dtxtInputParam6.Visible = true; this.dtxtInputParam7.Visible = true; this.dtxtInputParam8.Visible = true; this.dtxtInputParam9.Visible = true; this.dtxtInputParam10.Visible = true; #endregion #region 输入参数 this.lblInputParam1.Text = "XNum"; lblInputParam1.MouseHover += (s, e) => ShowToolTip((Control)s, "横坐标个数XNum"); dtxtInputParam1.Text = Subject.Params.Inputs["XNum"]?.ToString(); this.lblInputParam2.Text = "XNum"; lblInputParam2.MouseHover += (s, e) => ShowToolTip((Control)s, "纵坐标个数YNum"); dtxtInputParam2.Text = Subject.Params.Inputs["YNum"]?.ToString(); this.lblInputParam3.Text = "MarkDist"; lblInputParam3.MouseHover += (s, e) => ShowToolTip((Control)s, "间距MarkDist"); dtxtInputParam3.Text = Subject.Params.Inputs["MarkDist"]?.ToString(); this.lblInputParam4.Text = "DiameterRatio"; lblInputParam4.MouseHover += (s, e) => ShowToolTip((Control)s, "比值DiameterRatio"); dtxtInputParam4.Text = Subject.Params.Inputs["DiameterRatio"]?.ToString(); this.lblInputParam5.Text = "焦距"; lblInputParam5.MouseHover += (s, e) => ShowToolTip((Control)s, "焦距Focus"); dtxtInputParam5.Text = Subject.Params.Inputs["Focus"]?.ToString(); this.lblInputParam6.Text = "Kappa"; lblInputParam6.MouseHover += (s, e) => ShowToolTip((Control)s, "Kappa"); dtxtInputParam6.Text = Subject.Params.Inputs["Kappa"]?.ToString(); dtxtInputParam6.Enabled = false; this.lblInputParam7.Text = "Sx"; lblInputParam7.MouseHover += (s, e) => ShowToolTip((Control)s, "像元宽Sx"); dtxtInputParam7.Text = Subject.Params.Inputs["Sx"]?.ToString(); this.lblInputParam8.Text = "Sy"; lblInputParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "像元高Sy"); dtxtInputParam8.Text = Subject.Params.Inputs["Sy"]?.ToString(); this.lblInputParam9.Text = "Width"; lblInputParam9.MouseHover += (s, e) => ShowToolTip((Control)s, "图宽Width"); dtxtInputParam9.Text = Subject.Params.Inputs["Width"]?.ToString(); this.lblInputParam10.Text = "Height"; lblInputParam10.MouseHover += (s, e) => ShowToolTip((Control)s, "图高Height"); dtxtInputParam10.Text = Subject.Params.Inputs["Height"]?.ToString(); #endregion 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; } switch (type) { case Type t when t == typeof(HRectangle2): inputImageHSmartWindowControl.oRoi = new HRectangle2(Subject.Params.ROI.X, Subject.Params.ROI.Y , Subject.Params.ROI.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.ROI.Y, ((HCircle)Subject.Params.ROI).Radius); break; default: inputImageHSmartWindowControl.oRoi = null; break; } if (Subject is HCaltabTool hCaltabTool) createModelImageHSmartWindowControl.ShowHoImage(hCaltabTool.Image); })); } /// /// 更新输出结果 /// public override void UpdataOutputs() { this.BeginInvoke(new Action(() => { //存在反序列化错乱的情况需要使用自定义的转换器 //dtxtCenterX.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterX"]); //dtxtCenterY.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["CenterY"]); //dtxtPhi.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Phi"]); //dtxtScore.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Score"]); //dtxtCount.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Count"]); })); } /// /// 点击运行 /// /// /// 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.OutputImage != null && Subject.OutputImage is HObject) { HOperatorSet.GetImageSize((HObject)Subject.OutputImage, out HTuple ho_ImageWidth, out HTuple ho_ImageHeight); recordImageHSmartWindowControl.ShowHoImage((HObject)Subject.OutputImage); } //先判断子类再判断父类 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(); })); } 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) { if (hv_Channels.TupleInt() == 4) { HOperatorSet.Decompose4(ho_Image, out HObject R, out HObject G, out HObject B, out _); HOperatorSet.Compose3(R, G, B, out ho_Image); } HOperatorSet.Rgb1ToGray(ho_Image, out ho_Image); //更新日志与结果 this.BeginInvoke(new Action(() => { lblMsg.Text = "导入图片非灰度图,自动转换为灰度图"; })); } InputImage = ho_Image; imgTabControl.SelectedTab = tabPageInputImage; inputImageHSmartWindowControl.oRoi = inputImageHSmartWindowControl.oRoi; } } } } public override void btnSaveParas_Click(object sender, EventArgs e) { //保存前需要更新输入参数Inputs UpdataInputs(); // 创建 SaveFileDialog 实例 using (SaveFileDialog saveFileDialog = new SaveFileDialog()) { // 设置对话框标题 saveFileDialog.Title = "保存文件"; // 设置默认路径 saveFileDialog.InitialDirectory = System.Windows.Forms.Application.StartupPath; // 设置文件类型过滤器 saveFileDialog.Filter = "文本文件 (*.json)|*.json|所有文件 (*.*)|*.*"; // 设置默认文件名 saveFileDialog.FileName = Subject.strProcessName + ".json"; // 显示对话框并检查用户是否点击了保存按钮 if (saveFileDialog.ShowDialog() == DialogResult.OK) { // 获取用户选择的文件路径 string fullPath = saveFileDialog.FileName; Debug.WriteLine("选择的文件路径是: " + fullPath); Subject.strProcessName = Path.GetFileNameWithoutExtension(fullPath); Subject.Save(Path.GetDirectoryName(fullPath)); } } } public override void btnLoadParas_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); // 设置文件对话框的属性 openFileDialog.Multiselect = false; // 不允许多选 // 设置文件过滤器,支持多种文件类型 openFileDialog.Filter = "Ini Files (*.json)|*.json|All Files (*.*)|*.*"; // 显示文件对话框 DialogResult result = openFileDialog.ShowDialog(); // 处理对话框返回结果 if (result == DialogResult.OK) { // 获取用户选择的文件名 string[] selectedFiles = openFileDialog.FileNames; if (selectedFiles.Length > 0) { Subject.Load(selectedFiles[0]); LoadParas(); } } } 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(); } } 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 { } } } }