版博士V2.0程序
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

482 строки
24 KiB

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