using HalconDotNet; using LB_VisionControl; using Newtonsoft.Json; using System.Diagnostics; using System.Reflection; using System.Threading.Tasks; using System.Windows.Forms; using static LB_VisionProcesses.Alogrithms.Halcon.HFindModelTool; namespace LB_VisionProcesses.Alogrithms.Halcon { public partial class HFindModelToolEdit : TAlgorithmEdit { public HFindModelToolEdit(HFindModelTool subject = null) { if (subject != null && subject is HFindModelTool) Subject = subject; else Subject = new HFindModelTool(); this.Dock = DockStyle.Fill; InitializeComponent(); } public HWindowControl modelImageHWindowControl = new HWindowControl(); public UserHSmartWindowControl createModelImageHSmartWindowControl = new UserHSmartWindowControl(); private bool isLeftDown = false; private int MaskSize { get { if (int.TryParse(txtMaskSize.Text, out int size)) return size; else return 10; } } private HObject Mask = new HObject(); private HObject FirstModelImage = new HObject(); private HObject TempModelImage = new HObject(); /// /// 控件加载事件 /// /// /// private void HFindModelToolEdit_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; grpModel.Controls.Add(modelImageHWindowControl); modelImageHWindowControl.Dock = DockStyle.Fill; // 设置轮廓默认为绿色 HOperatorSet.SetColor(modelImageHWindowControl.HalconWindow, "red"); HOperatorSet.SetLineWidth(modelImageHWindowControl.HalconWindow, 5); modelImageHWindowControl.MouseDown += (sender, e) => { if (e.Button == MouseButtons.Left) isLeftDown = true; }; modelImageHWindowControl.MouseUp += (sender, e) => { if (e.Button == MouseButtons.Left) isLeftDown = true; }; modelImageHWindowControl.MouseMove += (sender, e) => { if (e.Button == MouseButtons.Left && isLeftDown && ckbStartMask.Checked) { // 点击鼠标 if (TempModelImage != null && TempModelImage.IsInitialized()) { try { HOperatorSet.GetMposition(modelImageHWindowControl.HalconWindow, out HTuple row, out HTuple col, out HTuple button_state); if (row.Length != 0 && col.Length != 0) { HTuple hv_color = new HTuple(); hv_color[0] = 0; hv_color[1] = 0; hv_color[2] = 255; HOperatorSet.GenCircle(out HObject ho_Circle, row, col, MaskSize); if (!Mask.IsInitialized()) Mask = ho_Circle; else HOperatorSet.Union2(ho_Circle, Mask, out Mask); HOperatorSet.GetImageSize(TempModelImage, out HTuple width, out HTuple height); HOperatorSet.GenRectangle1(out HObject allROI, 0, 0, height, width); HOperatorSet.Difference(allROI, Mask, out HObject subROI); HOperatorSet.ReduceDomain(TempModelImage, subROI, out HObject ModelImage); HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow); TAlgorithm.DispImage(ModelImage, modelImageHWindowControl.HalconWindow); } } catch { } } } }; ckbStartMask.CheckedChanged += (sender, e) => { try { if (ckbStartMask.Checked) { // 点击鼠标 if (FirstModelImage == null || !FirstModelImage.IsInitialized()) FirstModelImage = ((HFindModelTool)Subject).ModelID.hoImage.CopyObj(1, -1); ; TempModelImage = FirstModelImage.CopyObj(1, -1); Mask.Dispose(); Mask = new HObject(); HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow); TAlgorithm.DispImage(FirstModelImage, modelImageHWindowControl.HalconWindow); } else { DialogResult res = MessageBox.Show("是否使用掩膜图片保存模板?", "提示", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); //保存结果信息 /// 参数1:显示文本,参数2:标题,参数3:按键类型,参数4:显示图标 if (res == DialogResult.Yes) //保存 { try { if (TempModelImage != null && TempModelImage is HObject) { if (Enum.TryParse(cmbModelType.Text, out ModelType modelType)) { string NumLevels = this.dtxtModelParam1.Text; string AngleStep = this.dtxtModelParam2.Text; double AngleStart = Convert.ToDouble(this.dtxtModelParam3.Text); double AngleExtent = Convert.ToDouble(this.dtxtModelParam4.Text); double ScaleRMin = Convert.ToDouble(this.dtxtModelParam5.Text); double ScaleRMax = Convert.ToDouble(this.dtxtModelParam6.Text); double ScaleCMin = Convert.ToDouble(this.dtxtModelParam7.Text); double ScaleCMax = Convert.ToDouble(this.dtxtModelParam8.Text); string Optimization = this.dtxtModelParam9.Text; string Metric = this.dtxtModelParam10.Text; string Contrast = this.dtxtModelParam11.Text; int MinContrast = Convert.ToInt16(this.dtxtModelParam12.Text); //HRectangle2 ROI = (HRectangle2)createModelImageHSmartWindowControl.oRoi; //HOperatorSet.GenRectangle2(out HObject hRectangle, ROI.Row, ROI.Column, ROI.Phi // , ROI.SemiLength1, ROI.SemiLength2); HObject hoDomainImage = FirstModelImage as HObject; HTuple hv_Channels = new HTuple(); //判断是否为灰度图 using (HDevDisposeHelper dh = new HDevDisposeHelper()) { try { HOperatorSet.CountChannels(hoDomainImage, out hv_Channels); if (hv_Channels.TupleInt() != 1) HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage); //转换后再次检查是否为灰度图 HOperatorSet.CountChannels(hoDomainImage, out hv_Channels); if (hv_Channels.TupleInt() != 1) HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage); } catch { } } HOperatorSet.GetImageSize(FirstModelImage, out HTuple width, out HTuple height); HOperatorSet.GenRectangle1(out HObject allROI, 0, 0, height, width); HOperatorSet.Difference(allROI, Mask, out HObject subROI); HOperatorSet.ReduceDomain(FirstModelImage, subROI, out HObject ModelImage); bool bCreateModel = false; switch (modelType) { case ModelType.局部变形模板: bCreateModel = ((HFindModelTool)Subject).CreateModel (ModelImage, modelType, NumLevels , AngleStart, AngleExtent, AngleStep , ScaleRMin, ScaleRMax, "auto" , ScaleCMin, ScaleCMax, "auto" , Optimization, Metric, Contrast, MinContrast); break; case ModelType.各向异形模板: default: bCreateModel = ((HFindModelTool)Subject).CreateModel (ModelImage, modelType, NumLevels , AngleStart, AngleExtent, AngleStep , ScaleRMin, ScaleRMax, "auto" , ScaleCMin, ScaleCMax, "auto" , Optimization, Metric, Contrast, MinContrast); break; } if (bCreateModel) { HObject ho_ModelContours = new HObject(); switch (((HFindModelTool)Subject).ModelID.Type) { case ModelType.局部变形模板: HOperatorSet.GetDeformableModelContours(out ho_ModelContours, ((HFindModelTool)Subject).ModelID.hvModel, 1); break; case ModelType.各向异形模板: default: HOperatorSet.GetShapeModelContours(out ho_ModelContours, ((HFindModelTool)Subject).ModelID.hvModel, 1); break; } HOperatorSet.GetImageSize(((HFindModelTool)Subject).ModelID.hoImage, out HTuple hv_Width, out HTuple hv_Height); HOperatorSet.VectorAngleToRigid(-hv_Height / 2, -hv_Width / 2, 0, 0, 0, 0, out HTuple hv_HomMat2D); HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_ModelContours, hv_HomMat2D); //建模成功导航到子页 parasTabControl.SelectedTab = tabPageRunParas; HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow); TAlgorithm.DispImage(((HFindModelTool)Subject).ModelID.hoImage, modelImageHWindowControl.HalconWindow); TAlgorithm.SetColor(modelImageHWindowControl.HalconWindow, "red"); TAlgorithm.DispObj(ho_ModelContours, modelImageHWindowControl.HalconWindow); TAlgorithm.DispMsg("创建模板成功", modelImageHWindowControl.HalconWindow, true); } else { HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow); TAlgorithm.DispMsg("创建模板失败", modelImageHWindowControl.HalconWindow, false); } } } TempModelImage.Dispose(); } catch { HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow); TAlgorithm.DispMsg("创建模板失败", modelImageHWindowControl.HalconWindow, false); } } } } catch { } }; //cmbModelType.SelectedIndex = cmbModelType.FindString("形状"); UpdataInputsUI(); // 设置显示样式 toolTip.AutoPopDelay = 5000;//提示信息的可见时间 toolTip.InitialDelay = 500;//事件触发多久后出现提示 toolTip.ReshowDelay = 500;//指针从一个控件移向另一个控件时,经过多久才会显示下一个提示框 toolTip.ShowAlways = true;//是否显示提示框 //遍历可以选择的Roi类型枚举 foreach (var value in Enum.GetValues(typeof(RoiType))) cmbTypeRoi.Items.Add(value.ToString()); //遍历可以选择的Fixture枚举 cmbFixture.Items.Add(""); foreach (string value in IProcess.dicFixtures.Keys) cmbFixture.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"; } /// /// 更新运行参数 /// public override void UpdataInputs() { //设置运行参数 double dResult = 0; int iResult = 0; cmbModelType.Text = ((HFindModelTool)Subject).ModelID.Type.ToString(); if (Enum.TryParse(cmbModelType.SelectedItem.ToString(), out ModelType modelType)) { switch (modelType) { case ModelType.局部变形模板: //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI //, ScaleRMin, ScaleRMax //, ScaleCMin, ScaleCMax //, MinScore, NumMatches, MaxOverlap //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels) //, Greediness, ResultType, new HTuple(), new HTuple() //, out hv_Score, out hv_CenterRow, out hv_CenterColumn); #region 输入参数 Subject.Params.Inputs["AngleStart"] = dtxtInputParam1.Text; Subject.Params.Inputs["AngleExtent"] = dtxtInputParam2.Text; Subject.Params.Inputs["ScaleRMin"] = dtxtInputParam3.Text; Subject.Params.Inputs["ScaleRMax"] = dtxtInputParam4.Text; Subject.Params.Inputs["ScaleCMin"] = dtxtInputParam5.Text; Subject.Params.Inputs["ScaleCMax"] = dtxtInputParam6.Text; Subject.Params.Inputs["MinScore"] = dtxtInputParam7.Text; Subject.Params.Inputs["NumMatches"] = dtxtInputParam8.Text; Subject.Params.Inputs["MaxOverlap"] = dtxtInputParam9.Text; Subject.Params.Inputs["ResultType"] = dtxtInputParam10.Text; Subject.Params.Inputs["NumLevels"] = dtxtInputParam11.Text; Subject.Params.Inputs["Greediness"] = dtxtInputParam12.Text; Subject.Params.Inputs["MinCount"] = dtxtInputParam13.Text; Subject.Params.Inputs["MaxCount"] = dtxtInputParam14.Text; #endregion break; case ModelType.各向异形模板: default: //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI //, ScaleRMin, ScaleRMax //, ScaleCMin, ScaleCMax //, MinScore, NumMatches, MaxOverlap, SubPixel //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels) //, Greediness #region 输入参数 Subject.Params.Inputs["AngleStart"] = dtxtInputParam1.Text; Subject.Params.Inputs["AngleExtent"] = dtxtInputParam2.Text; Subject.Params.Inputs["ScaleRMin"] = dtxtInputParam3.Text; Subject.Params.Inputs["ScaleRMax"] = dtxtInputParam4.Text; Subject.Params.Inputs["ScaleCMin"] = dtxtInputParam5.Text; Subject.Params.Inputs["ScaleCMax"] = dtxtInputParam6.Text; Subject.Params.Inputs["MinScore"] = dtxtInputParam7.Text; Subject.Params.Inputs["NumMatches"] = dtxtInputParam8.Text; Subject.Params.Inputs["MaxOverlap"] = dtxtInputParam9.Text; Subject.Params.Inputs["SubPixel"] = dtxtInputParam10.Text; Subject.Params.Inputs["NumLevels"] = dtxtInputParam11.Text; Subject.Params.Inputs["Greediness"] = dtxtInputParam12.Text; Subject.Params.Inputs["MinCount"] = dtxtInputParam13.Text; Subject.Params.Inputs["MaxCount"] = dtxtInputParam14.Text; #endregion break; } //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; } } } /// /// 加载运行参数 /// public override void LoadParas() { this.BeginInvoke(new Action(() => { cmbModelType.Text = ((HFindModelTool)Subject).ModelID.Type.ToString(); if (Enum.TryParse(cmbModelType.Text, out ModelType modelType)) { switch (modelType) { case ModelType.局部变形模板: //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI //, ScaleRMin, ScaleRMax //, ScaleCMin, ScaleCMax //, MinScore, NumMatches, MaxOverlap //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels) //, Greediness, ResultType, new HTuple(), new HTuple() #region 输入参数 dtxtInputParam1.Text = Subject.Params.Inputs["AngleStart"].ToString(); dtxtInputParam2.Text = Subject.Params.Inputs["AngleExtent"].ToString(); dtxtInputParam3.Text = Subject.Params.Inputs["ScaleRMin"].ToString(); dtxtInputParam4.Text = Subject.Params.Inputs["ScaleRMax"].ToString(); dtxtInputParam5.Text = Subject.Params.Inputs["ScaleCMin"].ToString(); dtxtInputParam6.Text = Subject.Params.Inputs["ScaleCMax"].ToString(); dtxtInputParam7.Text = Subject.Params.Inputs["MinScore"].ToString(); dtxtInputParam8.Text = Subject.Params.Inputs["NumMatches"].ToString(); dtxtInputParam9.Text = Subject.Params.Inputs["MaxOverlap"].ToString(); dtxtInputParam10.Text = Subject.Params.Inputs["ResultType"].ToString(); dtxtInputParam11.Text = Subject.Params.Inputs["NumLevels"].ToString(); dtxtInputParam12.Text = Subject.Params.Inputs["Greediness"].ToString(); dtxtInputParam13.Text = Subject.Params.Inputs["MinCount"].ToString(); dtxtInputParam14.Text = Subject.Params.Inputs["MaxCount"].ToString(); #endregion break; case ModelType.各向异形模板: default: #region 输入参数 dtxtInputParam1.Text = Subject.Params.Inputs["AngleStart"].ToString(); dtxtInputParam2.Text = Subject.Params.Inputs["AngleExtent"].ToString(); dtxtInputParam3.Text = Subject.Params.Inputs["ScaleRMin"].ToString(); dtxtInputParam4.Text = Subject.Params.Inputs["ScaleRMax"].ToString(); dtxtInputParam5.Text = Subject.Params.Inputs["ScaleCMin"].ToString(); dtxtInputParam6.Text = Subject.Params.Inputs["ScaleCMax"].ToString(); dtxtInputParam7.Text = Subject.Params.Inputs["MinScore"].ToString(); dtxtInputParam8.Text = Subject.Params.Inputs["NumMatches"].ToString(); dtxtInputParam9.Text = Subject.Params.Inputs["MaxOverlap"].ToString(); dtxtInputParam10.Text = Subject.Params.Inputs["ResultType"].ToString(); dtxtInputParam11.Text = Subject.Params.Inputs["NumLevels"].ToString(); dtxtInputParam12.Text = Subject.Params.Inputs["Greediness"].ToString(); dtxtInputParam13.Text = Subject.Params.Inputs["MinCount"].ToString(); dtxtInputParam14.Text = Subject.Params.Inputs["MaxCount"].ToString(); #endregion break; } } if (Subject.InputImage != null && Subject.InputImage is HImage) { using (HImage hImage = (HImage)Subject.InputImage) { hImage.GetImageSize(out HTuple ho_ImageWidth, out HTuple ho_ImageHeight); inputImageHSmartWindowControl.ShowHoImage(hImage); } } 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; } parasTabControl.SelectedTab = tabPageRunParas; ShowModel(((HFindModelTool)Subject).ModelID); parasTabControl.SelectedTab = tabPageInputParas; })); } /// /// 更新输出结果 /// 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.InputImage != null && Subject.InputImage is HImage) { using (HImage hImage = (HImage)Subject.InputImage) { hImage.GetImageSize(out HTuple ho_ImageWidth, out HTuple ho_ImageHeight); recordImageHSmartWindowControl.ShowHoImage(hImage); } } //先判断子类再判断父类 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) { 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); ((HFindModelTool)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) { ((HFindModelTool)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 { } } 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 { } } private System.Windows.Forms.ToolTip toolTip = new System.Windows.Forms.ToolTip(); private void ShowToolTip(Control control, string message) => toolTip.SetToolTip(control, message); // 通过反射清除所有事件处理程序 public void ClearAllEventHandlers() { // 获取事件字段 FieldInfo field = typeof(Label).GetField("MouseHover", BindingFlags.NonPublic | BindingFlags.Instance); if (field != null) { // 将事件字段设为 null,移除所有事件处理程序 field.SetValue(this, null); } } private void cmbModelType_SelectedIndexChanged(object sender, EventArgs e) => UpdataInputsUI(); void UpdataInputsUI() { this.BeginInvoke(() => { #region 清空输入 this.lblInputParam1.Visible = false; this.lblInputParam2.Visible = false; this.lblInputParam3.Visible = false; this.lblInputParam4.Visible = false; this.lblInputParam5.Visible = false; this.lblInputParam6.Visible = false; this.lblInputParam7.Visible = false; this.lblInputParam8.Visible = false; this.lblInputParam9.Visible = false; this.lblInputParam10.Visible = false; this.lblInputParam11.Visible = false; this.lblInputParam12.Visible = false; this.lblInputParam13.Visible = false; this.lblInputParam14.Visible = false; this.lblInputParam15.Visible = false; this.lblInputParam16.Visible = false; this.lblInputParam17.Visible = false; this.lblInputParam18.Visible = false; this.dtxtInputParam1.Visible = false; this.dtxtInputParam2.Visible = false; this.dtxtInputParam3.Visible = false; this.dtxtInputParam4.Visible = false; this.dtxtInputParam5.Visible = false; this.dtxtInputParam6.Visible = false; this.dtxtInputParam7.Visible = false; this.dtxtInputParam8.Visible = false; this.dtxtInputParam9.Visible = false; this.dtxtInputParam10.Visible = false; this.dtxtInputParam11.Visible = false; this.dtxtInputParam12.Visible = false; this.dtxtInputParam13.Visible = false; this.dtxtInputParam14.Visible = false; this.dtxtInputParam15.Visible = false; this.dtxtInputParam16.Visible = false; this.dtxtInputParam17.Visible = false; this.dtxtInputParam18.Visible = false; #endregion #region 清空模板 this.lblModelParam1.Visible = false; this.lblModelParam2.Visible = false; this.lblModelParam3.Visible = false; this.lblModelParam4.Visible = false; this.lblModelParam5.Visible = false; this.lblModelParam6.Visible = false; this.lblModelParam7.Visible = false; this.lblModelParam8.Visible = false; this.lblModelParam9.Visible = false; this.lblModelParam10.Visible = false; this.lblModelParam11.Visible = false; this.lblModelParam12.Visible = false; this.lblModelParam13.Visible = false; this.lblModelParam14.Visible = false; this.lblModelParam15.Visible = false; this.lblModelParam16.Visible = false; this.lblModelParam17.Visible = false; this.lblModelParam18.Visible = false; this.dtxtModelParam1.Visible = false; this.dtxtModelParam2.Visible = false; this.dtxtModelParam3.Visible = false; this.dtxtModelParam4.Visible = false; this.dtxtModelParam5.Visible = false; this.dtxtModelParam6.Visible = false; this.dtxtModelParam7.Visible = false; this.dtxtModelParam8.Visible = false; this.dtxtModelParam9.Visible = false; this.dtxtModelParam10.Visible = false; this.dtxtModelParam11.Visible = false; this.dtxtModelParam12.Visible = false; this.dtxtModelParam13.Visible = false; this.dtxtModelParam14.Visible = false; this.dtxtModelParam15.Visible = false; this.dtxtModelParam16.Visible = false; this.dtxtModelParam17.Visible = false; this.dtxtModelParam18.Visible = false; #endregion ClearAllEventHandlers(); if (Enum.TryParse(cmbModelType.Text, out ModelType modelType)) { switch (modelType) { case ModelType.局部变形模板: //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI //, ScaleRMin, ScaleRMax //, ScaleCMin, ScaleCMax //, MinScore, NumMatches, MaxOverlap //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels) //, Greediness, ResultType, new HTuple(), new HTuple() #region 输入参数 //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI this.lblInputParam1.Text = "起始角度"; this.dtxtInputParam1.Text = Subject.Params.Inputs["AngleStart"].ToString(); this.lblInputParam1.Visible = true; this.dtxtInputParam1.Visible = true; this.dtxtInputParam1.Enabled = true; lblInputParam1.MouseHover += (s, e) => ShowToolTip((Control)s, "搜索时的起始角度AngleStart"); this.lblInputParam2.Text = "角度范围"; this.dtxtInputParam2.Text = Subject.Params.Inputs["AngleExtent"].ToString(); this.lblInputParam2.Visible = true; this.dtxtInputParam2.Visible = true; this.dtxtInputParam2.Enabled = true; lblInputParam2.MouseHover += (s, e) => ShowToolTip((Control)s, "搜索时的角度范围AngleExtent,'0'表示无角度搜索"); //, ScaleRMin, ScaleRMax this.lblInputParam3.Text = "纵向缩放最小值"; this.dtxtInputParam3.Text = Subject.Params.Inputs["ScaleRMin"].ToString(); this.lblInputParam3.Visible = true; this.dtxtInputParam3.Visible = true; this.dtxtInputParam3.Enabled = true; lblInputParam3.MouseHover += (s, e) => ShowToolTip((Control)s, "纵向缩放最小值ScaleRMin"); this.lblInputParam4.Text = "纵向缩放最大值"; this.dtxtInputParam4.Text = Subject.Params.Inputs["ScaleRMax"].ToString(); this.lblInputParam4.Visible = true; this.dtxtInputParam4.Visible = true; this.dtxtInputParam4.Enabled = true; lblInputParam4.MouseHover += (s, e) => ShowToolTip((Control)s, "纵向缩放最大值ScaleRMax"); //, ScaleCMin, ScaleCMax this.lblInputParam5.Text = "横向缩放最小值"; this.dtxtInputParam5.Text = Subject.Params.Inputs["ScaleCMin"].ToString(); this.lblInputParam5.Visible = true; this.dtxtInputParam5.Visible = true; this.dtxtInputParam5.Enabled = true; lblInputParam5.MouseHover += (s, e) => ShowToolTip((Control)s, "横向缩放最小值ScaleCMin"); this.lblInputParam6.Text = "横向缩放最大值"; this.dtxtInputParam6.Text = Subject.Params.Inputs["ScaleCMax"].ToString(); this.lblInputParam6.Visible = true; this.dtxtInputParam6.Visible = true; this.dtxtInputParam6.Enabled = true; lblInputParam6.MouseHover += (s, e) => ShowToolTip((Control)s, "横向缩放最大值ScaleCMax"); //, MinScore, NumMatches, MaxOverlap, ResultType this.lblInputParam7.Text = "最小分数"; this.dtxtInputParam7.Text = Subject.Params.Inputs["MinScore"].ToString(); this.lblInputParam7.Visible = true; this.dtxtInputParam7.Visible = true; this.dtxtInputParam7.Enabled = true; lblInputParam7.MouseHover += (s, e) => ShowToolTip((Control)s, "被找到的模板最小分数MinScore"); this.lblInputParam8.Text = "期望个数"; this.dtxtInputParam8.Text = Subject.Params.Inputs["NumMatches"].ToString(); this.lblInputParam8.Visible = true; this.dtxtInputParam8.Visible = true; this.dtxtInputParam8.Enabled = true; lblInputParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "要找到的模板最多的实例数NumMatches,'0'则找到所有可能的匹配"); this.lblInputParam9.Text = "最大重叠比例"; this.dtxtInputParam9.Text = Subject.Params.Inputs["MaxOverlap"].ToString(); this.lblInputParam9.Visible = true; this.dtxtInputParam9.Visible = true; this.dtxtInputParam9.Enabled = true; lblInputParam9.MouseHover += (s, e) => ShowToolTip((Control)s, "允许找到的模型实例的最大重叠比例MaxOverlap[较小的值会避免找到多个相似的匹配]"); this.lblInputParam10.Text = "ResultType"; this.dtxtInputParam10.Text = Subject.Params.Inputs["ResultType"]?.ToString(); this.lblInputParam10.Visible = true; this.dtxtInputParam10.Visible = true; this.dtxtInputParam10.Enabled = false; lblInputParam10.MouseHover += (s, e) => ShowToolTip((Control)s, "计算精度的设置ResultType['1'得到亚像素精度]"); //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels) //, Greediness, , new HTuple(), new HTuple() this.lblInputParam11.Text = "搜索时金字塔的层级"; this.dtxtInputParam11.Text = "0"; this.lblInputParam11.Visible = true; this.dtxtInputParam11.Visible = true; this.dtxtInputParam11.Enabled = false; lblInputParam11.MouseHover += (s, e) => ShowToolTip((Control)s, "搜索时金字塔的层级"); this.lblInputParam12.Text = "贪婪度"; this.dtxtInputParam12.Text = Subject.Params.Inputs["Greediness"]?.ToString(); this.lblInputParam12.Visible = true; this.dtxtInputParam12.Visible = true; this.dtxtInputParam12.Enabled = true; lblInputParam12.MouseHover += (s, e) => ShowToolTip((Control)s, "贪婪度,越高速度越快[一般都设为0.8,太大容易出现找不到的情况]"); this.lblInputParam13.Text = "最小数量"; this.dtxtInputParam13.Text = Subject.Params.Inputs["MinCount"]?.ToString(); this.lblInputParam13.Visible = true; this.dtxtInputParam13.Visible = true; this.dtxtInputParam13.Enabled = true; lblInputParam13.MouseHover += (s, e) => ShowToolTip((Control)s, "匹配结果要求的最小数量"); this.lblInputParam14.Text = "最大数量"; this.dtxtInputParam14.Text = Subject.Params.Inputs["MaxCount"]?.ToString(); this.lblInputParam14.Visible = true; this.dtxtInputParam14.Visible = true; this.dtxtInputParam14.Enabled = true; lblInputParam14.MouseHover += (s, e) => ShowToolTip((Control)s, "匹配结果要求的最大数量"); #endregion //UpdataInputs(); //NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels) // , AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep) // , ScaleRMin, ScaleRMax, ScaleRStep == "auto" ? ScaleRStep : Convert.ToDouble(ScaleRStep) // , ScaleCMin, ScaleCMax, ScaleCStep == "auto" ? ScaleCStep : Convert.ToDouble(ScaleCStep) // , Optimization, Metric // , Contrast, MinContrast #region 模板参数 //NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels) this.lblModelParam1.Text = "金字塔的层级"; this.dtxtModelParam1.Text = "auto"; this.lblModelParam1.Visible = true; this.dtxtModelParam1.Visible = true; this.dtxtModelParam1.Enabled = false; lblModelParam1.MouseHover += (s, e) => ShowToolTip((Control)s, "搜索时金字塔的层级NumLevels,'0'表示不使用金字塔"); // , AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep) this.lblModelParam2.Text = "角度步长"; this.dtxtModelParam2.Text = "auto"; this.lblModelParam2.Visible = true; this.dtxtModelParam2.Visible = true; this.dtxtModelParam2.Enabled = false; lblModelParam2.MouseHover += (s, e) => ShowToolTip((Control)s, "角度范围内进行旋转的步长AngleStep,'auto'表示由系统自动选择合适的步长"); this.lblModelParam3.Text = "起始角度"; this.dtxtModelParam3.Text = "-5"; this.lblModelParam3.Visible = true; this.dtxtModelParam3.Visible = true; this.dtxtModelParam3.Enabled = true; lblModelParam3.MouseHover += (s, e) => ShowToolTip((Control)s, "搜索时的起始角度AngleStart"); this.lblModelParam4.Text = "角度范围"; this.dtxtModelParam4.Text = "10"; this.lblModelParam4.Visible = true; this.dtxtModelParam4.Visible = true; this.dtxtModelParam4.Enabled = true; lblModelParam4.MouseHover += (s, e) => ShowToolTip((Control)s, "搜索时的角度范围AngleExtent,'0'表示无角度搜索"); //, double ScaleRMin = 0.9, double ScaleRMax = 1.1, string ScaleRStep = "auto" this.lblModelParam5.Text = "纵向缩放最小值"; this.dtxtModelParam5.Text = "0.9"; this.lblModelParam5.Visible = true; this.dtxtModelParam5.Visible = true; this.dtxtModelParam5.Enabled = true; lblModelParam5.MouseHover += (s, e) => ShowToolTip((Control)s, "纵向缩放最小值ScaleRMin"); this.lblModelParam6.Text = "纵向缩放最大值"; this.dtxtModelParam6.Text = "1.1"; this.lblModelParam6.Visible = true; this.dtxtModelParam6.Visible = true; this.dtxtModelParam6.Enabled = true; lblModelParam6.MouseHover += (s, e) => ShowToolTip((Control)s, "纵向缩放最大值ScaleRMax"); //, double ScaleCMin = 1.1, double ScaleCMax = 0.9, string ScaleCStep = "auto" this.lblModelParam7.Text = "横向缩放最小值"; this.dtxtModelParam7.Text = "0.9"; this.lblModelParam7.Visible = true; this.dtxtModelParam7.Visible = true; this.dtxtModelParam7.Enabled = true; lblModelParam7.MouseHover += (s, e) => ShowToolTip((Control)s, "横向缩放最小值ScaleCMin"); this.lblModelParam8.Text = "横向缩放最大值"; this.dtxtModelParam8.Text = "1.1"; this.lblModelParam8.Visible = true; this.dtxtModelParam8.Visible = true; this.dtxtModelParam8.Enabled = true; lblModelParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "横向缩放最大值ScaleCMax"); //, string Optimization = "auto", string Metric = "ignore_local_polarity" this.lblModelParam9.Text = "优化"; this.dtxtModelParam9.Text = "none"; this.lblModelParam9.Visible = true; this.dtxtModelParam9.Visible = true; this.dtxtModelParam9.Enabled = false; lblModelParam9.MouseHover += (s, e) => ShowToolTip((Control)s, "影响形状模型创建时的速度和精度的优化选项Optimization"); this.lblModelParam10.Text = "极性"; this.dtxtModelParam10.Text = "ignore_local_polarity"; this.lblModelParam10.Visible = true; this.dtxtModelParam10.Visible = true; this.dtxtModelParam10.Enabled = false; lblModelParam10.MouseHover += (s, e) => ShowToolTip((Control)s, "极性信息的度量方法Metric"); //, string Contrast = "auto", int MinContrast = 10 this.lblModelParam11.Text = "对比度参数"; this.dtxtModelParam11.Text = "auto"; this.lblModelParam11.Visible = true; this.dtxtModelParam11.Visible = true; this.dtxtModelParam11.Enabled = false; lblModelParam11.MouseHover += (s, e) => ShowToolTip((Control)s, "创建模板时的对比度Contrast"); this.lblModelParam12.Text = "最小对比度参数"; this.dtxtModelParam12.Text = "10"; this.lblModelParam12.Visible = true; this.dtxtModelParam12.Visible = true; this.dtxtModelParam12.Enabled = true; lblModelParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "模型匹配过程中考虑的最小对比度MinContrast"); #endregion break; case ModelType.各向异形模板: default: //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI //, ScaleRMin, ScaleRMax //, ScaleCMin, ScaleCMax //, MinScore, NumMatches, MaxOverlap, SubPixel //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels) //, Greediness #region 输入参数 //, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI this.lblInputParam1.Text = "起始角度"; this.dtxtInputParam1.Text = Subject.Params.Inputs["AngleStart"]?.ToString(); this.lblInputParam1.Visible = true; this.dtxtInputParam1.Visible = true; this.dtxtInputParam1.Enabled = true; lblInputParam1.MouseHover += (s, e) => ShowToolTip((Control)s, "搜索时的起始角度AngleStart"); this.lblInputParam2.Text = "角度范围"; this.dtxtInputParam2.Text = Subject.Params.Inputs["AngleExtent"]?.ToString(); this.lblInputParam2.Visible = true; this.dtxtInputParam2.Visible = true; this.dtxtInputParam2.Enabled = true; lblInputParam2.MouseHover += (s, e) => ShowToolTip((Control)s, "搜索时的角度范围AngleExtent,'0'表示无角度搜索"); //, ScaleRMin, ScaleRMax this.lblInputParam3.Text = "纵向缩放最小值"; this.dtxtInputParam3.Text = Subject.Params.Inputs["ScaleRMin"]?.ToString(); this.lblInputParam3.Visible = true; this.dtxtInputParam3.Visible = true; this.dtxtInputParam3.Enabled = true; lblInputParam3.MouseHover += (s, e) => ShowToolTip((Control)s, "纵向缩放最小值ScaleRMin"); this.lblInputParam4.Text = "纵向缩放最大值"; this.dtxtInputParam4.Text = Subject.Params.Inputs["ScaleRMax"]?.ToString(); this.lblInputParam4.Visible = true; this.dtxtInputParam4.Visible = true; this.dtxtInputParam4.Enabled = true; lblInputParam4.MouseHover += (s, e) => ShowToolTip((Control)s, "纵向缩放最大值ScaleRMax"); //, ScaleCMin, ScaleCMax this.lblInputParam5.Text = "横向缩放最小值"; this.dtxtInputParam5.Text = Subject.Params.Inputs["ScaleCMin"]?.ToString(); this.lblInputParam5.Visible = true; this.dtxtInputParam5.Visible = true; this.dtxtInputParam5.Enabled = true; lblInputParam5.MouseHover += (s, e) => ShowToolTip((Control)s, "横向缩放最小值ScaleCMin"); this.lblInputParam6.Text = "横向缩放最大值"; this.dtxtInputParam6.Text = Subject.Params.Inputs["ScaleCMax"]?.ToString(); this.lblInputParam6.Visible = true; this.dtxtInputParam6.Visible = true; this.dtxtInputParam6.Enabled = true; lblInputParam6.MouseHover += (s, e) => ShowToolTip((Control)s, "横向缩放最大值ScaleCMax"); //, MinScore, NumMatches, MaxOverlap, ResultType this.lblInputParam7.Text = "最小分数"; this.dtxtInputParam7.Text = Subject.Params.Inputs["MinScore"]?.ToString(); this.lblInputParam7.Visible = true; this.dtxtInputParam7.Visible = true; this.dtxtInputParam7.Enabled = true; lblInputParam7.MouseHover += (s, e) => ShowToolTip((Control)s, "被找到的模板最小分数MinScore"); this.lblInputParam8.Text = "期望个数"; this.dtxtInputParam8.Text = Subject.Params.Inputs["NumMatches"]?.ToString(); this.lblInputParam8.Visible = true; this.dtxtInputParam8.Visible = true; this.dtxtInputParam8.Enabled = true; lblInputParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "要找到的模板最多的实例数NumMatches,'0'则找到所有可能的匹配"); this.lblInputParam9.Text = "最大重叠比例"; this.dtxtInputParam9.Text = Subject.Params.Inputs["MaxOverlap"]?.ToString(); this.lblInputParam9.Visible = true; this.dtxtInputParam9.Visible = true; this.dtxtInputParam9.Enabled = true; lblInputParam9.MouseHover += (s, e) => ShowToolTip((Control)s, "允许找到的模型实例的最大重叠比例MaxOverlap[较小的值会避免找到多个相似的匹配]"); this.lblInputParam10.Text = "计算精度"; this.dtxtInputParam10.Text = Subject.Params.Inputs["SubPixel"]?.ToString(); this.lblInputParam10.Visible = true; this.dtxtInputParam10.Visible = true; this.dtxtInputParam10.Enabled = false; lblInputParam10.MouseHover += (s, e) => ShowToolTip((Control)s, "计算精度的设置SubPixel['none'最大误差为半个像素]"); //, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels) //, Greediness, , new HTuple(), new HTuple() this.lblInputParam11.Text = "搜索时金字塔的层级"; this.dtxtInputParam11.Text = "0"; this.lblInputParam11.Visible = true; this.dtxtInputParam11.Visible = true; this.dtxtInputParam11.Enabled = false; lblInputParam11.MouseHover += (s, e) => ShowToolTip((Control)s, "搜索时金字塔的层级"); this.lblInputParam12.Text = "贪婪度"; this.dtxtInputParam12.Text = Subject.Params.Inputs["Greediness"]?.ToString(); this.lblInputParam12.Visible = true; this.dtxtInputParam12.Visible = true; this.dtxtInputParam12.Enabled = true; lblInputParam12.MouseHover += (s, e) => ShowToolTip((Control)s, "贪婪度,越高速度越快[一般都设为0.8,太大容易出现找不到的情况]"); this.lblInputParam13.Text = "最小数量"; this.dtxtInputParam13.Text = Subject.Params.Inputs["MinCount"]?.ToString(); this.lblInputParam13.Visible = true; this.dtxtInputParam13.Visible = true; this.dtxtInputParam13.Enabled = true; lblInputParam13.MouseHover += (s, e) => ShowToolTip((Control)s, "匹配结果要求的最小数量"); this.lblInputParam14.Text = "最大数量"; this.dtxtInputParam14.Text = Subject.Params.Inputs["MaxCount"]?.ToString(); this.lblInputParam14.Visible = true; this.dtxtInputParam14.Visible = true; this.dtxtInputParam14.Enabled = true; lblInputParam14.MouseHover += (s, e) => ShowToolTip((Control)s, "匹配结果要求的最大数量"); #endregion //UpdataInputs(); //string NumLevels = "auto" //, double AngleStart = -5, double AngleExtent = 10, string AngleStep = "auto" //, double ScaleRMin = 0.9, double ScaleRMax = 1.1, string ScaleRStep = "auto" //, double ScaleCMin = 1.1, double ScaleCMax = 0.9, string ScaleCStep = "auto" //, string Optimization = "auto", string Metric = "ignore_local_polarity" //, string Contrast = "auto", int MinContrast = 10 #region 模板参数 //NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels) this.lblModelParam1.Text = "金字塔的层级"; this.dtxtModelParam1.Text = "auto"; this.lblModelParam1.Visible = true; this.dtxtModelParam1.Visible = true; this.dtxtModelParam1.Enabled = false; lblModelParam1.MouseHover += (s, e) => ShowToolTip((Control)s, "搜索时金字塔的层级NumLevels,'0'表示不使用金字塔"); // , AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep) this.lblModelParam2.Text = "角度步长"; this.dtxtModelParam2.Text = "auto"; this.lblModelParam2.Visible = true; this.dtxtModelParam2.Visible = true; this.dtxtModelParam2.Enabled = false; lblModelParam2.MouseHover += (s, e) => ShowToolTip((Control)s, "角度范围内进行旋转的步长AngleStep,'auto'表示由系统自动选择合适的步长"); this.lblModelParam3.Text = "起始角度"; this.dtxtModelParam3.Text = "-5"; this.lblModelParam3.Visible = true; this.dtxtModelParam3.Visible = true; this.dtxtModelParam3.Enabled = true; lblModelParam3.MouseHover += (s, e) => ShowToolTip((Control)s, "搜索时的起始角度AngleStart"); this.lblModelParam4.Text = "角度范围"; this.dtxtModelParam4.Text = "10"; this.lblModelParam4.Visible = true; this.dtxtModelParam4.Visible = true; this.dtxtModelParam4.Enabled = true; lblModelParam4.MouseHover += (s, e) => ShowToolTip((Control)s, "搜索时的角度范围AngleExtent,'0'表示无角度搜索"); //, double ScaleRMin = 0.9, double ScaleRMax = 1.1, string ScaleRStep = "auto" this.lblModelParam5.Text = "纵向缩放最小值"; this.dtxtModelParam5.Text = "0.9"; this.lblModelParam5.Visible = true; this.dtxtModelParam5.Visible = true; this.dtxtModelParam5.Enabled = true; lblModelParam5.MouseHover += (s, e) => ShowToolTip((Control)s, "纵向缩放最小值ScaleRMin"); this.lblModelParam6.Text = "纵向缩放最大值"; this.dtxtModelParam6.Text = "1.1"; this.lblModelParam6.Visible = true; this.dtxtModelParam6.Visible = true; this.dtxtModelParam6.Enabled = true; lblModelParam6.MouseHover += (s, e) => ShowToolTip((Control)s, "纵向缩放最大值ScaleRMax"); //, double ScaleCMin = 1.1, double ScaleCMax = 0.9, string ScaleCStep = "auto" this.lblModelParam7.Text = "横向缩放最小值"; this.dtxtModelParam7.Text = "0.9"; this.lblModelParam7.Visible = true; this.dtxtModelParam7.Visible = true; this.dtxtModelParam7.Enabled = true; lblModelParam7.MouseHover += (s, e) => ShowToolTip((Control)s, "横向缩放最小值ScaleCMin"); this.lblModelParam8.Text = "横向缩放最大值"; this.dtxtModelParam8.Text = "1.1"; this.lblModelParam8.Visible = true; this.dtxtModelParam8.Visible = true; this.dtxtModelParam8.Enabled = true; lblModelParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "横向缩放最大值ScaleCMax"); //, string Optimization = "auto", string Metric = "ignore_local_polarity" this.lblModelParam9.Text = "优化"; this.dtxtModelParam9.Text = "auto"; this.lblModelParam9.Visible = true; this.dtxtModelParam9.Visible = true; this.dtxtModelParam9.Enabled = false; lblModelParam9.MouseHover += (s, e) => ShowToolTip((Control)s, "影响形状模型创建时的速度和精度的优化选项Optimization"); this.lblModelParam10.Text = "极性"; this.dtxtModelParam10.Text = "ignore_local_polarity"; this.lblModelParam10.Visible = true; this.dtxtModelParam10.Visible = true; this.dtxtModelParam10.Enabled = false; lblModelParam10.MouseHover += (s, e) => ShowToolTip((Control)s, "极性信息的度量方法Metric"); //, string Contrast = "auto", int MinContrast = 10 this.lblModelParam11.Text = "对比度参数"; this.dtxtModelParam11.Text = "auto"; this.lblModelParam11.Visible = true; this.dtxtModelParam11.Visible = true; this.dtxtModelParam11.Enabled = false; lblModelParam11.MouseHover += (s, e) => ShowToolTip((Control)s, "创建模板时的对比度Contrast"); this.lblModelParam12.Text = "最小对比度参数"; this.dtxtModelParam12.Text = "10"; this.lblModelParam12.Visible = true; this.dtxtModelParam12.Visible = true; this.dtxtModelParam12.Enabled = true; lblModelParam8.MouseHover += (s, e) => ShowToolTip((Control)s, "模型匹配过程中考虑的最小对比度MinContrast"); #endregion break; } } }); } private void btnCreateModel_Click(object sender, EventArgs e) { if (InputImage != null && InputImage is HImage) { imgTabControl.SelectedTab = tabPageModelImage; using (HImage hImage = (HImage)Subject.InputImage) { hImage.GetImageSize(out HTuple hv_imageWidth, out HTuple hv_imageHeight); createModelImageHSmartWindowControl.ShowHoImage(hImage); createModelImageHSmartWindowControl.bAollowDraw = true; createModelImageHSmartWindowControl.oRoi = new HRectangle2(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2 , 0, hv_imageWidth.TupleReal() / 4, hv_imageHeight.TupleReal() / 4); } } } private void btnSaveModel_Click(object sender, EventArgs e) { try { if (InputImage != null && InputImage is HObject) { double result = 0; if (Enum.TryParse(cmbModelType.Text, out ModelType modelType)) { string NumLevels = this.dtxtModelParam1.Text; string AngleStep = this.dtxtModelParam2.Text; double AngleStart = Convert.ToDouble(this.dtxtModelParam3.Text); double AngleExtent = Convert.ToDouble(this.dtxtModelParam4.Text); double ScaleRMin = Convert.ToDouble(this.dtxtModelParam5.Text); double ScaleRMax = Convert.ToDouble(this.dtxtModelParam6.Text); double ScaleCMin = Convert.ToDouble(this.dtxtModelParam7.Text); double ScaleCMax = Convert.ToDouble(this.dtxtModelParam8.Text); string Optimization = this.dtxtModelParam9.Text; string Metric = this.dtxtModelParam10.Text; string Contrast = this.dtxtModelParam11.Text; int MinContrast = Convert.ToInt16(this.dtxtModelParam12.Text); HRectangle2 ROI = (HRectangle2)createModelImageHSmartWindowControl.oRoi; HOperatorSet.GenRectangle2(out HObject hRectangle, ROI.Row, ROI.Column, ROI.Phi, ROI.SemiLength1, ROI.SemiLength2); HObject hoDomainImage = InputImage as HObject; HTuple hv_Channels = new HTuple(); //判断是否为灰度图 using (HDevDisposeHelper dh = new HDevDisposeHelper()) { try { HOperatorSet.CountChannels(hoDomainImage, out hv_Channels); if (hv_Channels.TupleInt() != 1) HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage); //转换后再次检查是否为灰度图 HOperatorSet.CountChannels(hoDomainImage, out hv_Channels); if (hv_Channels.TupleInt() != 1) HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage); } catch { } } HOperatorSet.ReduceDomain(hoDomainImage, hRectangle, out HObject hoImageReduced); HOperatorSet.CropDomain(hoImageReduced, out HObject hoModelImage); bool bCreateModel = false; switch (modelType) { case ModelType.局部变形模板: bCreateModel = ((HFindModelTool)Subject).CreateModel (hoModelImage, modelType, NumLevels , AngleStart, AngleExtent, AngleStep , ScaleRMin, ScaleRMax, "auto" , ScaleCMin, ScaleCMax, "auto" , Optimization, Metric, Contrast, MinContrast); break; case ModelType.各向异形模板: default: bCreateModel = ((HFindModelTool)Subject).CreateModel (hoModelImage, modelType, NumLevels , AngleStart, AngleExtent, AngleStep , ScaleRMin, ScaleRMax, "auto" , ScaleCMin, ScaleCMax, "auto" , Optimization, Metric, Contrast, MinContrast); break; } if (bCreateModel) { HObject ho_ModelContours = new HObject(); switch (((HFindModelTool)Subject).ModelID.Type) { case ModelType.局部变形模板: HOperatorSet.GetDeformableModelContours(out ho_ModelContours, ((HFindModelTool)Subject).ModelID.hvModel, 1); break; case ModelType.各向异形模板: default: HOperatorSet.GetShapeModelContours(out ho_ModelContours, ((HFindModelTool)Subject).ModelID.hvModel, 1); break; } HOperatorSet.GetImageSize(((HFindModelTool)Subject).ModelID.hoImage, out HTuple hv_Width, out HTuple hv_Height); HOperatorSet.VectorAngleToRigid(-hv_Height / 2, -hv_Width / 2, 0, 0, 0, 0, out HTuple hv_HomMat2D); HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_ModelContours, hv_HomMat2D); //建模成功导航到子页 parasTabControl.SelectedTab = tabPageRunParas; HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow); TAlgorithm.DispImage(((HFindModelTool)Subject).ModelID.hoImage, modelImageHWindowControl.HalconWindow); TAlgorithm.SetColor(modelImageHWindowControl.HalconWindow, "red"); TAlgorithm.DispObj(ho_ModelContours, modelImageHWindowControl.HalconWindow); TAlgorithm.DispMsg("创建模板成功", modelImageHWindowControl.HalconWindow, true); FirstModelImage = ((HFindModelTool)Subject).ModelID.hoImage.CopyObj(1, -1); } else { HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow); TAlgorithm.DispMsg("创建模板失败", modelImageHWindowControl.HalconWindow, false); } } } } catch { } } public void ShowModel(HModel ModelID) { try { if (ModelID != null && ModelID.hvModel != null && ModelID.hvModel.Length > 0) { HOperatorSet.GenEmptyObj(out HObject ho_ModelContours); switch (ModelID.Type) { case ModelType.局部变形模板: HOperatorSet.GetDeformableModelContours(out ho_ModelContours, ModelID.hvModel, 1); break; case ModelType.各向异形模板: default: HOperatorSet.GetShapeModelContours(out ho_ModelContours, ModelID.hvModel, 1); break; } HOperatorSet.GetImageSize(ModelID.hoImage, out HTuple hv_Width, out HTuple hv_Height); HOperatorSet.VectorAngleToRigid(-hv_Height / 2, -hv_Width / 2, 0, 0, 0, 0, out HTuple hv_HomMat2D); HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_ModelContours, hv_HomMat2D); HOperatorSet.ClearWindow(modelImageHWindowControl.HalconWindow); TAlgorithm.DispImage(ModelID.hoImage, modelImageHWindowControl.HalconWindow); TAlgorithm.SetColor(modelImageHWindowControl.HalconWindow, "red"); TAlgorithm.DispObj(ho_ModelContours, modelImageHWindowControl.HalconWindow); TAlgorithm.DispMsg("创建模板成功", modelImageHWindowControl.HalconWindow, true); } } catch { } } private void HFindModelToolEdit_SizeChanged(object sender, EventArgs e) => ShowModel(((HFindModelTool)Subject).ModelID); private void parasTabControl_SelectedIndexChanged(object sender, EventArgs e) { TabControl tabControl = sender as TabControl; if (tabControl != null) { if (tabControl.SelectedTab == tabPageRunParas) ShowModel(((HFindModelTool)Subject).ModelID); } } } }