革博士V2程序
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

1051 řádky
55 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Diagnostics;
  5. using System.Diagnostics.Contracts;
  6. using System.Drawing;
  7. using System.Drawing.Imaging;
  8. using System.IO;
  9. using System.Linq;
  10. using System.Reflection;
  11. using System.Runtime.InteropServices;
  12. using System.Threading;
  13. using LeatherApp.Utils;
  14. using Models;
  15. using OpenCvSharp;
  16. using OpenCvSharp.Extensions;
  17. using SqlSugar;
  18. namespace LeatherApp.Device
  19. {
  20. public class DefectLib : IDisposable
  21. {
  22. //private const string dll_path = "yoloOrt.dll";
  23. //[DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
  24. //extern static IntPtr CreateDetector(string model_path, string labels_path, bool is_gpu, int numberThreads);
  25. private const string dll_path = "yolo_trt.dll";
  26. [DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
  27. static extern IntPtr CreateDetector(string model_path);
  28. [DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
  29. extern static bool DestroyDetector(IntPtr detector);
  30. /// <summary>
  31. /// 非0值表示成功,0表示失败 返回小图张数
  32. /// </summary>
  33. /// <param name="detector"></param>
  34. /// <returns></returns>
  35. [DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
  36. static extern int GetBatchSize(IntPtr detector);
  37. //[DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
  38. //extern static bool Detect1(IntPtr detector, ref byte bgrs_data,
  39. // int image_num, int width, int height, int channels,
  40. // float conf_threshold, float iou_threshold,
  41. // ref int output, int output_size, ref int object_num);
  42. [DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
  43. static extern bool Detect(IntPtr detector, ref byte bgrs_data,
  44. int image_num, int width, int height, int channels,
  45. float conf_threshold, float iou_threshold,
  46. ref float output, int output_size, ref int object_num,
  47. int expand_pixel);
  48. //-----
  49. //private const string dll_path = "yolo_trt .dll";
  50. //[DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
  51. //static extern IntPtr CreateDetector(string model_path);
  52. //[DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
  53. //static extern bool DestroyDetector(IntPtr detector);
  54. //[DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
  55. //static extern bool Detect(IntPtr detector, ref byte bgrs_data,
  56. // int image_num, int width, int height, int channels,
  57. // float conf_threshold, float iou_threshold,
  58. // ref int output, int output_size, ref int object_num);
  59. //---
  60. private IntPtr detector = IntPtr.Zero;
  61. private readonly int image_width = 2048;
  62. private readonly int image_hight = 2048;
  63. private readonly int image_channels = 3;
  64. private readonly int image_bytes = 2048 * 2048 * 3;
  65. private readonly int detect_elem_size = 7; //维度数据结果,x y w h conf classid
  66. private readonly int detect_max_object_num = 20;//这个指的是一张子图可能最多给你返回的目标个球
  67. //
  68. public Action<int, int> QueueCountEvent;//0/1/2, 数量
  69. public Action<DateTime,WarningEnum, string> WarningEvent;
  70. /// <summary>
  71. /// 检测结果JSON(原图,结果)
  72. /// </summary>
  73. public Action<DefectTask> finishEvent;
  74. /// <summary>
  75. /// 是否打开设备成功
  76. /// </summary>
  77. public bool IsInit { get; private set; } = false;
  78. string rootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
  79. private Thread t_task, t_task_operation ,t_task_maketag;
  80. //=======task list
  81. private List<DefectTask> taskList = new List<DefectTask>();
  82. private List<DefectTask> taskOperationList = new List<DefectTask>();
  83. private List<DefectTask> taskMakeTagList = new List<DefectTask>();
  84. private string preModelName = "";
  85. public DefectLib()
  86. {
  87. }
  88. public bool start()
  89. {
  90. List<DefectLabelInfo> DefectLabelInfoList = new List<DefectLabelInfo>();
  91. DefectLabelInfoList.Add(new DefectLabelInfo() { x = 1953, y = 429, w = 200, h = 200, classId = 1, confidence = 0.8, contrast = 0.9, i = 0, j = 0 });
  92. DefectLabelInfoList.Add(new DefectLabelInfo() {x = 1953,y = 929,w=900,h = 400,classId = 11,confidence = 0.8, contrast = 0.9, i = 0,j = 0 });
  93. DefectLabelInfoList.Add(new DefectLabelInfo() { x = 3169, y = 1029, w = 900, h = 400, classId = 11, confidence = 0.8, contrast = 0.9, i = 1, j = 0 });
  94. DefectLabelInfoList.Add(new DefectLabelInfo() { x = 4721, y = 919, w = 900, h = 400, classId = 11, confidence = 0.8, contrast = 0.9, i = 2, j = 0 });
  95. DefectLabelInfoList.Add(new DefectLabelInfo() { x = 6145, y = 829, w = 900, h = 400, classId = 11, confidence = 0.8, contrast = 0.9, i = 3, j = 0 });
  96. DefectLabelInfoList.Add(new DefectLabelInfo() { x = 8073, y = 929, w = 900, h = 400, classId = 11, confidence = 0.8, contrast = 0.9, i = 4, j = 0 });
  97. DefectLabelInfoList.Add(new DefectLabelInfo() { x = 9407, y = 929, w = 900, h = 400, classId = 11, confidence = 0.8, contrast = 0.9, i = 5, j = 0 });
  98. DefectLabelInfoList.Add(new DefectLabelInfo() { x = 10801, y = 999, w = 900, h = 400, classId = 11, confidence = 0.8, contrast = 0.9, i = 6, j = 0 });
  99. DefectLabelInfoList.Add(new DefectLabelInfo() { x = 12465, y = 629, w = 900, h = 800, classId = 11, confidence = 0.8, contrast = 0.9, i = 7, j = 0 });
  100. DefectLabelInfoList = HeBingDefect(16384, DefectLabelInfoList);
  101. try
  102. {
  103. //detector = CreateDetector(Config.model_path, Config.labels_path, true, 6);
  104. //if (detector == IntPtr.Zero)
  105. // throw new Exception("模型初始化失败!");
  106. preModelName = "";
  107. IsInit = true;
  108. taskList.Clear();
  109. taskOperationList.Clear();
  110. taskMakeTagList.Clear();
  111. t_task = new System.Threading.Thread(runStep);
  112. t_task.IsBackground = true;
  113. t_task.Start();
  114. t_task_operation = new System.Threading.Thread(run2);
  115. t_task_operation.IsBackground = true;
  116. t_task_operation.Start();
  117. t_task_maketag = new System.Threading.Thread(run3);
  118. t_task_maketag.IsBackground = true;
  119. t_task_maketag.Start();
  120. return true;
  121. }
  122. catch (Exception ex)
  123. {
  124. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, ex.Message);
  125. return false;
  126. }
  127. }
  128. public void stop()
  129. {
  130. if (!IsInit) return;
  131. try
  132. {
  133. IsInit = false;
  134. //timer.Elapsed -= Timer_Elapsed;
  135. preModelName = "";
  136. //释放模型
  137. if (detector != IntPtr.Zero)
  138. {
  139. DestroyDetector(detector);
  140. detector = IntPtr.Zero;
  141. }
  142. if (t_task != null)
  143. {
  144. bool b = t_task.Join(5000);
  145. if (!b) t_task.Abort();
  146. t_task = null;
  147. }
  148. if (t_task_operation != null)
  149. {
  150. bool b = t_task_operation.Join(5000);
  151. if (!b) t_task_operation.Abort();
  152. t_task_operation = null;
  153. }
  154. if (t_task_maketag != null)
  155. {
  156. bool b = t_task_maketag.Join(5000);
  157. if (!b) t_task_maketag.Abort();
  158. t_task_maketag = null;
  159. }
  160. taskList.Clear();
  161. taskOperationList.Clear();
  162. taskMakeTagList.Clear();
  163. }
  164. catch { }
  165. }
  166. /// <summary>
  167. ///
  168. /// </summary>
  169. /// <param name="sumWidth">多个相机图像总宽(外部去除重合部分)</param>
  170. /// <returns></returns>
  171. public int GetWidthForResize(int sumWidth)
  172. {
  173. int count =(int) Math.Round(sumWidth * 1.0f / image_width, 0);
  174. return count * image_width;
  175. //int count = sumWidth / image_width;
  176. ////int remainder = sumWidth % image_width;
  177. //if (count % 2 == 0)
  178. // return count * image_width;
  179. //else
  180. // return count * image_width+ image_width;
  181. }
  182. /// <summary>
  183. /// 保存图片
  184. /// </summary>
  185. /// <param name="Img"></param>图片
  186. /// <param name="pictureUrl"></param>保存路径
  187. /// <param name="pictureName"></param>保存名称
  188. private void SaveImage(Bitmap Img, string pictureUrl, string pictureName)
  189. {
  190. if (!Directory.Exists(pictureUrl))
  191. {
  192. Directory.CreateDirectory(pictureUrl);
  193. }
  194. FileInfo FileUrl = new FileInfo(pictureUrl);//防止路径中有日期导致路径错误
  195. try
  196. {
  197. using (Bitmap bitmap = new Bitmap(Img))
  198. {
  199. using (MemoryStream stream = new MemoryStream())
  200. {
  201. bitmap.Save(stream, ImageFormat.Bmp);
  202. System.Drawing.Image img = System.Drawing.Image.FromStream(stream);
  203. //img.Save(FileUrl +"\\"+ pictureName);
  204. //img.Dispose();
  205. string szURL = FileUrl + "\\" + pictureName;
  206. img.Save(szURL, ImageFormat.Bmp);
  207. img.Dispose();
  208. }
  209. }
  210. }
  211. catch (Exception)
  212. {
  213. if (Img != null)
  214. {
  215. Img.Dispose();
  216. }
  217. }
  218. }
  219. private void runStep()
  220. {
  221. int step = 0;
  222. while (IsInit)
  223. {
  224. if (taskList.Count < 1)
  225. {
  226. Thread.Sleep(0);
  227. continue;
  228. }
  229. //
  230. step = 1;
  231. var task = pop();
  232. try
  233. {
  234. if (task != null)
  235. {
  236. Stopwatch stopwatch = Stopwatch.StartNew();
  237. step =2;
  238. if (preModelName != task.modelName)
  239. {
  240. step = 3;
  241. //先释放模型
  242. if (detector != IntPtr.Zero)
  243. {
  244. step = 4;
  245. DestroyDetector(detector);
  246. detector = IntPtr.Zero;
  247. }
  248. step = 5;
  249. detector = CreateDetector($"./models/{task.modelName}");
  250. if (detector == IntPtr.Zero)
  251. throw new Exception($"模型({task.modelName})初始化失败!");
  252. step = 6;
  253. preModelName = task.modelName;
  254. }
  255. //源图
  256. //Bitmap bmp = yolo1.Read2Bmp(file_path);
  257. //切割图像,输入图像格式14208*10640
  258. stopwatch.Start();
  259. //task.resizeBmp = OpenCVUtil.resize( task.bmp.Clone(), task.resize.Width, task.resize.Height);//在外面已做了resize
  260. //Cv2.CvtColor(task.bmp, task.bmpBgr2rgb, ColorConversionCodes.BGR2RGB);
  261. //task.bmps_cut = OpenCVToCutsMat(task.bmpBgr2rgb, image_width, image_hight); //这里cut时之前加的clone
  262. step = 7;
  263. task.bmps_cut = OpenCVToCutsMat(task.bmp, image_width, image_hight); //这里cut时之前加的clone
  264. stopwatch.Stop();
  265. task.stopwatch[0] = stopwatch.ElapsedMilliseconds;
  266. //Resize图像
  267. //stopwatch.Restart();
  268. //task.bmps_resize = yolo1.OpenCVToResizesMat(task.bmps_cut, task.resize.Width, task.resize.Height);
  269. //stopwatch.Stop();
  270. //task.stopwatch[1] = stopwatch.ElapsedMilliseconds;
  271. //预处理模型
  272. //stopwatch.Restart();
  273. //task.tensors = yolo1.PreprocessImageMat(task.bmps_resize);
  274. //stopwatch.Stop();
  275. //task.stopwatch[2] = stopwatch.ElapsedMilliseconds;
  276. step = 8;
  277. lock (taskOperationList)
  278. {
  279. taskOperationList.Add(task);
  280. QueueCountEvent?.BeginInvoke(1, taskOperationList.Count, null, null);
  281. }
  282. step = 9;
  283. }
  284. }
  285. catch (Exception ex)
  286. {
  287. WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"DefectLib task1 err({step}):" + ex.Message);
  288. task.isSucceed = false;
  289. task.resultInfo = ex.Message;
  290. callback(task);
  291. }
  292. Thread.Sleep(5);
  293. }
  294. }
  295. //推理
  296. private void run2()
  297. {
  298. QualifiedLimit qualifiedLimit;
  299. while (IsInit)
  300. {
  301. if (taskOperationList.Count < 1)
  302. {
  303. Thread.Sleep(0);
  304. continue;
  305. }
  306. //
  307. var task = pop2();
  308. int cut_count=0,step = 0;
  309. try
  310. {
  311. if (task != null && task.bmps_cut.Count()>0)
  312. {
  313. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, "DefectLib tasks 运行推理...");
  314. cut_count = task.bmps_cut.Count();
  315. Stopwatch stopwatch = Stopwatch.StartNew();
  316. //====推理(必需单队列)
  317. stopwatch.Start();
  318. // 把数据转为byte数组,【h, w, c】的bgr格式,第一张在前,第二张在后
  319. byte[] imgData = new byte[image_bytes * cut_count];
  320. for (int i = 0; i < cut_count; i++)
  321. Marshal.Copy(task.bmps_cut[i].Data, imgData, image_bytes * i, image_bytes);
  322. step = 1;
  323. stopwatch.Stop();
  324. task.stopwatch[1] = stopwatch.ElapsedMilliseconds;
  325. stopwatch.Restart();
  326. task.output = new float[cut_count * detect_elem_size * detect_max_object_num];
  327. task.output_num = new int[cut_count];
  328. //执行推理
  329. step =2;
  330. bool ok = Detect(detector, ref imgData[0], cut_count, image_width, image_hight, image_channels,
  331. 0.25f, 0.45f, ref task.output[0], task.output.Length, ref task.output_num[0],Config.expand_pixel);
  332. //bool ok = Detect(_detector, ref imgData[0], imgs.Count, ImageWidth, image_hight, image_channels,
  333. // 0.25f, 0.45f, ref output[0], output.Length, ref output_num[0]);
  334. step = 3;
  335. stopwatch.Stop();
  336. task.stopwatch[2] = stopwatch.ElapsedMilliseconds;
  337. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"DefectLib tasks 结果推理={ok}");
  338. for (int i = 0; i < cut_count; i++)
  339. task.bmps_cut[i].Dispose();
  340. if (ok == false)
  341. throw new Exception($"推理失败或者输入数组太小({cut_count})");
  342. //
  343. lock (taskMakeTagList)
  344. {
  345. taskMakeTagList.Add(task);
  346. QueueCountEvent?.BeginInvoke(2, taskMakeTagList.Count, null, null);
  347. }
  348. }
  349. }
  350. catch (Exception ex)
  351. {
  352. WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"DefectLib task2 err({step}):({cut_count}){ ex.Message}");
  353. task.isSucceed = false;
  354. task.resultInfo = ex.Message;
  355. callback(task);
  356. }
  357. Thread.Sleep(5);
  358. }
  359. }
  360. private class DefectLabelInfo
  361. {
  362. public int x { get; set; }
  363. public int y { get; set; }
  364. public int w { get; set; }
  365. public int h { get; set; }
  366. public int classId { get; set; }
  367. public double confidence { get; set; } //置信度
  368. public double contrast { get; set; }//对比度
  369. public double cmW { get; set; }
  370. public double cmH { get; set; }
  371. public int i { get; set; }//小图index
  372. public int j { get; set; }//缺陷index
  373. }
  374. private double ContrastLow = 0.8;
  375. private double ContrastTop = 1.2;
  376. //private double ContrastToPercent(double val)
  377. //{
  378. // if (val < ContrastLow)
  379. // return 0;
  380. // else if (val > ContrastTop)
  381. // return 100;
  382. // double temp = 100 / (ContrastTop - ContrastLow);
  383. // return temp * (val - ContrastLow);
  384. //}
  385. //private double PercentToContrast(double val)
  386. //{
  387. // double temp = val * (ContrastTop - ContrastLow);
  388. // return temp + ContrastLow;
  389. //}
  390. private double ContrastToPercent(double val)
  391. {
  392. if (val < ContrastLow)
  393. return 0;
  394. else if (val > ContrastTop)
  395. return 100;
  396. double temp = 100 / (ContrastTop - ContrastLow);
  397. return Math.Round(temp * (val - ContrastLow), 2);
  398. }
  399. private double PercentToContrast(double val)
  400. {
  401. double tt = 1;
  402. if (val > 100)
  403. tt = 100;
  404. else if (val < 0)
  405. tt = 0;
  406. else
  407. tt = val;
  408. double temp = tt / 100 * (ContrastTop - ContrastLow);
  409. return temp + ContrastLow;
  410. }
  411. private List<DefectLabelInfo> HeBingDefect(int Width, List<DefectLabelInfo> DefectLabelInfoList)
  412. {
  413. List<DefectLabelInfo> outList = new List<DefectLabelInfo>();
  414. List<DefectLabelInfo> HeBingList = new List<DefectLabelInfo>();
  415. List<DefectLabelInfo> XcHeBingList = new List<DefectLabelInfo>();
  416. List<int> xPos = new List<int>();
  417. List<double> ZXD = new List<double>();
  418. List<DefectLabelInfo> HeBingList2 = new List<DefectLabelInfo>();
  419. List<DefectLabelInfo> XcHeBingList2 = new List<DefectLabelInfo>();
  420. List<int> xPos2 = new List<int>();
  421. List<double> ZXD2 = new List<double>();
  422. DefectLabelInfo stpoint = DefectLabelInfoList[0];
  423. int colNum = Width / image_width;
  424. //寻找在一条线上
  425. for (int q = 0; q < DefectLabelInfoList.Count; q++)
  426. {
  427. if (Config.getDefectCode(DefectLabelInfoList[q].classId) == "jietou")
  428. {
  429. int max = stpoint.y + 500;
  430. int min = stpoint.y - 500 > 0? stpoint.y - 500:0;
  431. if (DefectLabelInfoList[q].y >= min && DefectLabelInfoList[q].y <= max)
  432. {
  433. HeBingList.Add(DefectLabelInfoList[q]);
  434. xPos.Add(DefectLabelInfoList[q].x);
  435. ZXD.Add(DefectLabelInfoList[q].confidence);
  436. }
  437. else
  438. XcHeBingList.Add(DefectLabelInfoList[q]);
  439. }
  440. else if (Config.getDefectCode(DefectLabelInfoList[q].classId) == "hengdang")
  441. {
  442. int max = stpoint.y + 500;
  443. int min = stpoint.y - 500 > 0 ? stpoint.y - 500 : 0;
  444. if (DefectLabelInfoList[q].y >= min && DefectLabelInfoList[q].y <= max)
  445. {
  446. HeBingList2.Add(DefectLabelInfoList[q]);
  447. xPos2.Add(DefectLabelInfoList[q].x);
  448. ZXD2.Add(DefectLabelInfoList[q].confidence);
  449. }
  450. else
  451. XcHeBingList2.Add(DefectLabelInfoList[q]);
  452. }
  453. else
  454. outList.Add(DefectLabelInfoList[q]);
  455. }
  456. //递归下次合并数据
  457. List<DefectLabelInfo> dg1 = new List<DefectLabelInfo>();
  458. List<DefectLabelInfo> dg2 = new List<DefectLabelInfo>();
  459. if (XcHeBingList.Count >0)
  460. dg1 = HeBingDefect(Width, XcHeBingList);
  461. if (XcHeBingList2.Count > 0)
  462. dg2 = HeBingDefect(Width, XcHeBingList2);
  463. //多个jietou合并
  464. if (HeBingList.Count>0)
  465. {
  466. var stIt = HeBingList.Find(x => x.x == xPos.Min());
  467. var edIt = HeBingList.Find(x => x.x == xPos.Max());
  468. var eZXD = HeBingList.Find(x => x.confidence == ZXD.Max());
  469. int newW = Math.Abs(((edIt.i % colNum) * image_width + edIt.x) - ((stIt.i % colNum) * image_width + stIt.x)) + edIt.w;
  470. outList.Add(new DefectLabelInfo() {
  471. x=stIt.x,
  472. y=edIt.y,
  473. w = newW, //多图叠加
  474. h = edIt.h,
  475. classId = eZXD.classId,
  476. confidence = eZXD.confidence,
  477. contrast = eZXD.contrast,
  478. cmH = Math.Round(edIt.h * 1.0 / Config.cm2px_y, 2),
  479. cmW = Math.Round(newW * 1.0 / Config.cm2px_x, 2),
  480. i = stIt.i,
  481. j = stIt.j,
  482. });
  483. }
  484. //多个hengdang合并
  485. if (HeBingList2.Count > 0)
  486. {
  487. var stIt = HeBingList2.Find(x => x.x == xPos2.Min());
  488. var edIt = HeBingList2.Find(x => x.x == xPos2.Max());
  489. var eZXD = HeBingList2.Find(x => x.confidence == ZXD2.Max());
  490. int newW = Math.Abs(((edIt.i % colNum) * image_width + edIt.x) - ((stIt.i % colNum) * image_width + stIt.x)) + edIt.w;
  491. outList.Add(new DefectLabelInfo()
  492. {
  493. x = stIt.x,
  494. y = edIt.y,
  495. w = newW, //多图叠加
  496. h = edIt.h,
  497. classId = eZXD.classId,
  498. confidence = eZXD.confidence,
  499. contrast = eZXD.contrast,
  500. cmH = Math.Round(edIt.h * 1.0 / Config.cm2px_y, 2),
  501. cmW = Math.Round(newW * 1.0 / Config.cm2px_x, 2),
  502. i = stIt.i,
  503. j = stIt.j,
  504. });
  505. }
  506. outList = outList.Concat(dg1).ToList<DefectLabelInfo>();//保留重复项
  507. outList = outList.Concat(dg2).ToList<DefectLabelInfo>();//保留重复项
  508. return outList;
  509. }
  510. //打标
  511. private void run3()
  512. {
  513. QualifiedLimit qualifiedLimit;
  514. while (IsInit)
  515. {
  516. if (taskMakeTagList.Count < 1)
  517. {
  518. Thread.Sleep(0);
  519. continue;
  520. }
  521. //
  522. var task = pop3();
  523. int liStep = 0;
  524. try
  525. {
  526. Stopwatch stopwatch = Stopwatch.StartNew();
  527. stopwatch.Restart();
  528. int cut_count = task.bmps_cut.Count();//上面bmps_cut已销毁
  529. int colNum = task.bmp.Width / image_width;
  530. int rowNum = task.bmp.Height / image_hight;
  531. int count = 0;
  532. liStep = 3;
  533. //车用革去除接头处横档误判
  534. bool haveJieTou = false;
  535. List<DefectLabelInfo> DefectLabelInfoList = new List<DefectLabelInfo>();
  536. for (int i = 0; i < cut_count; i++)
  537. {
  538. liStep = i * 100;
  539. //task.resultInfo += $"第 {i}/{cut_count} 张小图(大图索引{task.photoIndex}): 缺陷数 = {task.output_num[i]}\n";
  540. //task.resultInfo +=$"大图({task.tag})[{task.bmp.Width}*{task.bmp.Height}],第 {i + 1}/{cut_count} 张小图[{task.bmps_cut[i].Width}*{task.bmps_cut[i].Height}]: 瑕疵output_num = {output_num[i]}\n";
  541. #region 检测信息汇总
  542. for (int j = 0; j < task.output_num[i]; j++)//缺陷数
  543. {
  544. liStep += j;//0
  545. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"-------");
  546. int index = count * detect_elem_size;
  547. // 打印输出信息(示例代码,根据实际情况进行修改和格式化)
  548. // 获取输出信息
  549. int x = (int)task.output[index];
  550. int y = (int)task.output[index + 1];
  551. int w = (int)task.output[index + 2];
  552. int h = (int)task.output[index + 3];
  553. int classId = (int)task.output[index + 4];
  554. double confidence = Math.Round(task.output[index + 5], 2); //置信度
  555. double contrast = Math.Round(task.output[index + 6], 3);//对比度
  556. //y = image_hight-y-h;//转到右下角为原点
  557. count++;
  558. //var cmW = Math.Round(w * task.widthRatio / Config.cm2px_x, 2);
  559. //var cmH = Math.Round(h * task.widthRatio / Config.cm2px_y, 2);
  560. var cmW = Math.Round(w * 1.0 / Config.cm2px_x, 2);
  561. var cmH = Math.Round(h * 1.0 / Config.cm2px_y, 2);
  562. // 打印输出信息
  563. //task.resultInfo += $"----{i}----col:{i % colNum}/{colNum} row:{i / colNum}/{colNum}-----------\n目标:{j + 1} 类别ID:{classId} 置信度:{confidence} 对比度:{contrast} 坐标:({x},{y})-({x + w},{y + h}) 宽高:w={w},h={h}; \n";
  564. DefectLabelInfoList.Add(new DefectLabelInfo()
  565. {
  566. x = (int)task.output[index],
  567. y = (int)task.output[index + 1],
  568. w = (int)task.output[index + 2],
  569. h = (int)task.output[index + 3],
  570. classId = (int)task.output[index + 4],
  571. confidence = Math.Round(task.output[index + 5], 2), //置信度
  572. contrast = ContrastToPercent( Math.Round(task.output[index + 6], 3)),//对比度
  573. //cmW = Math.Round(w * task.widthRatio / Config.cm2px_x, 2),
  574. //cmH = Math.Round(h * task.widthRatio / Config.cm2px_y, 2),
  575. cmW = Math.Round(w * 1.0 / Config.cm2px_x, 2),
  576. cmH = Math.Round(h * 1.0 / Config.cm2px_y, 2),
  577. i = i,
  578. j = j,
  579. });
  580. }
  581. #endregion
  582. #if false
  583. for (int j = 0; j < task.output_num[i]; j++)//缺陷数
  584. {
  585. liStep += j;//0
  586. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"-------");
  587. int index = count * detect_elem_size;
  588. // 打印输出信息(示例代码,根据实际情况进行修改和格式化)
  589. // 获取输出信息
  590. int x = (int)task.output[index];
  591. int y = (int)task.output[index + 1];
  592. int w = (int)task.output[index + 2];
  593. int h = (int)task.output[index + 3];
  594. int classId = (int)task.output[index + 4];
  595. double confidence = Math.Round(task.output[index + 5],2); //置信度
  596. double contrast = Math.Round(task.output[index + 6], 3);//对比度
  597. //y = image_hight-y-h;//转到右下角为原点
  598. count++;
  599. var cmW = Math.Round(w * task.widthRatio / Config.cm2px_x, 2);
  600. var cmH = Math.Round(h * task.widthRatio / Config.cm2px_y, 2);
  601. // 打印输出信息
  602. task.resultInfo += $"----{i}----col:{i % colNum}/{colNum} row:{i / colNum}/{colNum}-----------\n目标:{j + 1} 类别ID:{classId} 置信度:{confidence} 对比度:{contrast} 坐标:({x},{y})-({x + w},{y + h}) 宽高:w={w},h={h}; \n";
  603. //是否满足此产品标准
  604. if (task.qualifiedLimitList != null && task.qualifiedLimitList.Count > 0)
  605. {
  606. qualifiedLimit = task.qualifiedLimitList.FirstOrDefault(m => m.Code == Config.getDefectCode(classId));
  607. if (qualifiedLimit != null)
  608. {
  609. //if ((qualifiedLimit.ZXD > 0 && qualifiedLimit.ZXD > confidence)
  610. // || (qualifiedLimit.ContrastTop + qualifiedLimit.ContrastLower > 0 && x> qualifiedLimit.ContrastLower && x < qualifiedLimit.ContrastTop)
  611. // || (qualifiedLimit.Area > 0 && qualifiedLimit.Area > cmW * cmH))
  612. if (confidence <= qualifiedLimit.ZXD)//confidence > qualifiedLimit.ZXD 是瑕疵 才继续判断下面的两个条件
  613. {
  614. task.resultInfo += $" 置信度不满足此产品瑕疵标准,跳过! \n";
  615. continue;
  616. }
  617. //下限<对比度<上限:不是瑕疵
  618. var ContrastTotal = qualifiedLimit.ContrastTop + qualifiedLimit.ContrastLower;
  619. if (qualifiedLimit.IsOR)
  620. {
  621. if (!(
  622. (qualifiedLimit.Area <= 0 || cmW * cmH >= qualifiedLimit.Area) ||
  623. (ContrastTotal <= 0 || (contrast < qualifiedLimit.ContrastLower || contrast > qualifiedLimit.ContrastTop))))
  624. {
  625. task.resultInfo += $" 不满足此产品瑕疵标准,跳过! \n";
  626. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"判断不是瑕疵:类别ID:{classId}; 置信度({confidence},[{qualifiedLimit.ZXD}]); isOr({qualifiedLimit.IsOR}); 面积({cmW * cmH},[{ qualifiedLimit.Area}]); 对比度({contrast},[{qualifiedLimit.ContrastLower}-{qualifiedLimit.ContrastTop}])");
  627. continue;
  628. }
  629. }
  630. else
  631. {
  632. if (!(
  633. (qualifiedLimit.Area<=0 || cmW * cmH >= qualifiedLimit.Area) &&
  634. (ContrastTotal <=0 || (contrast < qualifiedLimit.ContrastLower || contrast > qualifiedLimit.ContrastTop))))
  635. {
  636. task.resultInfo += $" 不满足此产品瑕疵标准,跳过! \n";
  637. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"判断不是瑕疵:类别ID:{classId}; 置信度({confidence},[{qualifiedLimit.ZXD}]); isOr({qualifiedLimit.IsOR}); 面积({cmW * cmH},[{ qualifiedLimit.Area}]); 对比度({contrast},[{qualifiedLimit.ContrastLower}-{qualifiedLimit.ContrastTop}])");
  638. continue;
  639. }
  640. }
  641. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"判断是瑕疵:类别ID:{classId}; 置信度({confidence},[{qualifiedLimit.ZXD}]); isOr({qualifiedLimit.IsOR}); 面积({cmW * cmH},[{ qualifiedLimit.Area}]); 对比度({contrast},[{qualifiedLimit.ContrastLower}-{qualifiedLimit.ContrastTop}])");
  642. }
  643. }
  644. liStep++;//1
  645. //打标
  646. var point1 = new OpenCvSharp.Point((i % colNum) * image_width + x, (i / colNum) * image_hight + y);
  647. var point2 = new OpenCvSharp.Point(point1.X + w, point1.Y + h);
  648. liStep++;//2
  649. task.resultInfo += $" 转换到大图坐标(px):p1={point1.X},{point1.Y}; p2={point2.X},{point2.Y}\n";
  650. Cv2.Rectangle(task.bmpTag, point1, point2, new Scalar(0.0, 0.0, 255.0), 1);//画打标点
  651. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"保存第 {count} 行缺陷信息;");
  652. var cmX = Math.Round(point1.X * task.widthRatio / Config.cm2px_x, 2);
  653. var cmY = Math.Round((task.bmp.Height-point1.Y-h) * task.widthRatio / Config.cm2px_y, 2);//外面计Y从右下角为原点
  654. liStep++;//3
  655. task.resultInfo += $" 转换到大图坐标(cm)[widthRatio={task.widthRatio}]:x={cmX},y={cmY}; w={cmW},h={cmH}\n";
  656. task.excelTable.Rows.Add($"{task.photoIndex}", cmX, cmY, cmW, cmH, j + 1, classId, confidence, contrast);
  657. liStep++;//4
  658. //切缺陷小图
  659. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"保存第 {count} 个缺陷小图;");
  660. int left, top, decX, decY;
  661. decX = (w > 236 ? 20 : 256 - w) / 2;
  662. decY = (h > 236 ? 20 : 256 - h) / 2;
  663. left = point1.X - decX;
  664. top = point1.Y - decY;
  665. if (left < 0) left = 0;
  666. if (top < 0) top = 0;
  667. int width = w + decX * 2;
  668. int height = h + decY * 2;
  669. if (left + width > task.bmp.Width - 1) width = task.bmp.Width - left - 1;
  670. if (top + height > task.bmp.Height - 1) height = task.bmp.Height - top - 1;
  671. liStep++;//5
  672. Rect roi = new Rect(left, top, width, height);
  673. liStep++;//6
  674. if (height < 1 || width < 1)
  675. {
  676. task.resultInfo += $" 打标到大图坐标Rect(px):left={left},top={top}; width={width},height={height}\n";
  677. task.resultInfo += $" test point1.Y={point1.Y},h={h}; top={top},mat.Height={ task.bmp.Height}\n================\n";
  678. WarningEvent?.Invoke(DateTime.Now,WarningEnum.Normal, task.resultInfo);
  679. }
  680. //保存
  681. //string filename = $"{Config.appBasePath}\\temp\\{task.tag}\\{task.tag}_X{mmX.ToString()}_Y{mmY.ToString()}_W{mmW.ToString()}_H{mmH.ToString()}_目标{j + 1}_类别{classId}_置信度{confidence}.bmp";
  682. //OpenCvSharp.Extensions.BitmapConverter.ToBitmap(new Mat(task.bmp, roi)).Save(filename, ImageFormat.Jpeg);
  683. task.lstDefectBmp.Add(new Mat(task.bmpTag, roi).Clone());
  684. liStep++;//7
  685. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"缺陷小图数量:{task.lstDefectBmp.Count}");
  686. }
  687. #endif
  688. }
  689. #region 合并接头横档
  690. liStep++;
  691. if (DefectLabelInfoList.Count >0)
  692. DefectLabelInfoList = HeBingDefect(task.bmp.Width, DefectLabelInfoList);
  693. liStep++;
  694. #endregion
  695. //结果过滤
  696. #region 结果过滤
  697. //降序排序,先得到是否有接头检出
  698. List<DefectLabelInfo> DefectLabelInfoListByClassID = DefectLabelInfoList.OrderByDescending(t => t.classId).ToList();//降序
  699. for (int q = 0; q < DefectLabelInfoListByClassID.Count; q++)
  700. {
  701. //是否满足此产品标准
  702. if (task.qualifiedLimitList != null && task.qualifiedLimitList.Count > 0)
  703. {
  704. qualifiedLimit = task.qualifiedLimitList.FirstOrDefault(m => m.Code == Config.getDefectCode(DefectLabelInfoListByClassID[q].classId));
  705. if (qualifiedLimit != null)
  706. {
  707. // 打印输出信息
  708. task.resultInfo += $"----{DefectLabelInfoListByClassID[q].i}----col:{DefectLabelInfoListByClassID[q].i % colNum}/{colNum} row:{DefectLabelInfoListByClassID[q].i / colNum}/{colNum}-----------\n目标:{DefectLabelInfoListByClassID[q].j + 1} 类别ID:{DefectLabelInfoListByClassID[q].classId} 置信度:{DefectLabelInfoListByClassID[q].confidence} 对比度:{DefectLabelInfoListByClassID[q].contrast}\n";
  709. //if ((qualifiedLimit.ZXD > 0 && qualifiedLimit.ZXD > confidence)
  710. // || (qualifiedLimit.ContrastTop + qualifiedLimit.ContrastLower > 0 && x> qualifiedLimit.ContrastLower && x < qualifiedLimit.ContrastTop)
  711. // || (qualifiedLimit.Area > 0 && qualifiedLimit.Area > cmW * cmH))
  712. if (DefectLabelInfoListByClassID[q].confidence <= qualifiedLimit.ZXD)//confidence > qualifiedLimit.ZXD 是瑕疵 才继续判断下面的两个条件
  713. {
  714. task.resultInfo += $" 置信度不满足此产品瑕疵标准,跳过! \n";
  715. continue;
  716. }
  717. //下限<对比度<上限:不是瑕疵
  718. var ContrastTotal = qualifiedLimit.ContrastTop + qualifiedLimit.ContrastLower;
  719. if (qualifiedLimit.IsOR)
  720. {
  721. //if (!(
  722. // (ContrastTotal <= 0 || (PercentToContrast(DefectLabelInfoListByClassID[q].contrast) < qualifiedLimit.ContrastLower || PercentToContrast(DefectLabelInfoListByClassID[q].contrast) > qualifiedLimit.ContrastTop))))
  723. //{
  724. // task.resultInfo += $" 不满足此产品瑕疵标准,跳过! \n";
  725. // //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"判断不是瑕疵:类别ID:{classId}; 置信度({confidence},[{qualifiedLimit.ZXD}]); isOr({qualifiedLimit.IsOR}); 面积({cmW * cmH},[{ qualifiedLimit.Area}]); 对比度({contrast},[{qualifiedLimit.ContrastLower}-{qualifiedLimit.ContrastTop}])");
  726. // continue;
  727. //}
  728. }
  729. else
  730. {
  731. if (!(ContrastTotal <= 0 || (PercentToContrast(DefectLabelInfoListByClassID[q].contrast) < qualifiedLimit.ContrastLower || PercentToContrast(DefectLabelInfoListByClassID[q].contrast) > qualifiedLimit.ContrastTop)))
  732. {
  733. task.resultInfo += $" 不满足此产品瑕疵标准,跳过! \n";
  734. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"判断不是瑕疵:类别ID:{classId}; 置信度({confidence},[{qualifiedLimit.ZXD}]); isOr({qualifiedLimit.IsOR}); 面积({cmW * cmH},[{ qualifiedLimit.Area}]); 对比度({contrast},[{qualifiedLimit.ContrastLower}-{qualifiedLimit.ContrastTop}])");
  735. continue;
  736. }
  737. }
  738. if(qualifiedLimit.Area > 0 && DefectLabelInfoListByClassID[q].cmW * DefectLabelInfoListByClassID[q].cmH < qualifiedLimit.Area)
  739. {
  740. task.resultInfo += $" 不满足此产品瑕疵标准面积,跳过! \n";
  741. continue;
  742. }
  743. if (Config.getDefectCode(DefectLabelInfoListByClassID[q].classId) == "jietou")
  744. haveJieTou = true;
  745. if(haveJieTou && (Config.getDefectCode(DefectLabelInfoListByClassID[q].classId) == "hengdang"))
  746. {
  747. task.resultInfo += $" 判断为接头处横档,跳过! \n";
  748. continue;
  749. }
  750. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"判断是瑕疵:类别ID:{classId}; 置信度({confidence},[{qualifiedLimit.ZXD}]); isOr({qualifiedLimit.IsOR}); 面积({cmW * cmH},[{ qualifiedLimit.Area}]); 对比度({contrast},[{qualifiedLimit.ContrastLower}-{qualifiedLimit.ContrastTop}])");
  751. }
  752. }
  753. liStep++;//1
  754. //打标
  755. var point1 = new OpenCvSharp.Point((DefectLabelInfoListByClassID[q].i % colNum) * image_width + DefectLabelInfoListByClassID[q].x, (DefectLabelInfoListByClassID[q].i / colNum) * image_hight + DefectLabelInfoListByClassID[q].y);
  756. var point2 = new OpenCvSharp.Point(point1.X + DefectLabelInfoListByClassID[q].w, point1.Y + DefectLabelInfoListByClassID[q].h);
  757. liStep++;//2
  758. //task.resultInfo += $" 转换到大图坐标(px):p1={point1.X},{point1.Y}; p2={point2.X},{point2.Y}\n";
  759. Cv2.Rectangle(task.bmpTag, point1, point2, new Scalar(0.0, 0.0, 255.0), 1);//画打标点
  760. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"保存第 {count} 行缺陷信息;");
  761. int px = (point1.X - task.xw) > 0 ? (point1.X - task.xw) : 0;
  762. //var cmX = Math.Round(px * task.widthRatio / Config.cm2px_x, 2);
  763. var cmX = Math.Round((double)px / Config.cm2px_x, 2);
  764. //var cmY = Math.Round((task.bmp.Height - point1.Y - DefectLabelInfoListByClassID[q].h) * task.widthRatio / Config.cm2px_y, 2);//外面计Y从右下角为原点
  765. var cmY = Math.Round((task.bmp.Height - point1.Y - DefectLabelInfoListByClassID[q].h) * 1.0 / Config.cm2px_y, 2);//外面计Y从右下角为原点
  766. liStep++;//3
  767. //task.resultInfo += $" 转换到大图坐标(cm)[widthRatio={task.widthRatio}]:x={cmX},y={cmY}; w={DefectLabelInfoList[q].cmW},h={DefectLabelInfoList[q].cmH}\n";
  768. task.excelTable.Rows.Add($"{task.photoIndex}", cmX, cmY, DefectLabelInfoListByClassID[q].cmW, DefectLabelInfoListByClassID[q].cmH, DefectLabelInfoListByClassID[q].j + 1, DefectLabelInfoListByClassID[q].classId, DefectLabelInfoListByClassID[q].confidence, DefectLabelInfoListByClassID[q].contrast);
  769. liStep++;//4
  770. //切缺陷小图
  771. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"保存第 {count} 个缺陷小图;");
  772. int left, top, decX, decY;
  773. decX = (DefectLabelInfoListByClassID[q].w > 236 ? 20 : 256 - DefectLabelInfoListByClassID[q].w) / 2;
  774. decY = (DefectLabelInfoListByClassID[q].h > 236 ? 20 : 256 - DefectLabelInfoListByClassID[q].h) / 2;
  775. left = point1.X - decX;
  776. top = point1.Y - decY;
  777. if (left < 0) left = 0;
  778. if (top < 0) top = 0;
  779. int width = DefectLabelInfoListByClassID[q].w + decX * 2;
  780. int height = DefectLabelInfoListByClassID[q].h + decY * 2;
  781. if (left + width > task.bmp.Width - 1) width = task.bmp.Width - left - 1;
  782. if (top + height > task.bmp.Height - 1) height = task.bmp.Height - top - 1;
  783. liStep++;//5
  784. Rect roi = new Rect(left, top, width, height);
  785. liStep++;//6
  786. if (height < 1 || width < 1)
  787. {
  788. //task.resultInfo += $" 打标到大图坐标Rect(px):left={left},top={top}; width={width},height={height}\n";
  789. //task.resultInfo += $" test point1.Y={point1.Y},h={DefectLabelInfoList[q].h}; top={top},mat.Height={task.bmp.Height}\n================\n";
  790. WarningEvent?.Invoke(DateTime.Now, WarningEnum.Normal, task.resultInfo);
  791. }
  792. //保存
  793. //string filename = $"{Config.appBasePath}\\temp\\{task.tag}\\{task.tag}_X{mmX.ToString()}_Y{mmY.ToString()}_W{mmW.ToString()}_H{mmH.ToString()}_目标{j + 1}_类别{classId}_置信度{confidence}.bmp";
  794. //OpenCvSharp.Extensions.BitmapConverter.ToBitmap(new Mat(task.bmp, roi)).Save(filename, ImageFormat.Jpeg);
  795. task.lstDefectBmp.Add(new Mat(task.bmpTag, roi).Clone());
  796. liStep++;//7
  797. }
  798. #endregion
  799. liStep = 99;
  800. stopwatch.Stop();
  801. task.stopwatch[3] = stopwatch.ElapsedMilliseconds;
  802. task.isSucceed = true;
  803. callback(task);
  804. }
  805. catch (Exception ex)
  806. {
  807. WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"DefectLib task3 err({liStep}):" + ex.Message);
  808. task.isSucceed = false;
  809. task.resultInfo = ex.Message;
  810. callback(task);
  811. }
  812. Thread.Sleep(5);
  813. }
  814. }
  815. private void callback(DefectTask task)
  816. {
  817. //返回成功/失败,异步调用
  818. if (task.finishEvent != null || (task.finishEvent = finishEvent) != null)
  819. //task.finishEvent.BeginInvoke(result, errInfo, res => task.finishEvent.EndInvoke(res), null);
  820. System.Threading.ThreadPool.QueueUserWorkItem(waitCallback, task);
  821. }
  822. //异步回调
  823. WaitCallback waitCallback = new WaitCallback(o =>
  824. {
  825. var task = (DefectTask)o;
  826. task.finishEvent(task);
  827. });
  828. /// <summary>
  829. /// 切割(先左右,后上下)
  830. /// </summary>
  831. /// <param name="mat"></param>
  832. /// <param name="width"></param>
  833. /// <param name="height"></param>
  834. /// <returns></returns>
  835. private Mat[] OpenCVToCutsMat(Mat mat, int width, int height)
  836. {
  837. Mat[] array = new Mat[mat.Width / width * mat.Height / height];
  838. int num = 0;
  839. for (int i = 0; i < mat.Height / height; i++)
  840. {
  841. for (int j = 0; j < mat.Width / width; j++)
  842. {
  843. int x = j * width;
  844. int y = i * height;
  845. System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle(x, y, width, height);
  846. Rect roi = new Rect(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
  847. array[num] = new Mat(mat, roi).Clone();
  848. num++;
  849. }
  850. }
  851. return array;
  852. }
  853. public class DefectTask
  854. {
  855. public DefectTask()
  856. {
  857. // 创建一个 DataTable 对象来存储数据
  858. excelTable = new DataTable("MyData");
  859. // 添加列到 DataTable
  860. excelTable.Columns.Add("FileName", typeof(string));
  861. excelTable.Columns.Add("X", typeof(decimal));
  862. excelTable.Columns.Add("Y", typeof(decimal));
  863. excelTable.Columns.Add("W", typeof(decimal));
  864. excelTable.Columns.Add("H", typeof(decimal));
  865. excelTable.Columns.Add("目标", typeof(int));
  866. excelTable.Columns.Add("类别", typeof(int));
  867. excelTable.Columns.Add("置信度", typeof(decimal));
  868. excelTable.Columns.Add("对比度", typeof(decimal));
  869. // 向 DataTable 中添加数据行
  870. //excelTable.Rows.Add("John Doe", 30);
  871. //excelTable.Rows.Add("Jane Smith", 25);
  872. }
  873. /// <summary>
  874. /// 模型名字
  875. /// </summary>
  876. public string modelName;
  877. public Models.Records record;
  878. //public string bmpPath;//源图路径(仅目录)
  879. /// <summary>
  880. /// 源图(resize后的)
  881. /// </summary>
  882. public Mat bmp;
  883. //public Mat bmpBgr2rgb=new Mat();
  884. public System.Drawing.Size resize = new System.Drawing.Size(224, 224);
  885. //public Mat resizeBmp;//resize后 BGR2RGB图,只用于识别
  886. public Mat bmpTag;
  887. /// <summary>
  888. /// 图片索引0-n
  889. /// </summary>
  890. public int photoIndex;//excel中对应的图像路径标识
  891. public float widthRatio;//宽度比例,resize前/resize后
  892. //切割后
  893. public Mat[] bmps_cut;
  894. //用于比对参数 }//置信度 面积 对比度
  895. public List<QualifiedLimit> qualifiedLimitList;
  896. //推理后结果用于打标
  897. public float[] output;
  898. public int[] output_num;
  899. //
  900. /// <summary>
  901. /// 完成后回调
  902. /// </summary>
  903. public Action<DefectTask> finishEvent;
  904. //==结果返回
  905. public bool isSucceed;//转换是否成功
  906. public string resultInfo = "";//成功或失败信息
  907. public List<Mat> lstDefectBmp=new List<Mat>();
  908. /// <summary>
  909. /// fileIndex,x_mm,y_mm,w_mm,h_mm,目标,类别ID,置信度
  910. /// </summary>
  911. public DataTable excelTable=new DataTable();
  912. public long[] stopwatch = new long[4];
  913. public int xw;
  914. }
  915. public void add(DefectTask task)
  916. {
  917. lock (taskList)
  918. {
  919. taskList.Add(task);
  920. QueueCountEvent?.BeginInvoke(0, taskList.Count, null, null);
  921. }
  922. }
  923. private DefectTask pop()
  924. {
  925. lock (taskList)
  926. {
  927. if (taskList.Count < 1)
  928. return null;
  929. //int index = 0;// taskList.FindIndex(p => { return p.isSync; });
  930. //if (index < 0) index = 0;
  931. var task = taskList[0];
  932. taskList.RemoveAt(0);
  933. QueueCountEvent?.BeginInvoke(0, taskList.Count, null, null);
  934. return task;
  935. }
  936. }
  937. private DefectTask pop2()
  938. {
  939. lock (taskOperationList)
  940. {
  941. if (taskOperationList.Count < 1)
  942. return null;
  943. //int index = 0;// taskList.FindIndex(p => { return p.isSync; });
  944. //if (index < 0) index = 0;
  945. var task = taskOperationList[0];
  946. taskOperationList.RemoveAt(0);
  947. QueueCountEvent?.BeginInvoke(1, taskOperationList.Count, null, null);
  948. return task;
  949. }
  950. }
  951. private DefectTask pop3()
  952. {
  953. lock (taskMakeTagList)
  954. {
  955. if (taskMakeTagList.Count < 1)
  956. return null;
  957. //int index = 0;// taskList.FindIndex(p => { return p.isSync; });
  958. //if (index < 0) index = 0;
  959. var task = taskMakeTagList[0];
  960. taskMakeTagList.RemoveAt(0);
  961. QueueCountEvent?.BeginInvoke(2, taskMakeTagList.Count, null, null);
  962. return task;
  963. }
  964. }
  965. public void Dispose()
  966. {
  967. stop();
  968. }
  969. }
  970. }