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 _cameras = new List(); private List _detections = new List(); 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 相机触发拍照 /// /// 相机触发拍照 /// /// 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 重置清零后处理参数 /// /// 重置清零后处理参数 /// public void ReSetDp() { //OS.Spin.SdkLayer.SdkImport.DP_Clear(_handle); } #endregion #region 码表清零 /// /// 码表清零 /// public void Zeroing() { if (null == _tbl) { return; } _tbl.Zero(); } #endregion #region 释放资源 /// /// 释放资源 /// 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 接收相机数据 /// /// 接收相机数据 /// /// 相机编号 /// 拍照数据 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 执行分类处理 /// /// 执行分类处理 /// 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 rts = new List(); // 解析返回结果 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 /// /// 改变布匹参数 /// /// 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 获取三通道照片信息 /// /// 获取三通道照片信息 /// /// /// 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 } }