Files
VisionEdit/EyeHandCalibTool/EyeHandCalib.cs
liu.wenjie 7ca84a8720 1、添加手眼标定工具,可选择4点或者9点标定,输出标定矩阵
2、修正Halcon引擎运行工具
3、添加相机SDK工具,但需完善
4、HalconTool取图工具增加选择文件夹功能
5、实现Job窗体可添加多个流程
2022-04-21 14:10:04 +08:00

339 lines
11 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CommonMethods;
using ToolBase;
using ViewROI;
using HalconDotNet;
using System.Data;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
using Logger;
using static DataStruct.DataStructClass;
namespace EyeHandCalibTool
{
[Serializable]
public class EyeHandCalib : IToolBase
{
/// <summary>
/// 仿射变换矩阵
/// </summary>
public HTuple homMat2D = new HTuple();
/// <summary>
/// 标定类型 四点标定|九点标定
/// </summary>
public CalibType calibType = CalibType.Four_Point;
/// <summary>
/// 标定表源数据
/// </summary>
public DataTable CalibSourceDataTable { get; set; } = null;
/// <summary>
/// 输入点信息
/// </summary>
public Point inputPoint = new Point();
/// <summary>
/// 输出点信息
/// </summary>
public Point outputPoint = new Point();
/// <summary>
/// 矩阵名称
/// </summary>
public string homMat2DName { get; set; } = Guid.NewGuid().ToString();
/// <summary>
/// X平移
/// </summary>
private HTuple _translateX = 0;
internal HTuple TranslateX
{
get
{
_translateX = Math.Round((double)_translateX, 2);
return _translateX;
}
set
{
value = Math.Round((double)value, 2);
_translateX = value;
}
}
/// <summary>
/// Y平移
/// </summary>
private HTuple _translateY = 0;
internal HTuple TranslateY
{
get
{
_translateY = Math.Round((double)_translateY, 2);
return _translateY;
}
set
{
value = Math.Round((double)value, 2);
_translateY = value;
}
}
/// <summary>
/// X缩放
/// </summary>
private HTuple _scanX = 1;
internal HTuple ScanX
{
get
{
_scanX = Math.Round((double)_scanX, 2);
return _scanX;
}
set
{
value = Math.Round((double)value, 2);
_scanX = value;
}
}
/// <summary>
/// Y缩放
/// </summary>
private HTuple _scanY = 1;
internal HTuple ScanY
{
get
{
_scanY = Math.Round((double)_scanY, 2);
return _scanY;
}
set
{
value = Math.Round((double)value, 2);
_scanY = value;
}
}
/// <summary>
/// 角度旋转
/// </summary>
private HTuple _rotation = 0;
internal HTuple Rotation
{
get
{
_rotation = Math.Round((double)_rotation, 2);
return _rotation;
}
set
{
value = Math.Round((double)value, 2);
_rotation = value;
}
}
/// <summary>
/// 轴斜切
/// </summary>
private HTuple _theta = 0;
internal HTuple Theta
{
get
{
_theta = Math.Round((double)_theta, 2);
return _theta;
}
set
{
value = Math.Round((double)value, 2);
_theta = value;
}
}
public override void DispImage()
{
// throw new NotImplementedException();
}
public override void DispMainWindow(HWindowTool_Smart window)
{
// throw new NotImplementedException();
}
public override void Run(SoftwareRunState softwareRunState)
{
try
{
// 若首次加载且本地存在矩阵,优先读取本地
if (File.Exists(homMat2DName) && homMat2D.Length == 0)
{
HOperatorSet.ReadTuple(homMat2DName, out homMat2D);
}
// 再次判断
if (homMat2D.Length == 0)
{
runMessage = $"{FormEyeHandCalib.Instance.myToolInfo.FormToolName}未生成仿射矩阵工具,需要先标定标准!";
toolRunStatu = ToolRunStatu.Tool_Run_Error;
FormEyeHandCalib.Instance.SetToolStatus(runMessage, toolRunStatu);
}
else
{
HTuple tupOutX, tupOutY;
HOperatorSet.AffineTransPoint2d(homMat2D, inputPoint.Row, inputPoint.Col, out tupOutX, out tupOutY);
outputPoint.Row = tupOutX;
outputPoint.Col = tupOutY;
runMessage = $"{FormEyeHandCalib.Instance.myToolInfo.FormToolName}运行成功";
toolRunStatu = ToolRunStatu.Succeed;
FormEyeHandCalib.Instance.SetToolStatus(runMessage, toolRunStatu);
}
}
catch (Exception ex)
{
runMessage = $"{FormEyeHandCalib.Instance.myToolInfo.FormToolName}运行出现异常";
toolRunStatu = ToolRunStatu.Tool_Run_Error;
}
}
/// <summary>
/// 初始化标定数据源
/// </summary>
public void InitDataTable()
{
CalibSourceDataTable = new DataTable();
//初始化DataTable并将datatable绑定到DataGridView的数据源
DataColumn c1 = new DataColumn("像素X", typeof(double));
DataColumn c2 = new DataColumn("像素Y", typeof(double));
DataColumn c3 = new DataColumn("机械X", typeof(double));
DataColumn c4 = new DataColumn("机械Y", typeof(double));
CalibSourceDataTable.Columns.Add(c1);
CalibSourceDataTable.Columns.Add(c2);
CalibSourceDataTable.Columns.Add(c3);
CalibSourceDataTable.Columns.Add(c4);
CalibSourceDataTable.Rows.Clear();
for (int i = 0; i < (int)calibType; i++)
{
DataRow dr = CalibSourceDataTable.NewRow();
dr[0] = 0;
dr[1] = 50;
dr[2] = 0;
dr[3] = 50;
CalibSourceDataTable.Rows.Add(dr);
}
}
/// <summary>
/// 导入标定数据
/// </summary>
public void ReadCalibData()
{
OpenFileDialog digOpenFile = new OpenFileDialog();
digOpenFile.FileName = string.Empty;
digOpenFile.Title = "请选择表格文件";
digOpenFile.Filter = "CSV文件(*.csv)|*.csv";
if (digOpenFile.ShowDialog() == DialogResult.OK)
{
string[] lines = File.ReadAllLines(digOpenFile.FileName, Encoding.Default);
for (int i = 0; i < lines.Length; i++)
{
string[] data = Regex.Split(lines[i], ",");
for (int j = 0; j < data.Length; j++)
{
CalibSourceDataTable.Rows[i][j] = data[j];
if (j == 3) //只导入前四列
break;
}
if (i == (int)calibType) //若标定类型为四点标定,则导入前四行,若为九点标定,则导入前九行
break;
}
}
}
/// <summary>
/// 导出标定数据
/// </summary>
public void ExportCalibData()
{
try
{
SaveFileDialog dig_saveImage = new SaveFileDialog();
dig_saveImage.FileName = "CalibData " + DateTime.Now.ToString("yyyy_MM_dd");
dig_saveImage.Title = "请选择导出路径";
dig_saveImage.Filter = "CSV文件(*.csv)|*.csv";
if (dig_saveImage.ShowDialog() == DialogResult.OK)
{
File.Create(dig_saveImage.FileName).Close();
string data = string.Empty;
for (int i = 0; i <CalibSourceDataTable.Rows.Count; i++)
{
for (int j = 0; j < 4; j++)
{
data += CalibSourceDataTable.Rows[i][j];
if (j < 3)
data += ",";
}
data += Environment.NewLine;
}
File.AppendAllText(dig_saveImage.FileName, data, Encoding.Default);
}
}
catch (Exception ex)
{
Logger.LoggerClass.WriteLog("导出标定数据时出错", ex);
}
}
public bool ManulCalib()
{
try
{
List<double> pixelRowList = new List<double>();
List<double> pixelColList = new List<double>();
List<double> MechanicalXList = new List<double>();
List<double> MechanicalYList = new List<double>();
try
{
for (int i = 0; i < CalibSourceDataTable.Rows.Count; i++)
{
pixelRowList.Add(Convert.ToDouble(CalibSourceDataTable.Rows[i][0]));
pixelColList.Add(Convert.ToDouble(CalibSourceDataTable.Rows[i][1]));
MechanicalXList.Add(Convert.ToDouble(CalibSourceDataTable.Rows[i][2]));
MechanicalYList.Add(Convert.ToDouble(CalibSourceDataTable.Rows[i][3]));
}
}
catch(Exception ex)
{
LoggerClass.WriteLog("标定失败标定数据异常错误代码12901", ex);
return false;
}
try
{
HTuple pixelRow = new HTuple(pixelRowList.ToArray());
HTuple pixelCol = new HTuple(pixelColList.ToArray());
HTuple mechanicalX = new HTuple(MechanicalXList.ToArray());
HTuple mechanicalY = new HTuple(MechanicalYList.ToArray());
HOperatorSet.VectorToHomMat2d(pixelRow, pixelCol, mechanicalX, mechanicalY, out homMat2D);
}
catch(HalconException ex)
{
LoggerClass.WriteLog("标定失败标定数据异常无法确定仿射变换关系错误代码12902", ex);
return false;
}
HOperatorSet.HomMat2dToAffinePar(homMat2D, out _scanX, out _scanY, out _rotation, out _theta, out _translateX, out _translateY);
return true;
}
catch (Exception ex)
{
LoggerClass.WriteLog("手动标定出现异常", ex);
return false;
}
}
}
/// <summary>
/// 标定类型 四点|九点
/// </summary>
[Serializable]
public enum CalibType
{
Four_Point = 4,
Nine_Point = 9,
}
}