版博士V2.0程序
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 

510 rindas
20 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Drawing;
  5. using System.Drawing.Imaging;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Reflection;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. using MaiMuAOI.SysCtrl;
  12. using MaiMuControl.Device;
  13. using Microsoft.ML.OnnxRuntime;
  14. using Microsoft.ML.OnnxRuntime.Tensors;
  15. using OpenCvSharp;
  16. using Yolo5;
  17. namespace MaiMuAOI.ImageProcessing
  18. {
  19. public class DefectLib : IDisposable
  20. {
  21. public Action<WarningEnum, string> WarningEvent;
  22. /// <summary>
  23. /// 检测结果JSON(原图,结果)
  24. /// </summary>
  25. public Action<DefectTask> finishEvent;
  26. /// <summary>
  27. /// 是否打开设备成功
  28. /// </summary>
  29. public bool IsInit { get; private set; } = false;
  30. //private System.Timers.Timer timer = new System.Timers.Timer();
  31. private Yolo_Class yolo1;
  32. private InferenceSession _onnxSession;
  33. //
  34. private Thread t_task, t_task_operation, t_task_operation2, t_task_tag;
  35. //=======task list
  36. private List<DefectTask> taskList = new List<DefectTask>();
  37. private List<DefectTask> taskOperationList = new List<DefectTask>();
  38. private List<DefectTask> taskTagList = new List<DefectTask>();
  39. public DefectLib()
  40. {
  41. }
  42. public bool start()
  43. {
  44. try
  45. {
  46. yolo1 = new Yolo_Class();
  47. //加载模型(只加载一次即可)
  48. //string modelFilePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\DevCfg\\best.onnx";
  49. //_onnxSession = yolo1.LoadModel(modelFilePath, true);//false-CPU true-显卡
  50. IsInit = true;
  51. //timer.Elapsed += Timer_Elapsed;
  52. //timer.Interval = 100;
  53. //timer.Enabled = true;
  54. taskList.Clear();
  55. taskOperationList.Clear();
  56. taskTagList.Clear();
  57. t_task = new System.Threading.Thread(runStep);
  58. t_task.IsBackground = true;
  59. t_task.Start();
  60. t_task_operation = new System.Threading.Thread(run2);
  61. t_task_operation.IsBackground = true;
  62. t_task_operation.Start();
  63. t_task_operation2 = new System.Threading.Thread(run2);
  64. t_task_operation2.IsBackground = true;
  65. t_task_operation2.Start();
  66. return true;
  67. }
  68. catch (Exception ex)
  69. {
  70. WarningEvent?.Invoke(WarningEnum.High, ex.Message);
  71. return false;
  72. }
  73. }
  74. public void stop()
  75. {
  76. if (!IsInit) return;
  77. try
  78. {
  79. IsInit = false;
  80. //timer.Elapsed -= Timer_Elapsed;
  81. //释放模型
  82. if (_onnxSession != null)
  83. {
  84. _onnxSession.Dispose();
  85. _onnxSession = null;
  86. }
  87. _preLoadONNXFilePath = null;
  88. if (t_task != null)
  89. {
  90. bool b = t_task.Join(5000);
  91. if (!b) t_task.Abort();
  92. t_task = null;
  93. }
  94. if (t_task_operation != null)
  95. {
  96. bool b = t_task_operation.Join(5000);
  97. if (!b) t_task_operation.Abort();
  98. t_task_operation = null;
  99. }
  100. if (t_task_operation2 != null)
  101. {
  102. bool b = t_task_operation2.Join(5000);
  103. if (!b) t_task_operation2.Abort();
  104. t_task_operation2 = null;
  105. }
  106. if (t_task_tag != null)
  107. {
  108. bool b = t_task_tag.Join(5000);
  109. if (!b) t_task_tag.Abort();
  110. t_task_tag = null;
  111. }
  112. taskList.Clear();
  113. taskOperationList.Clear();
  114. taskTagList.Clear();
  115. }
  116. catch { }
  117. }
  118. private string _preLoadONNXFilePath;//记录上次成功加载的模型,不重复加载
  119. public void loadModelFile(string onnxFilePath)
  120. {
  121. //string modelFilePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\DevCfg\\best.onnx";
  122. //不重复加载
  123. if (!string.IsNullOrWhiteSpace(_preLoadONNXFilePath) && _preLoadONNXFilePath.ToLower() == onnxFilePath.ToLower())
  124. return;
  125. //Task.Run(async () =>
  126. //{
  127. // if (_onnxSession != null)
  128. // {
  129. // _onnxSession.Dispose();
  130. // _onnxSession = null;
  131. // }
  132. // _onnxSession = yolo1.LoadModel(onnxFilePath, true);//false-CPU true-显卡
  133. // _preLoadONNXFilePath = onnxFilePath;
  134. //});
  135. if (_onnxSession != null)
  136. {
  137. _onnxSession.Dispose();
  138. _onnxSession = null;
  139. }
  140. _onnxSession = yolo1.LoadModel(onnxFilePath, true);//false-CPU true-显卡
  141. _preLoadONNXFilePath = onnxFilePath;
  142. }
  143. /// <summary>
  144. /// 保存图片
  145. /// </summary>
  146. /// <param name="Img"></param>图片
  147. /// <param name="pictureUrl"></param>保存路径
  148. /// <param name="pictureName"></param>保存名称
  149. private void SaveImage(Bitmap Img, string pictureUrl, string pictureName)
  150. {
  151. if (!Directory.Exists(pictureUrl))
  152. {
  153. Directory.CreateDirectory(pictureUrl);
  154. }
  155. FileInfo FileUrl = new FileInfo(pictureUrl);//防止路径中有日期导致路径错误
  156. try
  157. {
  158. using (Bitmap bitmap = new Bitmap(Img))
  159. {
  160. using (MemoryStream stream = new MemoryStream())
  161. {
  162. bitmap.Save(stream, ImageFormat.Bmp);
  163. System.Drawing.Image img = System.Drawing.Image.FromStream(stream);
  164. //img.Save(FileUrl +"\\"+ pictureName);
  165. //img.Dispose();
  166. string szURL = FileUrl + "\\" + pictureName;
  167. img.Save(szURL, ImageFormat.Bmp);
  168. img.Dispose();
  169. }
  170. }
  171. }
  172. catch (Exception)
  173. {
  174. if (Img != null)
  175. {
  176. Img.Dispose();
  177. }
  178. }
  179. }
  180. private void runStep()
  181. {
  182. while (IsInit)
  183. {
  184. if (taskList.Count < 1 || _onnxSession == null)
  185. {
  186. Thread.Sleep(5);
  187. continue;
  188. }
  189. //
  190. var task = pop();
  191. try
  192. {
  193. if (task != null)
  194. {
  195. Stopwatch stopwatch = Stopwatch.StartNew();
  196. //源图
  197. //Bitmap bmp = yolo1.Read2Bmp(file_path);
  198. //切割图像,输入图像格式14208*10640
  199. stopwatch.Start();
  200. task.bmps_cut = yolo1.OpenCVToCutsMat(task.bmp, task.cut_size.Width, task.cut_size.Height);
  201. stopwatch.Stop();
  202. task.stopwatch[0] = stopwatch.ElapsedMilliseconds;
  203. //Resize图像
  204. stopwatch.Restart();
  205. task.bmps_resize = yolo1.OpenCVToResizesMat(task.bmps_cut, task.resize.Width, task.resize.Height);
  206. stopwatch.Stop();
  207. task.stopwatch[1] = stopwatch.ElapsedMilliseconds;
  208. //预处理模型
  209. stopwatch.Restart();
  210. task.tensors = yolo1.PreprocessImageMat(task.bmps_resize);
  211. stopwatch.Stop();
  212. task.stopwatch[2] = stopwatch.ElapsedMilliseconds;
  213. lock (taskOperationList)
  214. taskOperationList.Add(task);
  215. }
  216. Thread.Sleep(5);
  217. }
  218. catch (Exception ex)
  219. {
  220. WarningEvent?.Invoke(WarningEnum.Low, "DefectLib task1 err:" + ex.Message);
  221. task.isSucceed = false;
  222. task.resultInfo = ex.Message;
  223. callback(task);
  224. }
  225. }
  226. }
  227. private void run2()
  228. {
  229. while (IsInit)
  230. {
  231. if (taskOperationList.Count < 1)
  232. {
  233. Thread.Sleep(5);
  234. continue;
  235. }
  236. //
  237. var task = pop2();
  238. int liStep = 0;
  239. try
  240. {
  241. if (task != null)
  242. {
  243. Stopwatch stopwatch = Stopwatch.StartNew();
  244. //====运行推理(必需单队列)
  245. stopwatch.Start();
  246. IDisposableReadOnlyCollection<DisposableNamedOnnxValue>[] results = yolo1.RunModlel(_onnxSession, task.tensors);
  247. liStep = 1;
  248. task.informationList = yolo1.ScreeningResults_YD(results, task.bmps_resize, task.thresholds, task.thresholdsClass, task.recAreaThreshold);
  249. liStep = 2;
  250. //当前大图上缺陷个数
  251. int currPicDefectCount = 0;
  252. for (int x = 0; x < task.informationList.Count(); x++)
  253. currPicDefectCount += task.informationList[x].Count();
  254. task.defectCount = currPicDefectCount;
  255. stopwatch.Stop();
  256. task.stopwatch[3] = stopwatch.ElapsedMilliseconds;
  257. liStep = 3;
  258. if (task.informationList.Count > 0)
  259. {
  260. liStep = 4;
  261. //lock (taskTagList)
  262. // taskTagList.Add(task);
  263. //====打标 ,有缺陷返回缺陷图片数组,没缺陷返回所有图片数组
  264. stopwatch.Restart();
  265. task.bmps_tag = yolo1.DrawYoloPrediction2Mat(task.bmps_cut, task.informationList, 27, SixLabors.ImageSharp.Color.OrangeRed, task.resize.Width,
  266. task.Xmm, task.Ymm, out task.defectInfor2RestorationDesk);
  267. liStep = 5;
  268. if (ConfMgr.Instance.SysConfigParams.OpenFlawDistribution)
  269. {
  270. //大图缺陷坐标转换到图纸坐标
  271. if (!string.IsNullOrWhiteSpace(task.drawingPagePath) && task.defectInfor2RestorationDesk != null && task.defectInfor2RestorationDesk.Count > 0)
  272. task.defectInfor2RestorationDeskPage = yolo1.DefectDrawGerberImage(task.drawingPagePath, task.defectInfor2RestorationDesk);
  273. }
  274. stopwatch.Stop();
  275. task.stopwatch[4] = stopwatch.ElapsedMilliseconds;
  276. liStep = 6;
  277. task.bmpCompress = yolo1.ResizesMat_4(task.bmp);
  278. task.isSucceed = true;
  279. callback(task);
  280. }
  281. else
  282. {
  283. task.isSucceed = true;
  284. callback(task);
  285. }
  286. }
  287. Thread.Sleep(5);
  288. }
  289. catch (Exception ex)
  290. {
  291. WarningEvent?.Invoke(WarningEnum.Low, $"DefectLib task2 err({liStep}):" + ex.Message);
  292. task.isSucceed = false;
  293. task.resultInfo = ex.Message;
  294. callback(task);
  295. }
  296. }
  297. }
  298. /// <summary>
  299. /// 已不用
  300. /// </summary>
  301. private void run3()
  302. {
  303. while (IsInit)
  304. {
  305. if (taskTagList.Count < 1)
  306. {
  307. Thread.Sleep(0);
  308. continue;
  309. }
  310. //
  311. var task = pop3();
  312. try
  313. {
  314. if (task != null)
  315. {
  316. Stopwatch stopwatch = Stopwatch.StartNew();
  317. //====打标 ,有缺陷返回缺陷图片数组,没缺陷返回所有图片数组
  318. stopwatch.Start();
  319. task.bmps_tag = yolo1.DrawYoloPrediction2Mat(task.bmps_cut, task.informationList, 27, SixLabors.ImageSharp.Color.OrangeRed, task.resize.Width,
  320. task.Xmm,task.Ymm,out task.defectInfor2RestorationDesk);
  321. stopwatch.Stop();
  322. task.stopwatch[4] = stopwatch.ElapsedMilliseconds;
  323. task.isSucceed = true;
  324. callback(task);
  325. }
  326. }
  327. catch (Exception ex)
  328. {
  329. WarningEvent?.Invoke(WarningEnum.Low, "DefectLib task3 err:" + ex.Message);
  330. task.isSucceed = false;
  331. task.resultInfo = ex.Message;
  332. callback(task);
  333. }
  334. }
  335. }
  336. private void callback(DefectTask task)
  337. {
  338. //返回成功/失败,异步调用
  339. if (task.finishEvent != null || (task.finishEvent = finishEvent) != null)
  340. //task.finishEvent.BeginInvoke(result, errInfo, res => task.finishEvent.EndInvoke(res), null);
  341. System.Threading.ThreadPool.QueueUserWorkItem(waitCallback, task);
  342. }
  343. //异步回调
  344. WaitCallback waitCallback = new WaitCallback(o =>
  345. {
  346. var task = (DefectTask)o;
  347. task.finishEvent(task);
  348. });
  349. public class DefectTask
  350. {
  351. public int stepIndex;
  352. public string processName;
  353. public string drawingPagePath;//图纸路径bmp
  354. //图索引
  355. public int index = 0;
  356. /// <summary>
  357. /// 绝对位置-----X2轴
  358. /// </summary>
  359. public double Xmm;
  360. /// <summary>
  361. /// 绝对位置-----Y轴
  362. /// </summary>
  363. public double Ymm;
  364. /// <summary>
  365. /// 源文件
  366. /// </summary>
  367. public Mat bmp;
  368. public Mat bmpCompress;//压缩有缺陷大图
  369. public System.Drawing.Size cut_size = new System.Drawing.Size(592, 532);
  370. public System.Drawing.Size resize = new System.Drawing.Size(224, 224);
  371. /// <summary>
  372. /// 阈值
  373. /// </summary>
  374. public float thresholds = 0.4f;
  375. /// <summary>
  376. /// 种类阈值
  377. /// </summary>
  378. public string thresholdsClass;
  379. /// <summary>
  380. /// 缺陷在面积内数量
  381. /// </summary>
  382. public Dictionary<string, float> recAreaThreshold;
  383. /// <summary>
  384. /// 完成后回调
  385. /// </summary>
  386. public Action<DefectTask> finishEvent;
  387. //
  388. public long createTime = DateTime.Now.Ticks;
  389. public DateTime nowTime;
  390. //中间变量,供step2使用
  391. public Mat[] bmps_cut;
  392. public Mat[] bmps_resize;
  393. //预处理模型
  394. public Tensor<float>[] tensors;
  395. //==结果返回
  396. public List<Dictionary<int, List<string>[]>> informationList;
  397. public int defectCount;//informationList中的缺陷数
  398. public List<List<string>> defectInfor2RestorationDesk, defectInfor2RestorationDeskPage;//打标缺陷转为图纸的坐标
  399. public Bitmap[] bmps_tag; //打标小图 //bmps_tag.count<=bmps_cut.count bmps_tag.count=informationList.count
  400. public bool isSucceed;//转换是否成功
  401. public string resultInfo = "";//成功或失败信息
  402. public long[] stopwatch = new long[5];
  403. }
  404. public void add(DefectTask task)
  405. {
  406. lock (taskList)
  407. taskList.Add(task);
  408. }
  409. /// <summary>
  410. /// 打标 返回每张图的绝对位置X,Y
  411. /// </summary>
  412. /// <param name="defectBmpIndex">缺陷小图索引</param>
  413. /// <param name="X">拍照位绝对位置-----X2轴</param>
  414. /// <param name="Y">拍照位绝对位置-----Y轴</param>
  415. /// <param name="imagewidth">裁剪小图的宽592</param>
  416. /// <param name="imageheight">裁剪小图的高532</param>
  417. public List<double> makeTag(int defectBmpIndex, double X, double Y, int imagewidth, int imageheight)
  418. {
  419. return yolo1.ImageXY(defectBmpIndex, X, Y, imagewidth, imageheight);
  420. }
  421. /// <summary>
  422. /// 用相机1查看缺陷点
  423. /// </summary>
  424. /// <param name="defectBmpIndex"></param>
  425. /// <param name="X"></param>
  426. /// <param name="Y"></param>
  427. /// <param name="imagewidth"></param>
  428. /// <param name="imageheight"></param>
  429. /// <returns></returns>
  430. public List<double> viewTag(int defectBmpIndex, double X, double Y, int imagewidth, int imageheight)
  431. {
  432. return yolo1.ImageXY2(defectBmpIndex, X, Y, imagewidth, imageheight);
  433. }
  434. private DefectTask pop()
  435. {
  436. lock (taskList)
  437. {
  438. if (taskList.Count < 1)
  439. return null;
  440. //int index = 0;// taskList.FindIndex(p => { return p.isSync; });
  441. //if (index < 0) index = 0;
  442. var task = taskList[0];
  443. taskList.RemoveAt(0);
  444. return task;
  445. }
  446. }
  447. private DefectTask pop2()
  448. {
  449. lock (taskOperationList)
  450. {
  451. if (taskOperationList.Count < 1)
  452. return null;
  453. //int index = 0;// taskList.FindIndex(p => { return p.isSync; });
  454. //if (index < 0) index = 0;
  455. var task = taskOperationList[0];
  456. taskOperationList.RemoveAt(0);
  457. return task;
  458. }
  459. }
  460. private DefectTask pop3()
  461. {
  462. lock (taskTagList)
  463. {
  464. if (taskTagList.Count < 1)
  465. return null;
  466. //int index = 0;// taskList.FindIndex(p => { return p.isSync; });
  467. //if (index < 0) index = 0;
  468. var task = taskTagList[0];
  469. taskTagList.RemoveAt(0);
  470. return task;
  471. }
  472. }
  473. public void Dispose()
  474. {
  475. stop();
  476. }
  477. }
  478. }