Blame view

OS.Spin/OS.Spin.BusinessLayer/MainBusiness/FlawDetectionBl.cs 26 KB
8ca6e89d   Tuo Wenbo   20211021
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
  using OpenCvSharp;
  using OS.Spin.BusinessLayer.SubBusiness;
  using OS.Spin.Common;
  using OS.Spin.Common.Files;
  using OS.Spin.Common.MultiThread;
  using OS.Spin.Modle.BusinessLayer;
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Runtime.InteropServices;
  using System.Threading;
  using static OS.Spin.Modle.Sdk.StructInfos;
  
  namespace OS.Spin.BusinessLayer.MainBusiness
  {
      public sealed class FlawDetectionBl
      {
          #region 变量
          private int _cameraCount = 0;
          private List<CameraBl> _cameras = new List<CameraBl>();
          private List<DetectionBl> _detections = new List<DetectionBl>();
          private Thread _runThread;
          private SemaphorePool _semaphorePool;
          private string _classId = string.Empty;
          private int _imageId = 0;
          private int _reallyImageId = 0;
          private int _finishedCameraCount = 0;
          private IntPtr _initHandle = new IntPtr(0);
          private IntPtr _handle = new IntPtr(1);
          private const int RS_FACTOR = 1;
          private const int ROI_WIDTH = 500;
          private const int ROI_HEIGHT = 250;
          public delegate void WindowsControl(int cmd);
          public WindowsControl TlWorker;
          private IntPtr _handle_5 = new IntPtr(5);
  
          private IntPtr _handle_37 = new IntPtr(37);
  
          private IntPtr _handle_h = new IntPtr(12);
          private IntPtr _handle_v = new IntPtr(22);
          private IntPtr _handle_proc = new IntPtr(32);
  
          private Modle.Sdk.StructInfos.FinalResults[] label_poolarray = new Modle.Sdk.StructInfos.FinalResults[100];
          private Modle.Sdk.StructInfos.FinalResults[] final_labelout = new Modle.Sdk.StructInfos.FinalResults[16];
          //private int pool_size = 0;
  
          private int _gainValue = 0;
  
          private bool _isSetGain = false;
  
          private int current_meter = 0;
          //private MachineStopBl _stopBl = null;
          //private MaxSmallTransferBl _transferBl = null;
          private bool _canRecived = true;
          //private string[] _lableNames = new[] { "背景", "停车痕(紧)", "停车痕(松)", "断经", "错花", "并纬", "缩纬", "缺纬", "糙纬", "折返", "断纬",
          //    "油污", "浆斑", "污经","经条", "擦白", "擦伤","空织","破洞","紧经","污纬","皱印","上首破边","下首破边", "刮伤", "纬密变化","蛛网","挡车工标记","毛纱、线头","起皱","水印","水波纹", "其他" };
          private string[] _lableNames = new[] { "背景","棉花","大棉团","横向折痕","经向折痕","小竹节","杂物","棉球","结头","破洞","拖纱","断疵","跳花","云织","经竹节","经缩","粗经","经向异纤","起圈纬缩","纬竹节","纬缩",
              "松纬缩","纬向异纤","断经_黑","断经_亮","松经","稀纬","稀弄","双纬","空织","百脚","密路","花毛密路","错支类","豁边","紧边","烂边毛边","深色油污","透明油污","交班印","条干不匀","其他瑕疵","人为干扰" };
  
          public delegate void AddFlawShot(MFlawInfo flaw);
          public AddFlawShot DoAddFlawShot;
  
          public delegate void RunningEvent();
          public RunningEvent Running;
          private int _lostTime = 0;
          private TimerBl _tbl = null;
  
          private Modle.Sdk.StructInfos.CLAS_PARAM _findWall;
  
          #endregion
  
          #region 程序入口
          public FlawDetectionBl(int cameraCount)
          {
              try
              {
                  _cameraCount = cameraCount;
                  _finishedCameraCount = cameraCount;
                  LogisTrac.WriteInfoLog(String.Format("[开始] =====[{0}]======", "FlawDetectionBl"));
                  _findWall = new Modle.Sdk.StructInfos.CLAS_PARAM
                  {
                      prob_cls = ConfigHelper.GetInstance().GetConfig().Prob_cls,//通用瑕疵
                      prob_sma = ConfigHelper.GetInstance().GetConfig().Prob_sma,//小瑕疵
                      prob_color = ConfigHelper.GetInstance().GetConfig().Prob_color,//色纤
                      prob_thin = ConfigHelper.GetInstance().GetConfig().Prob_thin,//淡痕
                      len_sma = ConfigHelper.GetInstance().GetConfig().Len_sma,//小瑕疵长度限制阈值
                      cloths_kind = 0,   //布种 0:正常布种; 1:薄布 2:厚布
                      m_gain = 0,     //增益返回值
                      m_base = ConfigHelper.GetInstance().GetConfig().M_base, //增益基准值
                      m_meters = (int)OS.Spin.Running.Cache.GetInstance().CMeter,    //当前米数计数值
                      thre_are = ConfigHelper.GetInstance().GetConfig().Thre_Area,//点状瑕疵面积
                      thre_location = ConfigHelper.GetInstance().GetConfig().Thre_Location//布尾米数位置阈值
                  };
  
                  #region TWB20210902
                  //// 初始化分类
                  var count = SdkLayer.SdkMyCode.Flaw_ClassifyInit(ref _handle_h, ref _handle_v, ref _handle_proc);
                  #endregion
                  // 初始化后处理
                  //count = OS.Spin.SdkLayer.SdkImport.Detc_Post_Init(ref _handle, _cameraCount);
                  _classId = Guid.NewGuid().ToString();
                  // 获取信号量
                  _semaphorePool = OS.Spin.Common.MultiThread.SemaphorePool.GetInstance();
                  // 创建检查信号量
                  _semaphorePool.MakeSemaphore(string.Format("{0}{1}", OS.Spin.Running.Infos.Names.S_DETECTION_OK, _classId));
  
                  // 初始化相机
                  for (var cId = 0; cId < _cameraCount; cId++)
                  {
                      var camera = new CameraBl(cId)
                      {
                          SendRecivedImg = RecivedImg
                      };
  
                      _cameras.Add(camera);
  
                      DetectionBl detection = new DetectionBl(_classId, cId)
                      {
                          DoGetThreeChannelMat = DoGetThreeChannelsMat
                      };
                      _detections.Add(detection);
                  }
  
                  // 启动分类线程
                  if (null == _runThread)
                  {
                      _runThread = new Thread(Classifying);
                      _runThread.Priority = ThreadPriority.AboveNormal;
                      _runThread.Start();
                  }
  
                  //// 创建码表通讯模块
                  //_tbl = new TimerBl
                  //{
                  //    DoRecived = TimerRecived
                  //};
                  //_tbl.OnStart();
              }
              catch (Exception ex)
              {
                  LogisTrac.WriteLog(string.Format("FlawDetectionBl:{0}", ex.Message));
              }
  
          }
  
          public bool CanTrigger
          {
              get { return _canRecived; }
          }
  
          private FlawDetectionBl()
          {
  
          }
          #endregion
  
          #region public
  
          #region 相机触发拍照
          /// <summary>
          /// 相机触发拍照
          /// </summary>
          /// <returns></returns>
          public bool CameraTrigger(double meter)
          {
              try
              {
                  LogisTrac.WriteLog("触发");
                  if (meter < 3)
                  {
                      foreach (var camera in _cameras)
                      {
                          camera.SetCameraCainValue(ConfigHelper.GetInstance().GetConfig().M_base / 10.0);
                          LogisTrac.WriteLog(string.Format("5米前设置相机增益===[{0}]=====", ConfigHelper.GetInstance().GetConfig().M_base / 10.0));
                      }
                      _isSetGain = true;
                      //pool_size = 0;
                  }
                  OS.Spin.Running.Cache.GetInstance().CMeter = meter;
                  Running?.Invoke();
                  if (!_canRecived)
                  {
                      _lostTime++;
                      if (_lostTime > 10)
                      {
                          _canRecived = true;
                      }
                      return false;
                  }
                  _lostTime = 0;
                  _canRecived = false;
                  OS.Spin.Running.Cache.GetInstance().CMeter = meter;
                  //if (_finishedCameraCount >= _cameraCount)
                  {
                      //_finishedCameraCount = 0;
                      // 重置相机接收完成标志
                      //OS.Spin.Running.Cache.GetInstance().CamerasOk = false;
                      if (meter > 3 && _isSetGain)
                      {
                          foreach (var camera in _cameras)
                          {
                              camera.SetCameraCainValue((_gainValue / 10.0));
                          }
                          _isSetGain = false;
                          //_gainValue = 0;
                          LogisTrac.WriteLog(string.Format("设置相机增益值===[{0}]==============", _gainValue));
                      }
  
                      foreach (var camera in _cameras)
                      {
                          camera.Trigger();
                      }
                      return true;
                  }
              }
              catch (Exception ex)
              {
                  LogisTrac.WriteLog(string.Format("CameraTrigger:{0}", ex.Message));
                  return false;
              }
  
              //return false;
          }
          #endregion
  
          #region 重置清零后处理参数
          /// <summary>
          /// 重置清零后处理参数
          /// </summary>
          public void ReSetDp()
          {
              //OS.Spin.SdkLayer.SdkImport.DP_Clear(_handle);
          }
          #endregion
  
          #region 码表清零
          /// <summary>
          ///  码表清零
          /// </summary>
          public void Zeroing()
          {
              if (null == _tbl)
              {
                  return;
              }
  
              _tbl.Zero();
          }
          #endregion
  
          #region 释放资源
          /// <summary>
          /// 释放资源
          /// </summary>
          public void Dispose()
          {
              try
              {
                  foreach (var d in _detections)
                  {
                      if (null == d)
                      {
                          continue;
                      }
  
                      d.Dispose();
                  }
  
                  foreach (var camera in _cameras)
                  {
                      camera.Dispose();
                  }
  
                  if (null != _tbl)
                  {
                      _tbl.Dispose();
                  }
  
                  _runThread.Abort();
  
                  #region TWB20210902
                  OS.Spin.SdkLayer.SdkMyCode.Flaw_ClassifyRelease(ref _handle_h, ref _handle_v, ref _handle_proc);
                  #endregion
                  OS.Spin.Common.Camera.JaiCamera.GetInstance().Close();
              }
              catch (Exception ex)
              {
                  LogisTrac.WriteInfoLog(string.Format("FlawDetectionBl Dispose:{0}", ex.Message));
              }
          }
          #endregion
  
          #endregion
  
          #region private
  
          #region 接收相机数据
          /// <summary>
          ///  接收相机数据
          /// </summary>
          /// <param name="cameraId">相机编号</param>
          /// <param name="img">拍照数据</param>
          private void RecivedImg(int cameraId, Modle.Sdk.StructInfos.DATA_IMAGE1 img)
          {
              _imageId = OS.Spin.Running.Cache.GetInstance().CacheImgId;
              // 开始执行
              _detections[cameraId].StartDetection(img);
              //_finishedCameraCount++;
          }
          #endregion
  
          private double _cMeter = -1;
          public void TimerRecived(int type, double meter)
          {
              if (type == 1)
              {
                  CameraTrigger(meter);
              }
  
              if (type == 0 && !_cMeter.Equals(meter))
              {
                  // ImageSavingBl.Getinstance().PutCopy(new MFileCopy(2, OS.Spin.Running.Cache.GetInstance().CacheImgId, _cameraCount));
                  _cMeter = meter;
              }
          }
          #region 执行分类处理
          /// <summary>
          /// 执行分类处理
          /// </summary>
          private void Classifying()
          {
              if (_cameraCount <= 0)
              {
                  return;
              }
              var id = OS.Spin.Common.Machine.CpuTool.SetCpuID(_cameraCount);
              //将当前线程绑定到指定的cpu核心上
              OS.Spin.Common.Machine.CpuTool.SetThreadAffinityMask(OS.Spin.Common.Machine.CpuTool.GetCurrentThread(), new UIntPtr(id));
  
              while (true)
              {
                  var time = 0;
                  while (time < _cameraCount)
                  {
                      _semaphorePool.Wait(string.Format("{0}{1}", OS.Spin.Running.Infos.Names.S_DETECTION_OK, _classId));
                      time++;
                  }
                  try
                  {
                      //// 手动验布时不做算法处理
                      //if (!OS.Spin.Running.Cache.GetInstance().AutoFlaw)
                      //{
                      //    //_canRecived = true;
                      //    continue;
                      //}
                      // 获取图像原图
                      var flaw = new MFlawInfo();
                      for (var i = 0; i < _cameraCount; i++)
                      {
                          flaw.AddMat(OS.Spin.Running.Cache.GetInstance().Mats[i].Clone());
                      }
                      current_meter = (int)OS.Spin.Running.Cache.GetInstance().CMeter;
                      // 记录当前处理的图片编号
                      _reallyImageId = _imageId;
                      // 释放拍照触发
                      // 统计需要分类处理的瑕疵快照个数
                      var classify_num = 0;
                      var cache = OS.Spin.Running.Cache.GetInstance();
  
                      for (var i = 0; i < _cameraCount; i++)
                      {
                          var rois = cache.GetFore_Result(i);
                          //var rts = rois;
                          if (null == rois)
                          {
                              continue;
                          }
                          classify_num += rois.Count();
                      }
                      //TWB20210902
                      var result = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Modle.Sdk.StructInfos.Fore_Result)) * classify_num);
  
                      var fIn = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Modle.Sdk.StructInfos.Fore_Result)) * classify_num);
                      long ptr = fIn.ToInt64();
                      var fores = new Modle.Sdk.StructInfos.Fore_Result[classify_num];
                      //IntPtr RPtr = new IntPtr(ptr);
                      var classify_cnt = 0;
                      for (int m = 0; m < _cameraCount; m++)
                      {
                          var rois = cache.GetFore_Result(m);
                          if (null == rois)
                          {
                              continue;
                          }
                          foreach (var roi in rois)
                          {
  
                              fores[classify_cnt] = roi;
                              //Marshal.StructureToPtr(fores[classify_cnt], RPtr, false);
  
                              ptr += Marshal.SizeOf(typeof(Modle.Sdk.StructInfos.Fore_Result));
                              //LogisTrac.WriteLog(String.Format("[检测] 结果 image id:{0}  label:{1}  prob:{2} prob_sum:{3} width:{4}  height:{5} x:{6} y:{7}", fores[classify_cnt].img_id, fores[classify_cnt].label, fores[classify_cnt].prob, fores[classify_cnt].prob_sum, fores[classify_cnt].width, fores[classify_cnt].height, fores[classify_cnt].xCenter_cam, fores[classify_cnt].yCenter_cam));
                              classify_cnt++;
                          }
                      }
                      // 组装分类数据
                      //var resultSize = Marshal.SizeOf(typeof(Modle.Sdk.StructInfos.CTOOLS_Result)) * classify_num;
                      //var results = Marshal.AllocHGlobal(resultSize);
                      LogisTrac.WriteInfoLog(String.Format("[分类] 开始 ={0}======", _reallyImageId));
  
                      //int final_labelsize = 0;
                      #region TWB20210902
                      _findWall.m_meters = current_meter;
                      //_findWall.th_prob0 = OS.Spin.Running.Cache.GetInstance().FindWall;
                      //_findWall.th_prob1 = OS.Spin.Running.Cache.GetInstance().JdWall;
                      //_findWall.th_prob2 = OS.Spin.Running.Cache.GetInstance().MhWall;
                      _findWall.cloths_kind = OS.Spin.Running.Cache.GetInstance().Cloths_kind;
                      #endregion
  
  
                      //int gain = 0;
                      #region TWB20210902
                      int finalNum = 0;
                      var a = OS.Spin.SdkLayer.SdkMyCode.Flaw_Classification(flaw.Mats[0].Data, flaw.Mats[1].Data, flaw.Mats[2].Data, fores, classify_num, result, ref finalNum, ref _findWall, _handle_h, _handle_v, _handle_proc);
                      //Marshal.FreeHGlobal(ptrIn);
                      #endregion
  
                      _gainValue = _findWall.m_gain;
  
                      LogisTrac.WriteInfoLog(String.Format("[相机增益] ===[{0}] ={1}======", _reallyImageId, _gainValue));
                      List<Fore_Result> rts = new List<Fore_Result>();
                      // 解析返回结果
                      for (var i = 0; i < finalNum; i++)
                      {
                          var ptr1 = (result + i * Marshal.SizeOf(typeof(Modle.Sdk.StructInfos.Fore_Result)));
  
                          rts.Add((Modle.Sdk.StructInfos.Fore_Result)Marshal.PtrToStructure(ptr1, typeof(Modle.Sdk.StructInfos.Fore_Result)));
                          LogisTrac.WriteInfoLog(String.Format("[分类] 结果 image id:{0}  label:{1}  prob:{2} prob_sum:{3} width:{4}  height:{5} x:{6} y:{7}", rts[i].img_id, rts[i].label, rts[i].prob, rts[i].prob_sum, rts[i].width, rts[i].height, rts[i].xCenter_cam, rts[i].yCenter_cam));
                      }
  
                      //for (var i = 0; i < finalNum; i++)
                      //{
                      //    LogisTrac.WriteLog(String.Format("[分类] 结果 ={0}===[{1}]===[{2}]==[{3}]==[{4}]==[{5}==[{7}]==[{8}]", fores[i].img_id, fores[i].label, fores[i].prob, fores[i].is_valid, fores[i].xCenter_cam, fores[i].yCenter_cam, fores[i].yCenter_cam, fores[i].width, fores[i].height));
                      //}
  
                      //for (var i = 0; i < final_labelout.Count(); i++)
                      //{
                      //    final_labelout[i].is_valid = 1;
                      //    final_labelout[i].deduction = 4;
                      //}
  
                      #region TWB20210902 方法删除
                      // OS.Spin.SdkLayer.SdkMyCode.Detc_Postprocess(fores, classify_num, label_poolarray, ref pool_size, final_labelout, ref final_labelsize, current_meter);
                      #endregion
  
                      //LogisTrac.WriteInfoLog(String.Format("[分类] 结束 ={0}===[{1}]===", _reallyImageId, final_labelsize));
  
                      //_canRecived = true;
  
                      if (finalNum == 0)
                      {
                          continue;
                      }
  
                      var index = cache.FlawId;
                      var subIndex = 0;
                      //先抠图后画框 本次只抠图
                      for (var i = 0; i < finalNum; i++)
                      {
                          var fl = rts[i];
  
                          //if (fl.is_repeat == 1)
                          //{
                          //    continue;
                          //}
                          MFinalFlawCell fr = new MFinalFlawCell();
                          fr.FlawName = _lableNames[fl.label];
                          fr.Meter = OS.Spin.Running.Cache.GetInstance().CMeter;
                          //MFinalFlawCell fr = new MFinalFlawCell()
                          //{
                          //    FlawName = _lableNames[fl.label],
                          //    Meter = OS.Spin.Running.Cache.GetInstance().CMeter
                          //};
  
                          flaw.AddFinalFlaw(fr);
  
                          var xMeter = 0.5;
                          if (fl.img_id > 1)
                          {
                              xMeter += 1;
                          }
  
                          if (fl.img_id > 2)
                          {
                              xMeter += 1;
                          }
                          var s = new MFlawSnap
                          {
                              No = string.Format("{0}_{1}", index, subIndex),
                              FlawName = _lableNames[fl.label],
                              #region TWB20210902
                              CenterX = xMeter,
                              CenterY = fl.yCenter_cam / 1200 * 0.3 + OS.Spin.Running.Cache.GetInstance().CMeter
                              #endregion
                          };
  
                          subIndex++;
  
                          var fMat = (flaw.Mats[fl.img_id]);
                          var newFMat = (flaw.Mats[fl.img_id]).Clone();
                          int start_x = fl.xCenter_cam * RS_FACTOR - ROI_WIDTH / 2;
                          int start_y = fl.yCenter_cam * RS_FACTOR - ROI_HEIGHT / 2;
  
                          if (start_x < 0)
                              start_x = 0;
                          if (start_x + ROI_WIDTH > fMat.Width)
                              start_x = fMat.Width - ROI_WIDTH;
                          if (start_y < 0)
                              start_y = 0;
                          if (start_y + ROI_HEIGHT > fMat.Height)
                              start_y = fMat.Height - ROI_HEIGHT;
                          s.SnapMat = (new Mat(fMat.Clone(), new OpenCvSharp.Rect(start_x, start_y, ROI_WIDTH, ROI_HEIGHT)));
                          //Cv2.Rectangle(fMat, new Point(start_x, start_y), new Point(start_x + ROI_WIDTH, start_y + ROI_HEIGHT), new Scalar(5, 5, 5), 2);
  
                          //Cv2.Circle(fMat, new Point(fore.xCenter_cam * RS_FACTOR, fore.yCenter_cam * RS_FACTOR), 150, new Scalar(255, 255, 255), 5);
                          flaw.AddSnapFlaws(s);
                          // LogisTrac.WriteLog(String.Format("[最终] 结果 ={0}===[{1}]===[{2}]==[{3}]", fores[i].img_id, fl.label, fl.prob, fl.is_valid));
                          //foreach (var fore in fores)
  
                      }
                      //本次循环只画框
                      for (var i = 0; i < finalNum; i++)
                      {
                          var fl = rts[i];
                          var xMeter = 0.5;
                          if (fl.img_id > 1)
                          {
                              xMeter += 1;
                          }
                          if (fl.img_id > 2)
                          {
                              xMeter += 1;
                          }
                          subIndex++;
                          var fMat = (flaw.Mats[fl.img_id]);
                          var newFMat = (flaw.Mats[fl.img_id]).Clone();
                          int start_x = fl.xCenter_cam * RS_FACTOR - ROI_WIDTH / 2;
                          int start_y = fl.yCenter_cam * RS_FACTOR - ROI_HEIGHT / 2;
  
                          if (start_x < 0)
                              start_x = 0;
                          if (start_x + ROI_WIDTH > fMat.Width)
                              start_x = fMat.Width - ROI_WIDTH;
                          if (start_y < 0)
                              start_y = 0;
                          if (start_y + ROI_HEIGHT > fMat.Height)
                              start_y = fMat.Height - ROI_HEIGHT;
  
                          //s.SnapMat = (new Mat(fMat, new OpenCvSharp.Rect(start_x, start_y, ROI_WIDTH, ROI_HEIGHT)));
                          Cv2.Rectangle(fMat, new Point(start_x, start_y), new Point(start_x + ROI_WIDTH, start_y + ROI_HEIGHT), new Scalar(5, 5, 5), 2);
                          //Cv2.Circle(fMat, new Point(fore.xCenter_cam * RS_FACTOR, fore.yCenter_cam * RS_FACTOR), 150, new Scalar(255, 255, 255), 5);
                          // LogisTrac.WriteLog(String.Format("[最终] 结果 ={0}===[{1}]===[{2}]==[{3}]", fores[i].img_id, fl.label, fl.prob, fl.is_valid));
                          //foreach (var fore in fores)
                      }
  
                      // 有用瑕疵存在时
                      if (flaw.FinalFlaws.Count > 0)
                      {
                          if (OS.Spin.Running.Cache.GetInstance().AutoFlaw)
                          {
                              TlWorker?.Invoke(11);
                          }
                          // 保存带瑕疵图片
                          ImageSavingBl.Getinstance().PutCopy(new MFileCopy(0, _reallyImageId, _cameraCount));
                          LogisTrac.WriteInfoLog(String.Format("PutCopy ={0}======", _reallyImageId));
                          DoAddFlawShot?.Invoke(flaw);
                          LogisTrac.WriteInfoLog(String.Format("DoAddFlawShot ={0}======", _reallyImageId));
                      }
                  }
                  catch (Exception ex)
                  {
                      LogisTrac.WriteInfoLog("Classifying");
                      LogisTrac.WriteLog(ex);
                  }
                  finally
                  {
                      _canRecived = true;
                      LogisTrac.WriteInfoLog(String.Format("正常结束 ={0}======", _reallyImageId));
                  }
              }
          }
          #endregion
  
  
          /// <summary>
          /// 改变布匹参数
          /// </summary>
          /// <param name="kind"></param>
          public void UploadClothsKind(int kind)
          {
              try
              {
                  foreach (var dl in _detections)
                  {
                      dl.DoUploadClothsKind(kind);
                  }
                  _findWall.cloths_kind = kind;
                  OS.Spin.Running.Cache.GetInstance().Cloths_kind = kind;
              }
              catch (Exception ex)
              {
                  LogisTrac.WriteInfoLog(String.Format("UploadClothsKind: {0}", ex.Message));
              }
          }
  
  
          #region 获取三通道照片信息
          /// <summary>
          /// 获取三通道照片信息
          /// </summary>
          /// <param name="cammeraId"></param>
          /// <returns></returns>
          private Mat DoGetThreeChannelsMat(int cammeraId)
          {
              return _cameras[cammeraId].ThreeChannelMat;
          }
          #endregion
  
          #endregion
  
          #region ===== WARNING FINISHED ON 2019/06/06 BY Ding Shujie VERSION: V1.0.0 ======
          #endregion
      }
  }