版博士V2.0程序
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

396 líneas
18 KiB

  1. using HalconDotNet;
  2. using Microsoft.ML.OnnxRuntime;
  3. using Microsoft.ML.OnnxRuntime.Tensors;
  4. using Newtonsoft.Json;
  5. using Newtonsoft.Json.Linq;
  6. using OpenCvSharp;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Drawing;
  10. using System.Drawing.Imaging;
  11. using System.IO;
  12. using System.Linq;
  13. using System.Reflection;
  14. using System.Text;
  15. using System.Threading;
  16. using System.Threading.Tasks;
  17. using Yolo5;
  18. namespace ProductionControl.Device
  19. {
  20. public class SizeLib : IDisposable
  21. {
  22. public Action<WarningEnum, string> WarningEvent;
  23. /// <summary>
  24. /// 检测结果JSON(原图,结果)
  25. /// </summary>
  26. public Action<SizeTask> finishEvent;
  27. /// <summary>
  28. /// 是否打开设备成功
  29. /// </summary>
  30. public bool IsInit { get; private set; } = false;
  31. //private System.Timers.Timer timer = new System.Timers.Timer();
  32. //配置
  33. HDevEngine MyEngine = new HDevEngine();
  34. //777时用
  35. Yolo_Class yolo5 =new Yolo_Class();
  36. private Thread t_task;
  37. public SizeLib()
  38. {
  39. }
  40. public bool start(string enginePath)
  41. {
  42. try
  43. {
  44. IsInit = true;
  45. taskList.Clear();
  46. MyEngine.SetProcedurePath(enginePath);
  47. t_task = new System.Threading.Thread(run);
  48. t_task.IsBackground = true;
  49. t_task.Start();
  50. return true;
  51. }
  52. catch (Exception ex)
  53. {
  54. WarningEvent?.Invoke(WarningEnum.High,ex.Message);
  55. return false;
  56. }
  57. }
  58. public void stop()
  59. {
  60. if (!IsInit) return;
  61. try
  62. {
  63. IsInit = false;
  64. //timer.Elapsed -= Timer_Elapsed;
  65. MyEngine.Dispose();
  66. }
  67. catch { }
  68. }
  69. private bool _debug = false;
  70. public bool setDebug {
  71. get { return _debug; }
  72. set {
  73. if (!IsInit) return;
  74. _debug=value;
  75. if (_debug)
  76. MyEngine.StartDebugServer();
  77. else
  78. MyEngine.StopDebugServer();
  79. }
  80. }
  81. //流程:111,222,444,333,777,777,777,。。。
  82. private void run()
  83. {
  84. int taskCount;
  85. while (IsInit)
  86. {
  87. lock (taskList)
  88. {
  89. taskCount = taskList.Count;
  90. }
  91. if (taskCount < 1)
  92. {
  93. Thread.Sleep(10);
  94. continue;
  95. }
  96. ////
  97. int step = 0;
  98. var task = pop();
  99. try
  100. {
  101. if (task != null)
  102. {
  103. var Program1 = new HDevProcedure(task.engineName);
  104. HDevProcedureCall ProcCall1_PI_PT = new HDevProcedureCall(Program1);
  105. step = 1;
  106. //
  107. HObject image;
  108. if (task.bmp != null)
  109. Bitmap2HObjectBpp24(out image, task.bmp);
  110. else
  111. HOperatorSet.ReadImage(out image, task.file_path);
  112. step = 2;
  113. //设置外部函数输入
  114. //if (task.index < 100)
  115. {
  116. ProcCall1_PI_PT.SetInputIconicParamObject("Image1", image.Clone());
  117. ProcCall1_PI_PT.SetInputCtrlParamTuple("index", task.index);//参数1-9
  118. ProcCall1_PI_PT.SetInputCtrlParamTuple("posX", task.posX);
  119. ProcCall1_PI_PT.SetInputCtrlParamTuple("posY", task.posY);
  120. ProcCall1_PI_PT.SetInputCtrlParamTuple("GerberPath",new HTuple( task.drawingPagePath));//美尚没有
  121. //设置外部函数输入
  122. if ((task.PTandLinePos != null) && (task.PTandLinePos[0] != 0))
  123. {
  124. double[] posarray = new double[23];
  125. posarray[0] = task.PTandLinePos[0];
  126. posarray[1] = task.PTandLinePos[2];
  127. posarray[2] = task.PTandLinePos[4];
  128. posarray[3] = task.PTandLinePos[6];
  129. posarray[4] = task.PTandLinePos[8];
  130. for (int i = 0; i < 18; i++)
  131. {
  132. posarray[5 + i] = task.PTandLinePos[10 + i];
  133. }
  134. ProcCall1_PI_PT.SetInputCtrlParamTuple("UserPose", posarray);
  135. /////
  136. ///
  137. //string directory = Config.LogPath + "\\" + DateTime.Now.ToString("yyyyMM") + "\\";
  138. //if (!System.IO.Directory.Exists(directory))
  139. // System.IO.Directory.CreateDirectory(directory);
  140. //File.AppendAllText(directory + "sizeData.log", "data:" + string.Join(",", posarray) + "\r\n");
  141. }
  142. else
  143. {
  144. double[] posarray = new double[23];
  145. ProcCall1_PI_PT.SetInputCtrlParamTuple("UserPose", posarray);
  146. }
  147. }
  148. if (task.index == 777)
  149. {
  150. ProcCall1_PI_PT.SetInputIconicParamObject("ContoursAffineTrans1", task.ContoursAffineTrans1_Out);
  151. }
  152. else
  153. {
  154. HObject ContoursAffineTrans1;
  155. HOperatorSet.GenEmptyObj(out ContoursAffineTrans1);
  156. ProcCall1_PI_PT.SetInputIconicParamObject("ContoursAffineTrans1", ContoursAffineTrans1);
  157. }
  158. step = 3;
  159. ProcCall1_PI_PT.Execute();//执行外部函数
  160. step = 4;
  161. //获取外部函数输出
  162. switch (task.index)
  163. {
  164. case 777://比对结果
  165. step = 10;
  166. task.CompResult = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("RES") == 1;//结果,1为true,0为false
  167. step = 11;
  168. if (!task.CompResult)
  169. {
  170. var Defects_X = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_X");
  171. var Defects_Y = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_Y");
  172. var Defects_LeftTop_X = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_LeftTop_X");
  173. var Defects_LeftTop_Y = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_LeftTop_Y");
  174. var Defects_RightBottom_X = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_RightBottom_X");
  175. var Defects_RightBottom_Y = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_RightBottom_Y");
  176. var Contour_Image = ProcCall1_PI_PT.GetOutputIconicParamObject("Contour_Image");
  177. //var Zoom_Image = ProcCall1_PI_PT.GetOutputIconicParamObject("Zoom_Image");
  178. var Defects_Type = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_Type");
  179. var Defects_Index = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_Index");
  180. step = 12;
  181. //对比打标图:显示在UI上,以后修复台用
  182. //task.Zoom_Image_mat = yolo5.DrawContour_Opencv(Contour_Image, Zoom_Image, Defects_LeftTop_X, Defects_LeftTop_Y, Defects_RightBottom_X, Defects_RightBottom_Y);
  183. //新YOLO.DLL
  184. task.defectInfor2RestorationDesk = new List<List<string>>();
  185. task.Zoom_Image_mat = yolo5.DrawContour_Opencv(Contour_Image, image, Defects_LeftTop_X, Defects_LeftTop_Y,
  186. Defects_RightBottom_X, Defects_RightBottom_Y, Defects_Type, Defects_Index, Defects_X, Defects_Y, out task.defectInfor2RestorationDesk);
  187. //WarningEvent?.Invoke(WarningEnum.Normal, $"SizeLib 777 call DrawContour_Opencv(),Defects_LeftTop_X={Defects_LeftTop_X}," +
  188. // $"Defects_LeftTop_Y={Defects_LeftTop_Y},Defects_RightBottom_X={Defects_RightBottom_X},Defects_RightBottom_Y={Defects_RightBottom_Y}," +
  189. // $"Defects_Type={Defects_Type},Defects_Index={Defects_Index},Defects_X={Defects_X},Defects_Y={Defects_Y}," +
  190. // $"defectInfor2RestorationDesk={JsonConvert.SerializeObject(task.defectInfor2RestorationDesk)}");
  191. step = 13;
  192. task.Zoom_Image_mat = yolo5.ResizesMat_4(task.Zoom_Image_mat);
  193. //大图缺陷坐标转换到图纸坐标
  194. step = 14;
  195. if (Config.OpenFlawDistribution)
  196. {
  197. if (!string.IsNullOrWhiteSpace(task.drawingPagePath) && task.defectInfor2RestorationDesk != null && task.defectInfor2RestorationDesk.Count > 0)
  198. task.defectInfor2RestorationDeskPage = yolo5.DefectDrawGerberImage(task.drawingPagePath, task.defectInfor2RestorationDesk);
  199. }
  200. }
  201. break;
  202. case 111:
  203. task.MarkPointList[0] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkX_1");
  204. task.MarkPointList[1] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkY_1");
  205. break;
  206. case 222:
  207. task.MarkPointList[2] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkX_2");
  208. task.MarkPointList[3] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkY_2");
  209. break;
  210. case 333:
  211. task.MarkPointList[4] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkX_3");
  212. task.MarkPointList[5] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkY_3");//ContoursAffineTrans1
  213. task.ContoursAffineTrans1_Out = ProcCall1_PI_PT.GetOutputIconicParamObject("ContoursAffineTrans1_Out");
  214. break;
  215. case 444:
  216. task.MarkPointList[6] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkX_4");
  217. task.MarkPointList[7] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkY_4");
  218. break;
  219. case 3333: //Tag使用,同时继续获取使用default时时校正和其它值
  220. step = 80;
  221. if (!string.IsNullOrWhiteSpace( task.sizeTag))
  222. task.posePT= ProcCall1_PI_PT.GetOutputCtrlParamTuple("posePT").DArr;
  223. goto default;
  224. default:
  225. step = 90;
  226. task.PT1 = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("DistancePT1");//index=8 PT1=PT2
  227. task.PT2 = ProcCall1_PI_PT.GetOutputCtrlParamTuple("DistancePT2");
  228. task.Shanxian = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("Distance3Median");
  229. //task.RowP = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("RowP");
  230. task.Circle_Ymm = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("Circle_Ymm");
  231. task.Circle_Xmm = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("Circle_Xmm");
  232. task.offsetX = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("offsetX");
  233. task.offsetY = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("offsetY");
  234. break;
  235. }
  236. step = 100;
  237. ProcCall1_PI_PT.Dispose();
  238. Program1.Dispose();
  239. step = 101;
  240. task.isSucceed = true;
  241. task.resultInfo = "成功";
  242. callback(task);
  243. step = 102;
  244. }
  245. Thread.Sleep(5);
  246. }
  247. catch (Exception ex)
  248. {
  249. WarningEvent?.Invoke(WarningEnum.Low, $"SizeLib task err({step}) index({task.index}):"+ ex.Message);
  250. task.isSucceed = false;
  251. task.resultInfo = $"(errcode:{step}):{ex.Message}";
  252. callback(task);
  253. }
  254. }
  255. }
  256. private void callback(SizeTask task)
  257. {
  258. //返回成功/失败,异步调用
  259. if (task.finishEvent != null || (task.finishEvent = finishEvent) != null)
  260. //task.finishEvent.BeginInvoke(result, errInfo, res => task.finishEvent.EndInvoke(res), null);
  261. System.Threading.ThreadPool.QueueUserWorkItem(waitCallback, task);
  262. }
  263. //异步回调
  264. WaitCallback waitCallback = new WaitCallback(o => {
  265. var task = (SizeTask)o;
  266. task.finishEvent(task);
  267. });
  268. //=======task list
  269. private List<SizeTask> taskList = new List<SizeTask>();
  270. public class SizeTask
  271. {
  272. public int stepIndex;//只为回调记录当前工序信息
  273. public string processName;//只为回调记录当前工序信息
  274. public string engineName,sizeTag;
  275. /// <summary>
  276. /// 源文件
  277. /// </summary>
  278. public string file_path;
  279. public double posX,posY;
  280. public Bitmap bmp;
  281. public string drawingPagePath = "";//.gbx图纸路径
  282. //2023-10-27 新增图纸选择pt点位与线宽点位
  283. public double[] PTandLinePos;
  284. /// <summary>
  285. /// 比对(index=777); 计算Mark(111/222/333/444); 尺寸(1-9); 轴偏移调整(10,20,30...)
  286. /// </summary>
  287. public int index; //index=8 PT1=PT2
  288. /// <summary>
  289. /// 完成后回调
  290. /// </summary>
  291. public Action<SizeTask> finishEvent;
  292. public long createTime = DateTime.Now.Ticks;
  293. //==结果返回
  294. /// <summary>
  295. /// 比对结果(index=777)
  296. /// </summary>
  297. public bool CompResult;
  298. public Mat Zoom_Image_mat;//对比打标图:777比对失败时计算得出,后面显示到UI 以后修复台用
  299. public List<List<string>> defectInfor2RestorationDesk, defectInfor2RestorationDeskPage;//对比未通过坐标信息,合并到缺陷检测中的 //打标缺陷转为图纸的坐标;
  300. //MARK点
  301. public double[] MarkPointList = { 0, 0, 0, 0, 0, 0, 0, 0 };
  302. public HObject ContoursAffineTrans1_Out;//index=333时输出,供后面多个777比对时输入使用
  303. public double[] posePT;//index=3333 && !isEmpty(sizeTag) 才取此数组值,len为0时急停
  304. //
  305. public double PT1,PT2, Shanxian, Circle_Ymm, Circle_Xmm, offsetX, offsetY;
  306. public bool isSucceed;//转换是否成功
  307. public string resultInfo = "";//成功或失败信息
  308. }
  309. public void add(SizeTask task)
  310. {
  311. lock (taskList)
  312. taskList.Add(task);
  313. }
  314. private SizeTask pop()
  315. {
  316. lock (taskList)
  317. {
  318. if (taskList.Count < 1)
  319. return null;
  320. var task = taskList[0];
  321. taskList.RemoveAt(0);
  322. return task;
  323. }
  324. }
  325. public void Dispose()
  326. {
  327. stop();
  328. }
  329. /// <summary>
  330. /// Bitmap转HObject灰度图
  331. /// </summary>
  332. /// <param name="bmp">Bitmap图像</param>
  333. /// <param name="image">HObject图像</param>
  334. private void Bitmap2HObjectBpp8( out HObject image,Bitmap bmp)
  335. {
  336. try
  337. {
  338. Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
  339. BitmapData srcBmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
  340. HOperatorSet.GenImage1(out image, "byte", bmp.Width, bmp.Height, srcBmpData.Scan0);
  341. bmp.UnlockBits(srcBmpData);
  342. }
  343. catch (Exception)
  344. {
  345. image = null;
  346. }
  347. }
  348. public void Bitmap2HObjectBpp24( out HObject image, Bitmap bmp)
  349. {
  350. try
  351. {
  352. Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
  353. BitmapData srcBmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
  354. HOperatorSet.GenImageInterleaved(out image, srcBmpData.Scan0, "bgr", bmp.Width, bmp.Height, 0, "byte", 0, 0, 0, 0, -1, 0);
  355. bmp.UnlockBits(srcBmpData);
  356. }
  357. catch (Exception ex)
  358. {
  359. image = null;
  360. }
  361. }
  362. }
  363. }