using Bro.Common.Base;
|
using Bro.Common.Helper;
|
using Bro.Common.Model;
|
using Bro.Common.UI;
|
using HalconDotNet;
|
using System;
|
using System.Collections.Generic;
|
using System.Data;
|
using System.Drawing;
|
using System.IO;
|
using System.Linq;
|
using System.Threading;
|
using System.Threading.Tasks;
|
using System.Windows.Forms;
|
|
namespace Bro.Common.Calibration
|
{
|
public partial class CalibrationStatic9PointFrm : Form
|
{
|
/// <summary>
|
/// 标定点位信息
|
/// </summary>
|
public List<CalibrationPoint> CPoints
|
{
|
get
|
{
|
return canvas1.Elements.Where(p => p.IsEnabled && (p is CrossHair)).Select(p => ((CrossHair)p).CenterPoint).ToList();
|
}
|
}
|
|
/// <summary>
|
/// 运动点位信息
|
/// </summary>
|
public CustomizedPoint MovingPosition { get; set; } = new CustomizedPoint();
|
|
Canvas canvas1 = new Canvas();
|
|
PLCBase PLC = null;
|
CameraBase Camera = null;
|
Bitmap Image = null;
|
CalibrationStatic9PointConfig Config = null;
|
HDevEngineTool tool = null;
|
|
public CalibrationStatic9PointFrm()
|
{
|
InitializeComponent();
|
|
canvas1 = new Canvas();
|
canvas1.Dock = DockStyle.Fill;
|
plCanvas.Controls.Add(canvas1);
|
}
|
|
public CalibrationStatic9PointFrm(string display, CameraBase camera, PLCBase plc, Bitmap image, CalibrationStatic9PointConfig config)
|
{
|
InitializeComponent();
|
|
if (!string.IsNullOrWhiteSpace(display))
|
{
|
this.Text = display;
|
}
|
|
Camera = camera;
|
PLC = plc;
|
Image = image;
|
propCalibrationConfig.SelectedObject = Config = config;
|
|
Camera.OnImageUpdated -= Camera_UpdateShowImage;
|
Camera.OnImageUpdated += Camera_UpdateShowImage;
|
|
canvas1.LoadImage(Image);
|
|
LoadHalconTool();
|
}
|
|
AutoResetEvent _imgShowedHandle = new AutoResetEvent(true);
|
private void Camera_UpdateShowImage(CameraBase camera, Bitmap image)
|
{
|
if (this.InvokeRequired)
|
{
|
this.Invoke(new Action(() => LoadImage(image)));
|
}
|
else
|
{
|
LoadImage(image);
|
}
|
}
|
|
private void LoadImage(Bitmap image)
|
{
|
canvas1.LoadImage(image);
|
_imgShowedHandle.Set();
|
}
|
|
private void PointTest()
|
{
|
canvas1.Elements.Clear();
|
|
for (int i = 0; i < 3; i++)
|
{
|
for (int j = 0; j < 3; j++)
|
{
|
PointF p = new PointF();
|
p.X = 300 + i * 100;
|
p.Y = 500 + j * 150;
|
|
CrossHair ch = new CrossHair(new CalibrationPoint(p));
|
|
ch.Index = i * 3 + j + 1;
|
ch.Name = p.X.ToString() + "--" + p.Y.ToString();
|
|
canvas1.Elements.Add(ch);
|
}
|
}
|
}
|
|
private void LoadHalconTool()
|
{
|
if (string.IsNullOrWhiteSpace(Config.CameraOpConfig.AlgorithemPath))
|
{
|
return;
|
}
|
|
txtAlgorithemPath.Text = Config.CameraOpConfig.AlgorithemPath;
|
|
string directoryPath = Path.GetDirectoryName(Config.CameraOpConfig.AlgorithemPath);
|
string fileName = Path.GetFileNameWithoutExtension(Config.CameraOpConfig.AlgorithemPath);
|
|
tool = new HDevEngineTool(directoryPath);
|
tool.LoadProcedure(fileName);
|
Thread.Sleep(1000);
|
}
|
|
private void btnCancel_Click(object sender, EventArgs e)
|
{
|
this.DialogResult = DialogResult.Cancel;
|
}
|
|
private void btnDone_Click(object sender, EventArgs e)
|
{
|
if (CPoints.Count < 9)
|
{
|
if (MessageBox.Show("一般需设置至少9个标定点的信息,是否确认完成", "完成确认", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
|
return;
|
}
|
|
if (CPoints.Count(p => p.X == 0 && p.Y == 0) > 1)
|
{
|
if (MessageBox.Show("标定点的XY信息未设置完成,是否确认完成", "完成确认", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
|
return;
|
}
|
|
GetCurrentPosition();
|
|
if (Config.IsEnableROIFilter)
|
{
|
Config.ROIList.Clear();
|
|
CPoints.ForEach(u =>
|
{
|
ROI_Circle circle = new ROI_Circle();
|
if (u.IsBasePoint)
|
{
|
circle.ROI_Index = "1";
|
}
|
|
circle.Center = new CustomizedPoint(u.U, u.V);
|
circle.Radius = Config.ROI_Radius;
|
|
Config.ROIList.Add(circle);
|
});
|
}
|
|
this.DialogResult = DialogResult.OK;
|
}
|
|
public virtual void GetCurrentPosition()
|
{
|
//if (Config.PLCSetting.IsRealTimeDataFromPLC)
|
//{
|
// int x = PLC.Read(Config.PLCSetting.XAddress, 2).ParseUnsignShortListToInt()[0];
|
// int y = PLC.Read(Config.PLCSetting.YAddress, 2).ParseUnsignShortListToInt()[0];
|
|
// MovingPosition = new CustomizedPoint(x, y);
|
|
// Config.PLCSetting.LocationX = x;
|
// Config.PLCSetting.LocationY = y;
|
//}
|
//else
|
//{
|
// MovingPosition = new CustomizedPoint(Config.PLCSetting.LocationX, Config.PLCSetting.LocationY);
|
//}
|
}
|
|
private void btnCalibrate_Click(object sender, EventArgs e)
|
{
|
DoCalibration();
|
}
|
|
private void DoCalibration()
|
{
|
canvas1.Elements.Clear();
|
|
if (Config.IsEnableROIFilter)
|
{
|
Config.ROIList.ForEach(r =>
|
{
|
canvas1.Elements.Add(r);
|
});
|
}
|
|
try
|
{
|
HTuple outputX = new HTuple();
|
HTuple outputY = new HTuple();
|
|
using (HObject hImage = canvas1.MAP.ConvertBitmapToHObject())
|
{
|
tool.InputImageDic.Clear();
|
tool.InputImageDic["INPUT_Image"] = hImage;
|
tool.RunProcedure();
|
|
if (!tool.IsSuccessful)
|
throw new ProcessException($"{Config.CameraOpConfig.AlgorithemPath}算法运行失败");
|
|
outputX = tool.GetResultTuple("OUTPUT_X");
|
outputY = tool.GetResultTuple("OUTPUT_Y");
|
}
|
|
List<CrossHair> chList = new List<CrossHair>();
|
for (int i = 0; i < outputX.DArr.Length; i++)
|
{
|
CalibrationPoint point = new CalibrationPoint(new PointF((float)outputX.DArr[i], (float)outputY.DArr[i]));
|
|
if (Config.IsEnableROIFilter && Config.ROIList.Count > 0)
|
{
|
var roi = Config.ROIList.FirstOrDefault(r => r.IsMouseInSide(new Point((int)point.U, (int)point.V)));
|
if (roi != null)
|
{
|
CrossHair ch = new CrossHair(point);
|
ch.IsShowRemark = Config.IsShowRemark;
|
ch.Index = i + 1;
|
ch.Name = point.U.ToString("f3") + "--" + point.V.ToString("f3");
|
|
if (roi.ROI_Index == "1")
|
{
|
ch.CenterPoint.IsBasePoint = true;
|
}
|
|
chList.Add(ch);
|
}
|
}
|
else
|
{
|
CrossHair ch = new CrossHair(point);
|
ch.IsShowRemark = Config.IsShowRemark;
|
ch.Index = i + 1;
|
ch.Name = point.U.ToString("f3") + "--" + point.V.ToString("f3");
|
chList.Add(ch);
|
}
|
}
|
|
Config.ROIList.ForEach(r =>
|
{
|
canvas1.Elements.Add(r);
|
});
|
}
|
catch (Exception ex)
|
{
|
MessageBox.Show(ex.GetExceptionMessage());
|
}
|
}
|
|
private void btnQuickSetXY_Click(object sender, EventArgs e)
|
{
|
if (MessageBox.Show("快捷设置XY坐标仅适用于标定坐标系和相机坐标系基本平行情况下", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk) != DialogResult.OK)
|
{
|
return;
|
}
|
|
if (CPoints.Count(p => p.IsBasePoint) > 1)
|
{
|
MessageBox.Show("基准点只能选择一个");
|
return;
|
}
|
|
var basePoint = CPoints.FirstOrDefault(p => p.IsBasePoint);
|
if (basePoint == null)
|
{
|
MessageBox.Show("请选择一个基准点");
|
return;
|
}
|
|
List<float> uList = CPoints.Select(p => Math.Abs(p.U - basePoint.U)).OrderBy(u => u).ToList();
|
List<float> vList = CPoints.Select(p => Math.Abs(p.V - basePoint.V)).OrderBy(u => u).ToList();
|
|
float intervalU = uList.FirstOrDefault(u => u > Config.IgnorePixel);
|
float intervalV = vList.FirstOrDefault(u => u > Config.IgnorePixel);
|
|
CPoints.ForEach(p =>
|
{
|
if (!p.IsBasePoint)
|
{
|
if (Config.IsInvert)
|
{
|
p.X = (int)(Math.Round((p.V - basePoint.V) / intervalV)) * Config.IntervalX + basePoint.X;
|
p.Y = (int)(Math.Round((p.U - basePoint.U) / intervalU)) * Config.IntervalY + basePoint.Y;
|
}
|
else
|
{
|
p.X = (int)(Math.Round((p.U - basePoint.U) / intervalU)) * Config.IntervalX + basePoint.X;
|
p.Y = (int)(Math.Round((p.V - basePoint.V) / intervalV)) * Config.IntervalY + basePoint.Y;
|
}
|
}
|
else
|
{
|
if (Config.IsEnableROIFilter)
|
{
|
var roi1st = Config.ROIList.FirstOrDefault(u => u.IsMouseInSide(new Point((int)p.U, (int)p.V)));
|
|
if (roi1st != null)
|
{
|
roi1st.ROI_Index = "1";
|
}
|
}
|
}
|
});
|
|
MessageBox.Show("快捷配置完成!");
|
}
|
|
private void btnReSnap_Click(object sender, EventArgs e)
|
{
|
Camera.Snapshot(Config.CameraOpConfig, out HObject hImage);
|
hImage.Dispose();
|
}
|
|
private void chkContinueMode_CheckedChanged(object sender, EventArgs e)
|
{
|
if (chkContinueMode.Checked)
|
{
|
Task.Run(() =>
|
{
|
while (chkContinueMode.Checked)
|
{
|
Camera.Snapshot(Config.CameraOpConfig, out HObject hImage);
|
hImage.Dispose();
|
|
_imgShowedHandle.WaitOne(3000);
|
}
|
});
|
}
|
}
|
|
private void btnTest_Click(object sender, EventArgs e)
|
{
|
PointTest();
|
}
|
|
private void btnReadLocation_Click(object sender, EventArgs e)
|
{
|
//int x = PLC.Read(Config.PLCSetting.XAddress, 2).ParseUnsignShortListToInt()[0];
|
//int y = PLC.Read(Config.PLCSetting.YAddress, 2).ParseUnsignShortListToInt()[0];
|
|
//string msg = string.Format("X:{0};Y:{1}", x, y);
|
//if (MessageBox.Show(msg + "\r\n是否保存到配置?", "坐标获取", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
|
//{
|
// Config.PLCSetting.LocationX = x;
|
// Config.PLCSetting.LocationY = y;
|
//}
|
|
GetCurrentPosition();
|
}
|
|
private void btnReloadAlgorithem_Click(object sender, EventArgs e)
|
{
|
LoadHalconTool();
|
|
MessageBox.Show("算法重新载入完成");
|
}
|
|
private void btnClearROI_Click(object sender, EventArgs e)
|
{
|
Config.ROIList.Clear();
|
|
DoCalibration();
|
}
|
|
private void CalibrationProcessFrm_FormClosing(object sender, FormClosingEventArgs e)
|
{
|
chkContinueMode.Checked = false;
|
}
|
}
|
}
|