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 { }
}
}
}