using HalconDotNet;
using System.Data.Common;
using LB_VisionProcesses.Alogrithms;
using System.Windows.Forms;
using Newtonsoft.Json;
using static LB_VisionProcesses.Alogrithms.Halcon.BlobAfterProcess;
using LB_VisionControl;
namespace LB_VisionProcesses.Alogrithms.Halcon
{
public partial class HBlobToolEdit : TAlgorithmEdit
{
public HBlobToolEdit(HBlobTool subject = null)
{
if (subject != null && subject is HBlobTool)
Subject = subject;
else
Subject = new HBlobTool();
this.Dock = DockStyle.Fill;
InitializeComponent();
// 遍历可以选择的类型枚举
foreach (var value in Enum.GetValues(typeof(ProcessType)))
cmbProcessType.Items.Add(value.ToString());
cmbProcessType.Text = ProcessType.Close.ToString();
// 遍历可以选择的类型枚举
foreach (var value in Enum.GetValues(typeof(ShapeType)))
cmbShapeType.Items.Add(value.ToString());
cmbShapeType.Text = ShapeType.Rectangle.ToString();
cmbShapeType.SelectedIndexChanged += (sender, e) =>
{
if (cmbShapeType.SelectedItem.ToString() == ShapeType.Circle.ToString())
txtAfterProcessHeight.Enabled = false;
else
txtAfterProcessHeight.Enabled = true;
};
btnAdd.Click += (sender, e) =>
{
if (txtAfterProcessWidth.Value > 0 && txtAfterProcessHeight.Value > 0
&& Enum.TryParse(cmbProcessType.Text, out ProcessType type)
&& Enum.TryParse(cmbShapeType.Text, out ShapeType shape))
{
if (shape == ShapeType.Circle)
ckbListAfter.Items.Add($"{type}_{shape}_{txtAfterProcessWidth.Value}*{txtAfterProcessWidth.Value}", true);
else
ckbListAfter.Items.Add($"{type}_{shape}_{txtAfterProcessWidth.Value}*{txtAfterProcessHeight.Value}", true);
}
};
btnDel.Click += (sender, e) =>
{
ckbListAfter.Items.RemoveAt(ckbListAfter.Items.Count - 1);
};
lblTips.Text = "闭运算(先膨胀再腐蚀) Close 填充孔洞、填补不规则缺陷" +
"\n开运算(先腐蚀再膨胀) Open 去除噪声、去除细小杂质、优化形状" +
"\n膨胀 Dilation 扩大区域、裂缝填补、目标区域扩展" +
"\n腐蚀 Erosion 消除噪声、目标分离、形态边界缩小";
}
///
/// 控件加载事件
///
///
///
private void HBlobToolEdit_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());
//遍历可以选择的Fixture枚举
cmbFixture.Items.Add("");
foreach (string value in IProcess.dicFixtures.Keys)
cmbFixture.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;
Subject.Params.Inputs["MinThreshold"] = int.TryParse(dtxtMinThreshold.Text, out iResult) ? iResult : Subject.Params.Inputs["MinThreshold"];
Subject.Params.Inputs["MaxThreshold"] = int.TryParse(dtxtMaxThreshold.Text, out iResult) ? iResult : Subject.Params.Inputs["MaxThreshold"];
Subject.Params.Inputs["MinArea"] = double.TryParse(dtxtMinArea.Text, out dResult) ? dResult : Subject.Params.Inputs["MinArea"];
Subject.Params.Inputs["MaxArea"] = double.TryParse(dtxtMaxArea.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxArea"];
Subject.Params.Inputs["MinRow"] = double.TryParse(dtxtMinRow.Text, out dResult) ? dResult : Subject.Params.Inputs["MinRow"];
Subject.Params.Inputs["MaxRow"] = double.TryParse(dtxtMaxRow.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxRow"];
Subject.Params.Inputs["MinColumn"] = double.TryParse(dtxtMinColumn.Text, out dResult) ? dResult : Subject.Params.Inputs["MinColumn"];
Subject.Params.Inputs["MaxColumn"] = double.TryParse(dtxtMaxColumn.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxColumn"];
Subject.Params.Inputs["MinCircularity"] = double.TryParse(dtxtMinCircularity.Text, out dResult) ? dResult : Subject.Params.Inputs["MinCircularity"];
Subject.Params.Inputs["MaxCircularity"] = double.TryParse(dtxtMaxCircularity.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxCircularity"];
Subject.Params.Inputs["MinRectangularity"] = double.TryParse(dtxtMinRectangularity.Text, out dResult) ? dResult : Subject.Params.Inputs["MinRectangularity"];
Subject.Params.Inputs["MaxRectangularity"] = double.TryParse(dtxtMaxRectangularity.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxRectangularity"];
Subject.Params.Inputs["MinCount"] = int.TryParse(dtxtMinCount.Text, out iResult) ? iResult : Subject.Params.Inputs["MinCount"];
Subject.Params.Inputs["MaxCount"] = int.TryParse(dtxtMaxCount.Text, out iResult) ? iResult : Subject.Params.Inputs["MaxCount"];
Subject.Params.Inputs["MinContlength"] = double.TryParse(dtxtMinContlength.Text, out dResult) ? dResult : Subject.Params.Inputs["MinContlength"];
Subject.Params.Inputs["MaxContlength"] = double.TryParse(dtxtMaxContlength.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxContlength"];
Subject.Params.Inputs["MinAnisometry"] = double.TryParse(dtxtMinAnisometry.Text, out dResult) ? dResult : Subject.Params.Inputs["MinAnisometry"];
Subject.Params.Inputs["MaxAnisometry"] = double.TryParse(dtxtMaxAnisometry.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxAnisometry"];
Subject.Params.Inputs["MinDistMean"] = double.TryParse(dtxtMinDistMean.Text, out dResult) ? dResult : Subject.Params.Inputs["MinDistMean"];
Subject.Params.Inputs["MaxDistMean"] = double.TryParse(dtxtMaxDistMean.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxDistMean"];
Subject.Params.Inputs["MinDistDeviation"] = double.TryParse(dtxtMinDistDeviation.Text, out dResult) ? dResult : Subject.Params.Inputs["MinDistDeviation"];
Subject.Params.Inputs["MaxDistDeviation"] = double.TryParse(dtxtMaxDistDeviation.Text, out dResult) ? dResult : Subject.Params.Inputs["MaxDistDeviation"];
try
{
List BlobAfterProcesses = new List();
for (int i = 0; i < ckbListAfter.Items.Count; i++)
{
string[] arrStr = ckbListAfter.Items[i].ToString().Split('_');
if (arrStr.Length >= 3
&& Enum.TryParse(arrStr[0], out ProcessType type)
&& Enum.TryParse(arrStr[1], out ShapeType shape))
{
string[] arrSize = arrStr[2].ToString().Split('*');
BlobAfterProcesses.Add(new BlobAfterProcess(
type, shape, Convert.ToInt32(arrSize[0]), Convert.ToInt32(arrSize[1]), ckbListAfter.GetItemChecked(i)));
}
}
Subject.Params.Inputs["BlobAfterProcesses"] = JsonConvert.SerializeObject(BlobAfterProcesses);
}
catch { }
if (cmbFixture.Text == "")
Subject.Params.Fixture = new Fixture();
else if (IProcess.dicFixtures.ContainsKey(cmbFixture.Text))
Subject.Params.Fixture = IProcess.dicFixtures[cmbFixture.Text];
base.UpdataInputs();
}
///
/// 加载运行参数
///
public override void LoadParas()
{
this.BeginInvoke(new Action(() =>
{
dtxtMinThreshold.Text = Subject.Params.Inputs["MinThreshold"]?.ToString();
dtxtMaxThreshold.Text = Subject.Params.Inputs["MaxThreshold"]?.ToString();
dtxtMinArea.Text = Subject.Params.Inputs["MinArea"]?.ToString();
dtxtMaxArea.Text = Subject.Params.Inputs["MaxArea"]?.ToString();
dtxtMinRow.Text = Subject.Params.Inputs["MinRow"]?.ToString();
dtxtMaxRow.Text = Subject.Params.Inputs["MaxRow"]?.ToString();
dtxtMinColumn.Text = Subject.Params.Inputs["MinColumn"]?.ToString();
dtxtMaxColumn.Text = Subject.Params.Inputs["MaxColumn"]?.ToString();
dtxtMinCircularity.Text = Subject.Params.Inputs["MinCircularity"]?.ToString();
dtxtMaxCircularity.Text = Subject.Params.Inputs["MaxCircularity"]?.ToString();
dtxtMinRectangularity.Text = Subject.Params.Inputs["MinRectangularity"]?.ToString();
dtxtMaxRectangularity.Text = Subject.Params.Inputs["MaxRectangularity"]?.ToString();
dtxtMinContlength.Text = Subject.Params.Inputs["MinContlength"]?.ToString();
dtxtMaxContlength.Text = Subject.Params.Inputs["MaxContlength"]?.ToString();
dtxtMinAnisometry.Text = Subject.Params.Inputs["MinAnisometry"]?.ToString();
dtxtMaxAnisometry.Text = Subject.Params.Inputs["MaxAnisometry"]?.ToString();
dtxtMinDistMean.Text = Subject.Params.Inputs["MinDistMean"]?.ToString();
dtxtMaxDistMean.Text = Subject.Params.Inputs["MaxDistMean"]?.ToString();
dtxtMinDistDeviation.Text = Subject.Params.Inputs["MinDistDeviation"]?.ToString();
dtxtMaxDistDeviation.Text = Subject.Params.Inputs["MaxDistDeviation"]?.ToString();
dtxtMinCount.Text = Subject.Params.Inputs["MinCount"]?.ToString();
dtxtMaxCount.Text = Subject.Params.Inputs["MaxCount"]?.ToString();
try
{
List BlobAfterProcesses = JsonConvert.DeserializeObject>(Subject.Params.Inputs["BlobAfterProcesses"].ToString());
foreach (var BlobAfterProcess in BlobAfterProcesses)
ckbListAfter.Items.Add($"{BlobAfterProcess.Type}_{BlobAfterProcess.Shape}_{BlobAfterProcess.Width}*{BlobAfterProcess.Height}", BlobAfterProcess.Enable);
}
catch { }
if (Subject.InputImage != null && Subject.InputImage is HImage)
inputImageHSmartWindowControl.ShowHoImage((HImage)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 = "";
base.LoadParas();
}));
}
///
/// 更新输出结果
///
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"]);
dtxtWidth.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Width"]);
dtxtHeight.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Height"]);
dtxtArea.Text = ProcessParams.ConvertToString(Subject.Params.Outputs["Area"]);
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) { base.btnSaveParas_Click(sender, e); }
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.Ellipse:
// inputImageHSmartWindowControl.oRoi
// = new HEllipse(hv_imageWidth.TupleReal() / 2, hv_imageHeight.TupleReal() / 2,0, hv_imageHeight.TupleReal() / 4, 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 { }
}
}
}