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

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