EyeHandCalib.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using CommonMethods;
  7. using ToolBase;
  8. using ViewROI;
  9. using HalconDotNet;
  10. using System.Data;
  11. using System.Windows.Forms;
  12. using System.IO;
  13. using System.Text.RegularExpressions;
  14. using Logger;
  15. using static DataStruct.DataStructClass;
  16. namespace EyeHandCalibTool
  17. {
  18. [Serializable]
  19. public class EyeHandCalib : IToolBase
  20. {
  21. /// <summary>
  22. /// 仿射变换矩阵
  23. /// </summary>
  24. public HTuple homMat2D = new HTuple();
  25. /// <summary>
  26. /// 标定类型 四点标定|九点标定
  27. /// </summary>
  28. public CalibType calibType = CalibType.Four_Point;
  29. /// <summary>
  30. /// 标定表源数据
  31. /// </summary>
  32. public DataTable CalibSourceDataTable { get; set; } = null;
  33. /// <summary>
  34. /// 输入点信息
  35. /// </summary>
  36. public Point inputPoint = new Point();
  37. /// <summary>
  38. /// 输出点信息
  39. /// </summary>
  40. public Point outputPoint = new Point();
  41. /// <summary>
  42. /// 矩阵名称
  43. /// </summary>
  44. public string homMat2DName { get; set; } = Guid.NewGuid().ToString();
  45. /// <summary>
  46. /// X平移
  47. /// </summary>
  48. private HTuple _translateX = 0;
  49. internal HTuple TranslateX
  50. {
  51. get
  52. {
  53. _translateX = Math.Round((double)_translateX, 2);
  54. return _translateX;
  55. }
  56. set
  57. {
  58. value = Math.Round((double)value, 2);
  59. _translateX = value;
  60. }
  61. }
  62. /// <summary>
  63. /// Y平移
  64. /// </summary>
  65. private HTuple _translateY = 0;
  66. internal HTuple TranslateY
  67. {
  68. get
  69. {
  70. _translateY = Math.Round((double)_translateY, 2);
  71. return _translateY;
  72. }
  73. set
  74. {
  75. value = Math.Round((double)value, 2);
  76. _translateY = value;
  77. }
  78. }
  79. /// <summary>
  80. /// X缩放
  81. /// </summary>
  82. private HTuple _scanX = 1;
  83. internal HTuple ScanX
  84. {
  85. get
  86. {
  87. _scanX = Math.Round((double)_scanX, 2);
  88. return _scanX;
  89. }
  90. set
  91. {
  92. value = Math.Round((double)value, 2);
  93. _scanX = value;
  94. }
  95. }
  96. /// <summary>
  97. /// Y缩放
  98. /// </summary>
  99. private HTuple _scanY = 1;
  100. internal HTuple ScanY
  101. {
  102. get
  103. {
  104. _scanY = Math.Round((double)_scanY, 2);
  105. return _scanY;
  106. }
  107. set
  108. {
  109. value = Math.Round((double)value, 2);
  110. _scanY = value;
  111. }
  112. }
  113. /// <summary>
  114. /// 角度旋转
  115. /// </summary>
  116. private HTuple _rotation = 0;
  117. internal HTuple Rotation
  118. {
  119. get
  120. {
  121. _rotation = Math.Round((double)_rotation, 2);
  122. return _rotation;
  123. }
  124. set
  125. {
  126. value = Math.Round((double)value, 2);
  127. _rotation = value;
  128. }
  129. }
  130. /// <summary>
  131. /// 轴斜切
  132. /// </summary>
  133. private HTuple _theta = 0;
  134. internal HTuple Theta
  135. {
  136. get
  137. {
  138. _theta = Math.Round((double)_theta, 2);
  139. return _theta;
  140. }
  141. set
  142. {
  143. value = Math.Round((double)value, 2);
  144. _theta = value;
  145. }
  146. }
  147. public override void DispImage()
  148. {
  149. // throw new NotImplementedException();
  150. }
  151. public override void DispMainWindow(HWindowTool_Smart window)
  152. {
  153. // throw new NotImplementedException();
  154. }
  155. public override void Run(SoftwareRunState softwareRunState)
  156. {
  157. try
  158. {
  159. // 若首次加载且本地存在矩阵,优先读取本地
  160. if (File.Exists(homMat2DName) && homMat2D.Length == 0)
  161. {
  162. HOperatorSet.ReadTuple(homMat2DName, out homMat2D);
  163. }
  164. // 再次判断
  165. if (homMat2D.Length == 0)
  166. {
  167. runMessage = $"{FormEyeHandCalib.Instance.myToolInfo.FormToolName}未生成仿射矩阵工具,需要先标定标准!";
  168. toolRunStatu = ToolRunStatu.Tool_Run_Error;
  169. FormEyeHandCalib.Instance.SetToolStatus(runMessage, toolRunStatu);
  170. }
  171. else
  172. {
  173. HTuple tupOutX, tupOutY;
  174. HOperatorSet.AffineTransPoint2d(homMat2D, inputPoint.Row, inputPoint.Col, out tupOutX, out tupOutY);
  175. outputPoint.Row = tupOutX;
  176. outputPoint.Col = tupOutY;
  177. runMessage = $"{FormEyeHandCalib.Instance.myToolInfo.FormToolName}运行成功";
  178. toolRunStatu = ToolRunStatu.Succeed;
  179. FormEyeHandCalib.Instance.SetToolStatus(runMessage, toolRunStatu);
  180. }
  181. }
  182. catch (Exception ex)
  183. {
  184. runMessage = $"{FormEyeHandCalib.Instance.myToolInfo.FormToolName}运行出现异常";
  185. toolRunStatu = ToolRunStatu.Tool_Run_Error;
  186. }
  187. }
  188. /// <summary>
  189. /// 初始化标定数据源
  190. /// </summary>
  191. public void InitDataTable()
  192. {
  193. CalibSourceDataTable = new DataTable();
  194. //初始化DataTable,并将datatable绑定到DataGridView的数据源
  195. DataColumn c1 = new DataColumn("像素X", typeof(double));
  196. DataColumn c2 = new DataColumn("像素Y", typeof(double));
  197. DataColumn c3 = new DataColumn("机械X", typeof(double));
  198. DataColumn c4 = new DataColumn("机械Y", typeof(double));
  199. CalibSourceDataTable.Columns.Add(c1);
  200. CalibSourceDataTable.Columns.Add(c2);
  201. CalibSourceDataTable.Columns.Add(c3);
  202. CalibSourceDataTable.Columns.Add(c4);
  203. CalibSourceDataTable.Rows.Clear();
  204. for (int i = 0; i < (int)calibType; i++)
  205. {
  206. DataRow dr = CalibSourceDataTable.NewRow();
  207. dr[0] = 0;
  208. dr[1] = 50;
  209. dr[2] = 0;
  210. dr[3] = 50;
  211. CalibSourceDataTable.Rows.Add(dr);
  212. }
  213. }
  214. /// <summary>
  215. /// 导入标定数据
  216. /// </summary>
  217. public void ReadCalibData()
  218. {
  219. OpenFileDialog digOpenFile = new OpenFileDialog();
  220. digOpenFile.FileName = string.Empty;
  221. digOpenFile.Title = "请选择表格文件";
  222. digOpenFile.Filter = "CSV文件(*.csv)|*.csv";
  223. if (digOpenFile.ShowDialog() == DialogResult.OK)
  224. {
  225. string[] lines = File.ReadAllLines(digOpenFile.FileName, Encoding.Default);
  226. for (int i = 0; i < lines.Length; i++)
  227. {
  228. string[] data = Regex.Split(lines[i], ",");
  229. for (int j = 0; j < data.Length; j++)
  230. {
  231. CalibSourceDataTable.Rows[i][j] = data[j];
  232. if (j == 3) //只导入前四列
  233. break;
  234. }
  235. if (i == (int)calibType) //若标定类型为四点标定,则导入前四行,若为九点标定,则导入前九行
  236. break;
  237. }
  238. }
  239. }
  240. /// <summary>
  241. /// 导出标定数据
  242. /// </summary>
  243. public void ExportCalibData()
  244. {
  245. try
  246. {
  247. SaveFileDialog dig_saveImage = new SaveFileDialog();
  248. dig_saveImage.FileName = "CalibData " + DateTime.Now.ToString("yyyy_MM_dd");
  249. dig_saveImage.Title = "请选择导出路径";
  250. dig_saveImage.Filter = "CSV文件(*.csv)|*.csv";
  251. if (dig_saveImage.ShowDialog() == DialogResult.OK)
  252. {
  253. File.Create(dig_saveImage.FileName).Close();
  254. string data = string.Empty;
  255. for (int i = 0; i <CalibSourceDataTable.Rows.Count; i++)
  256. {
  257. for (int j = 0; j < 4; j++)
  258. {
  259. data += CalibSourceDataTable.Rows[i][j];
  260. if (j < 3)
  261. data += ",";
  262. }
  263. data += Environment.NewLine;
  264. }
  265. File.AppendAllText(dig_saveImage.FileName, data, Encoding.Default);
  266. }
  267. }
  268. catch (Exception ex)
  269. {
  270. Logger.LoggerClass.WriteLog("导出标定数据时出错", ex);
  271. }
  272. }
  273. public bool ManulCalib()
  274. {
  275. try
  276. {
  277. List<double> pixelRowList = new List<double>();
  278. List<double> pixelColList = new List<double>();
  279. List<double> MechanicalXList = new List<double>();
  280. List<double> MechanicalYList = new List<double>();
  281. try
  282. {
  283. for (int i = 0; i < CalibSourceDataTable.Rows.Count; i++)
  284. {
  285. pixelRowList.Add(Convert.ToDouble(CalibSourceDataTable.Rows[i][0]));
  286. pixelColList.Add(Convert.ToDouble(CalibSourceDataTable.Rows[i][1]));
  287. MechanicalXList.Add(Convert.ToDouble(CalibSourceDataTable.Rows[i][2]));
  288. MechanicalYList.Add(Convert.ToDouble(CalibSourceDataTable.Rows[i][3]));
  289. }
  290. }
  291. catch(Exception ex)
  292. {
  293. LoggerClass.WriteLog("标定失败,标定数据异常(错误代码:12901)", ex);
  294. return false;
  295. }
  296. try
  297. {
  298. HTuple pixelRow = new HTuple(pixelRowList.ToArray());
  299. HTuple pixelCol = new HTuple(pixelColList.ToArray());
  300. HTuple mechanicalX = new HTuple(MechanicalXList.ToArray());
  301. HTuple mechanicalY = new HTuple(MechanicalYList.ToArray());
  302. HOperatorSet.VectorToHomMat2d(pixelRow, pixelCol, mechanicalX, mechanicalY, out homMat2D);
  303. }
  304. catch(HalconException ex)
  305. {
  306. LoggerClass.WriteLog("标定失败,标定数据异常,无法确定仿射变换关系(错误代码:12902)", ex);
  307. return false;
  308. }
  309. HOperatorSet.HomMat2dToAffinePar(homMat2D, out _scanX, out _scanY, out _rotation, out _theta, out _translateX, out _translateY);
  310. return true;
  311. }
  312. catch (Exception ex)
  313. {
  314. LoggerClass.WriteLog("手动标定出现异常", ex);
  315. return false;
  316. }
  317. }
  318. }
  319. /// <summary>
  320. /// 标定类型 四点|九点
  321. /// </summary>
  322. [Serializable]
  323. public enum CalibType
  324. {
  325. Four_Point = 4,
  326. Nine_Point = 9,
  327. }
  328. }