#define Online
#define Online_defect
//#define Online_One
using BarTenderPrint;
using CCWin.SkinControl;
using CCWin.Win32;
using CCWin.Win32.Const;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml.Wordprocessing;
using GeBoShi.ImageDefect;
using GeBoShi.UI.InageShow;
using GeBoShi.UI.Product;
using HalconDotNet;
using HZH_Controls;
using HZH_Controls.Forms;
using K4os.Hash.xxHash;
using MaiMuControl.Device;
using MaiMuControl.Device.CamDev;
using MaiMuControl.Device.IOCardDev;
using MaiMuControl.Device.IOCardDev.Advantech;
using MaiMuControl.Device.LightDev;
using MaiMuControl.Device.LightDev.CST;
using MaiMuControl.Device.LightDev.Rsee;
using MaiMuControl.Device.PlcDev;
using MaiMuControl.SysStatusMgr.CloudMgr;
using MaiMuControl.SysStatusMgr.StatusMgr;
using MaiMuControl.SysStatusMgr.UserMgr;
using MaiMuControl.Utils;
using Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using S7.Net;
using SqlSugar;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net.Mail;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using System.Windows.Forms.VisualStyles;
using ToolKits.Disk;
using ToolKits.Http;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TaskbarClock;
namespace GeBoShi.SysCtrl
{
///
/// 主系统控制
///
public class SysMgr
{
#region singleton实例化
private static SysMgr _instance;
private static readonly object _lock = new object();
public static SysMgr Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
if (_instance == null)
{
_instance = new SysMgr();
}
}
}
return _instance;
}
}
#endregion
#region 私有
//系统状态
private StatusMgr statusMgr;
public StatusMgr StatusMgr { get { return statusMgr; } }
//用户管理
private GeBoShi.UI.User.UserMgr userMgr;
public GeBoShi.UI.User.UserMgr UserMgr { get { return userMgr; } }
//系统配置管理
private ConfMgr confMgr;
//图像处理
private DefectLib defectLib;
public DefectLib DefectLib { get { return defectLib; } }
//产品检测列表
private List productCodeList = new List();
public List ProductCodeList { get { return productCodeList; } }
//产品ID列表
private List productIdList = new List();
public List ProductIdList { get { return productIdList; } }
///
/// 当前产品
///
private Models.Product CurrProductModel = null;
//数据锁
private object lockCurrKey = new object();
//当前运行数据key
private int currKey = 0;
//线程管控
private Hashtable htTask = new Hashtable();//默认单线程写入不用lock, 多线程安全同步读取用Synchronized
//是否处理完成
private bool _isDefect = false;
//计算速度用,暂停时停止计数
private Stopwatch pStopWatch = new Stopwatch();
//计算速度用,计算实时速度
private Stopwatch pRunSpeedWatch = new Stopwatch();
private object lock_defectPuase = new object();
///
/// 二次判定缺陷
///
private List defectPuaseList = new List();
///
///
///
private ConcurrentDictionary defectPuaseImgList = new ConcurrentDictionary();
//实时速度
private double ActiveSpeed = 0;
//图片队列
private int _DefectEnd = 0;
private double _NarmalWidth = 0; //正常幅宽
private int listCntMax = 60;
private int Cam1Cnt = 0;
private int Cam2Cnt = 0;
int _marginWidth1 = 0;
int _marginWidth2 = 0;
///
/// 界面二次判定开启
///
private bool DefectPauseForUser = true;
///
/// 第一次计米启用
///
private bool JmFtStart = false;
///
/// 界面光源值
///
private int FrmLightValue = 0;
private string ImgDirSN = "";
#region 处理类型
private class ScanPhotoInfo
{
///
///
///
///
/// 1-n 第1张会把1改为0
///
public ScanPhotoInfo(int _devIndex, int _photoIndex, string _path)
{
devIndex = _devIndex;
photoIndex = _photoIndex;
path = _path;
}
public ScanPhotoInfo(int _devIndex, int _photoIndex, Mat _mat, bool haveEdge = true)
{
devIndex = _devIndex;
photoIndex = _photoIndex;
mat = _mat;
EdgeSts = haveEdge;
}
public int devIndex { get; set; }
///
/// 0-n
///
public int photoIndex { get; set; }
public string path { get; set; }
public Mat mat { get; set; }
public bool EdgeSts { get; set; }
}
#endregion
private ConcurrentQueue _matList1 = new ConcurrentQueue();
private ConcurrentQueue _matList2 = new ConcurrentQueue();
private Service.ProductService PdtService = new Service.ProductService();
private Service.RecordsService RecordService = new Service.RecordsService();
private bool _isOpenIO;
private bool _isHaveImgL;
private bool _isHaveImgR;
#endregion
#region 公开字段
private bool _isInit;
///
/// 是否初始化完成
///
public bool IsInit { get { return _isInit; } }
private bool _isRuning;
///
/// 设备正在运行
///
public bool IsRuning { get { return _isRuning; } }
private bool _isAuto;
///
/// 设备正在自动化流程中
///
public bool IsAuto { get { return _isAuto; } }
#endregion
#region 私有流程
//主流程
private Thread _mainThread;
private Thread _Cam1Thread;
private Thread _Cam2Thread;
private Thread _SpeedThread;
private Thread _SaveImgThread;
private CancellationTokenSource _cts;
private Form _FatherFrm;
private object _lockOpenCV = new object();
#endregion
#region 云端
//局域网云端
private bool init_Cloud;
private CloudMgr cloudMgr;
private int DailyOutput;
#endregion
private SysMgr()
{
_isInit = false;
_isRuning = false;
_isAuto = false;
statusMgr = StatusMgr.Instance;
confMgr = ConfMgr.Instance;
userMgr = new GeBoShi.UI.User.UserMgr(statusMgr.MySqlIP);
_cts = new CancellationTokenSource();
init_Cloud = false;
cloudMgr = new CloudMgr();
DailyOutput = 0;
Service.InitDB.ConnectionString = confMgr.DBConStr;
PdtService = new Service.ProductService();
RecordService = new Service.RecordsService();
}
#region 本地云上传
///
/// 上传当日产量
///
private void SendDailyOutput()
{
//开启云端
if (init_Cloud)
{
try
{
if (!cloudMgr.SendTopic("device/attributes", $"{{ \"DailyOutput\": \"{DailyOutput}\"}}"))
Log("云端", $"上传失败", WarningEnum.Low);
}
catch (Exception e)
{
Log("云端", $"上传失败:{e.Message}", WarningEnum.Low);
}
}
}
///
/// 上传正常状态
///
public void SendStatus()
{
//开启云端
if (init_Cloud)
{
//上传报警状态和信息
string statusStr = "正常";
switch (StatusMgr.Status)
{
case SystemStsEnum.Manual:
statusStr = "人工操作";
break;
case SystemStsEnum.Standby:
statusStr = "正常待机";
break;
case SystemStsEnum.Initial:
statusStr = "初始化";
break;
case SystemStsEnum.Auto:
statusStr = "自动运行";
break;
case SystemStsEnum.Pause:
statusStr = "自动暂停";
break;
case SystemStsEnum.SetParams:
statusStr = "参数设置";
break;
case SystemStsEnum.Debug:
statusStr = "调试";
break;
case SystemStsEnum.Warning:
statusStr = "系统报警";
break;
case SystemStsEnum.Bootload:
statusStr = "Bootload";
break;
default:
statusStr = "未知";
break;
}
try
{
if (!cloudMgr.SendTopic("device/attributes", $"{{\"status\": \"{statusStr}\", \"alm\": \"无报警信息\", " +
$"\"name\": \"{confMgr.SysConfigParams.CloudThisName}\", \"DailyOutput\": \"{DailyOutput}\"}}"))
Log("云端", $"上传失败", WarningEnum.Low);
}
catch (Exception e)
{
Log("云端", $"上传失败:{e.Message}", WarningEnum.Low);
}
}
}
#endregion
#region 用户+登入+管理
///
/// 登入
///
///
public bool LoginSystem()
{
return userMgr.UserLoginDialog();
}
///
/// 用户权限
///
public void UserPermissiomMgr()
{
userMgr.RightManageDialog();
}
///
/// 用户管理
///
public void UserListMgr()
{
userMgr.UserManagerDialog();
}
#endregion
#region 系统初始化&&运行
///
/// 系统初始化
///
///
public bool Initial()
{
try
{
bool ret = false;
string err = "";
ret = confMgr.LoadSystemConfig();
//根据llog路径,开始记录日志
if (!Directory.Exists(confMgr.SysConfigParams.LogPath))
throw new Exception("日志路径不存在");
statusMgr.StartLog(confMgr.SysConfigParams.LogPath);
InitLog("系统开始初始化...");
//Thread.Sleep(200);
int minWorker, minIOC;
ThreadPool.GetMinThreads(out minWorker, out minIOC);
bool trt = ThreadPool.SetMinThreads(25, minIOC);
// 加载系统配置
InitLog("加载系统参数...");
//ret = confMgr.LoadSystemConfig();
if (!ret)
{
throw new Exception("系统参数加载失败...");
}
InitLog("系统参数加载完成!");
//根据llog路径,开始记录日志
//if(!Directory.Exists(confMgr.SysConfigParams.LogPath))
// throw new Exception("日志路径不存在");
//statusMgr.StartLog(confMgr.SysConfigParams.LogPath);
statusMgr.GotoInitial();
SendStatus();
//Thread.Sleep(200);
// 硬件初始化
if (!InitAllDev())
{
throw new Exception("硬件初始化失败...");
}
InitLog("硬件初始化完成!");
// 加载硬件配置
InitLog("加载硬件驱动参数...");
if (!LoadDevConfig())
{
throw new Exception("加载硬件驱动参数失败...");
}
InitLog("加载硬件驱动参数完成!");
//Thread.Sleep(200);
// 处理运行
InitLog("AI算法核心初始化...");
defectLib = new DefectLib();
if (!defectLib.start())
throw new Exception("外观检测核心初始化失败...");
InitLog("AI算法核心初始化完成!");
LedReady();
//初始化成功
_isInit = true;
statusMgr.GotoNormalStandby();
SendStatus();
OnInitRuning(new InitEventArgs("系统初始化完成...", this.IsInit));
Run();
return ret;
}
catch (Exception ex)
{
InitLog(ex.Message, "初始化", WarningEnum.High);
InitLog("系统初始化失败!", "初始化", WarningEnum.High);
//statusMgr.GotoWarning(MaiMuControl.Device.WarningEnum.High, "初始化", ex.Message);
return false;
}
}
///
/// 初始化图像处理报警
///
///
public bool InitDefectEvent()
{
if (defectLib != null)
{
defectLib.WarningEvent = (warning, msg) =>
{
Log("缺陷检测", msg, warning);
};
return true;
}
return false;
}
public bool InitCloudConnect()
{
if (confMgr.SysConfigParams.OpenCloud)
{
if (cloudMgr.ConnectCloud(confMgr.SysConfigParams.CloudServerIP, confMgr.SysConfigParams.CloudServerPort,
confMgr.SysConfigParams.CloudUser, confMgr.SysConfigParams.CloudPassword))
{
init_Cloud = true;
Log("云端数据", "开启云端连接");
return true;
}
Log("云端数据", "云端连接失败!", WarningEnum.Low);
return false;
}
return true;
}
///
/// 运行主线程
///
private void Run()
{
_mainThread = new Thread(() =>
{
MainThreadFunction();
});
_mainThread.IsBackground = true;
_mainThread.Start();
#if Online_One
#else
_Cam1Thread = new Thread(() =>
{
Cam1ThreadFunction();
});
_Cam1Thread.IsBackground = true;
_Cam1Thread.Start();
_Cam2Thread = new Thread(() =>
{
Cam2ThreadFunction();
});
_Cam2Thread.IsBackground = true;
_Cam2Thread.Start();
#endif
_SpeedThread = new Thread(() =>
{
GetLenAndSpd();
});
_SpeedThread.IsBackground = true;
_SpeedThread.Start();
_SaveImgThread = new Thread(() =>
{
SaveImgThreadFunction();
});
_SaveImgThread.IsBackground = true;
_SaveImgThread.Start();
}
#endregion
#region 二次判断开关
public void SetDefectPause(bool val)
{
DefectPauseForUser = val;
}
public bool GetDefectPause()
{
return DefectPauseForUser;
}
#endregion
#region 界面光源设置
public void SetLightValue(int val)
{
FrmLightValue = val;
if(IsInit)
lightDev.SetLightDigitalValue(1, val);
}
#endregion
#region 计米器控制
///
/// 计米器清空
///
private void ClearLengthCount()
{
if (confMgr.SysConfigParams.OpenLengthCount)
{
byte[] clearData = new byte[] { 0x01, 0x06, 0x00, 0x00, 0x00, 0x01, 0x48, 0x0a };
lengthCounter.Write(clearData, 0, 8);
//Thread.Sleep(100);
Thread.Sleep(10);
byte[] recv = new byte[64];
//string recvdata = serialPort.ReadLine();
//recv = recvdata.ToBytes();
int readCnt = lengthCounter.BytesToRead;
lengthCounter.Read(recv, 0, readCnt);
}
}
///
/// 获取计米数据
///
///
private double GetLength()
{
//bool isFile = true;
double length = -1;
bool GetData = false;
if (lengthCounter.IsOpen)
{
byte[] data = new byte[] { 0x01, 0x03, 0x00, 0x21, 0x00, 0x02, 0x94, 0x01 };
lengthCounter.Write(data, 0, 8);
Thread.Sleep(10);
byte[] recv = new byte[64];
//string recvdata = serialPort.ReadLine();
//recv = recvdata.ToBytes();
int readCnt = lengthCounter.BytesToRead;
lengthCounter.Read(recv, 0, readCnt);
byte[] bytes = new byte[4];
for (int i = 0; i < readCnt; i++)
{
if (recv[i] == 0x01 && recv[i + 1] == 0x03 && recv[i + 2] == 0x04)
{
bytes[0] = recv[i + 3];
bytes[1] = recv[i + 4];
bytes[2] = recv[i + 5];
bytes[3] = recv[i + 6];
GetData = true;
}
}
if (GetData)
{
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
int spddata = BitConverter.ToInt32(bytes, 0);
length = spddata / 100.0;
//if (isFile)
// length = -length;
}
if (length > 10000)
return -1;
}
return length;
}
#endregion
#region 后台
private object LockSpd = new object();
private void SedSpd(double spd)
{
lock (LockSpd)
{
ActiveSpeed = spd;
}
}
private double GetSpd()
{
double spd;
lock (LockSpd)
{
spd = ActiveSpeed;
}
return spd;
}
///
/// 中断工序运行
///
///
private bool isBreakProcessRun()
{
return statusMgr.Status == SystemStsEnum.Pause || statusMgr.Warning == WarningEnum.High;
}
///
/// 获取缺陷数据
///
///
///
private List GetDefectListInfo(int liPhotoIndex)
{
List ret;
lock (lock_defectPuase)
{
ret = defectPuaseList.Where(m => m.PhotoIndex == liPhotoIndex).ToList();
}
return ret;
}
///
/// 获取速度和长度
///
private void GetLenAndSpd()
{
double stl = 0; //计米起始位置
double etl = 0; //计米结束位置
double spl = 0; //计算速度计米位置
double yqjimi = 0; //计米长度
double cehouDis = 0;//测厚位置记录
double UseTime = 1;
double preSpd = 0;//上次速度,防止速度出差
double rioSpd = 0.3;//过冲
while (true)
{
int spdcnt = 0;
try
{
if (_cts.IsCancellationRequested)
break;
if (IsRuning)
{
////暂停开始
//stopWatch.Start();
do
{
#if Online
if (currKey > 0)
{
Records curRecord = Hashtable.Synchronized(htTask)[currKey] as Records;
#region 实时速度
if (confMgr.SysConfigParams.OpenLengthCount)
{
double length = GetLength();
if (length >= 0)
{
if (!JmFtStart)
{
//第一次记录起始数据
stl = 0;
spl = 0;
cehouDis = 0;
JmFtStart = true;
pRunSpeedWatch.Restart();
}
else
{
//1s计算一次实时速度
double dt = pRunSpeedWatch.ElapsedMilliseconds;
if (dt / 1000.0d > UseTime)
{
double spddis = Math.Abs(length - spl);
spl = length;
double runOnePicTime = dt / 1000.0d /( 60.0d);//总时间 分
double spd = Math.Round(spddis / runOnePicTime, 2);
//if (spd !=0&&((Math.Abs(spd - preSpd) / preSpd) > rioSpd))
//{
// spd = (Math.Abs(spd - preSpd))/4 + preSpd;
//}
preSpd = spd;
SedSpd(spd);
if (spdcnt > 2)
{
Log($"计米对比", $"计米器距离{Math.Round(spddis,2)},计米速度{Math.Round(spd,2)},计米时间{Math.Round(runOnePicTime,4)}", WarningEnum.Normal, false);
spdcnt = 0;
}
spdcnt++;
//重新计时
pRunSpeedWatch.Restart();
}
etl = length;//记录当前读数
yqjimi = Math.Round((etl - stl) / 1.00, 2); //记录长度
}
lock (lockCurrKey)
{
curRecord.Len = yqjimi;
curRecord.TimeLen = pStopWatch.ElapsedMilliseconds / 1000.0d / 60.0d;//总时间 分
}
double tRunSpd = GetSpd();//1s计算的实时速度
//显示平均速度
OnAutoRuning(new RunEventArgs(yqjimi, tRunSpd));
#region 处理2次判定
//处理2次判定
double aveSpd = Math.Round(yqjimi / (pStopWatch.ElapsedMilliseconds / 1000.0d / (60.0d)), 2);
double StopDecRunDis = tRunSpd / 60.0 * confMgr.SysConfigParams.StopDecTime / 2;
double atcDis = (confMgr.SysConfigParams.StopLookDis - StopDecRunDis);
//计米器判断暂停:瑕疵二次判断
if (confMgr.SysConfigParams.OpenLengthCountStop && DefectPauseForUser && defectPuaseList.Count > 0)
{
if ((yqjimi - atcDis) > (defectPuaseList[0].Y / 100))
{
//if ((yqjimi - atcDis) < (defectPuaseList[0].Y / 100 + 1))
{
Log($"二次判断", $"计米器{yqjimi},瑕疵位置{defectPuaseList[0].Y / 100},停车距离{confMgr.SysConfigParams.StopLookDis}m,停车减速时间{confMgr.SysConfigParams.StopDecTime}s,减速位移{StopDecRunDis},实际停车距离{atcDis},实时速度{tRunSpd},匀速{aveSpd}", WarningEnum.Normal, false);
List lstEditDefect0 = GetDefectListInfo(defectPuaseList[0].PhotoIndex);
Log($"二次判断", $"(图像{defectPuaseList[0].PhotoIndex})已达观察台,瑕疵二次判断=》({string.Join(",", lstEditDefect0.Select(m => m.Code).ToArray())})是否包含在({string.Join(",", curRecord.ProductInfo.DefectPauseOption.ToArray())})中。", WarningEnum.Normal, false);
//瑕疵选项过滤
if (curRecord.ProductInfo.DefectPauseOption.Count == 0 || lstEditDefect0.Where(x => curRecord.ProductInfo.DefectPauseOption.Contains(x.Code)).Count() > 0)
{
Log($"二次判断", $"(图像{defectPuaseList[0].PhotoIndex})需瑕疵二次判断,已达观察台,进入暂停。", WarningEnum.Normal, false);
if (lstEditDefect0.Where(x => DefectItemsPuaseNameList.Contains(x.Name)).Count() > 0)
{
Stop();
//获取完整数据
Thread.Sleep(500);
var lstEditDefect = GetDefectListInfo(defectPuaseList[0].PhotoIndex);
#region 二级界面
int liPhotoIndex = defectPuaseList[0].PhotoIndex;
#region 加载界面
if (defectPuaseImgList.ContainsKey(liPhotoIndex))
{
var pimage = (Bitmap)defectPuaseImgList[liPhotoIndex].ToBitmap().Clone();
var pmat = defectPuaseImgList[liPhotoIndex].Clone();
Task.Run(() =>
{
int liDefectCount = lstEditDefect.Count;
ImageShowFrm frmDefect = new ImageShowFrm(liPhotoIndex, lstEditDefect, pimage);
//frmDefect.Show();
if (frmDefect.ShowDialog() == DialogResult.OK)
{
SysMgr.Instance.DelDefectEdit(curRecord, frmDefect.lstDel);
OnAutoRuning(new RunEventArgs(liPhotoIndex, lstEditDefect, curRecord, pmat, frmDefect.lstDel));
//double len = (double)this.lblLen.Tag;
//this.reDrawDefectPoints(curRecord.DefectInfoList, new double[] { 0, Math.Round(curRecord.FaceWidthMax + 0.005f, 2) }, new double[] { 0, len });
Log($"二次检测", $"本次忽略{frmDefect.lstDel.Count}个瑕疵,本张图由{liDefectCount} -> {lstEditDefect.Count},总数{curRecord.DefectInfoList.Count}");
}
else
{
OnAutoRuning(new RunEventArgs(liPhotoIndex, lstEditDefect, curRecord, pmat, null));
}
});
}
else
Log($"二次检测", $"本次图像已检测完成");
#endregion
//OnAutoRuning(new RunEventArgs(liPhotoIndex, lstEditDefect, curRecord, defectPuaseImgList[liPhotoIndex]));
#endregion
}
}
Log($"二次判断删除", $"{defectPuaseList[0].PhotoIndex}-{testCnt}", WarningEnum.Normal, false);
lstEditDefect0 = defectPuaseList.Where(m => m.PhotoIndex == defectPuaseList[0].PhotoIndex).ToList();
if (lstEditDefect0.Count > 0 && defectPuaseImgList.Count > 0)
{
Mat mt;
defectPuaseImgList.TryRemove(lstEditDefect0[0].PhotoIndex, out mt);
}
//foreach (var item in lstEditDefect0)
{
lock (lock_defectPuase)
{
defectPuaseList.RemoveAll(m => m.PhotoIndex == defectPuaseList[0].PhotoIndex);
//defectPuaseList.Remove(item);
}
}
}
//else
//{
// Log($"二次判断", $"速度过快,超过展示位置!实时速度{tRunSpd},{defectPuaseList[0].PhotoIndex}-{testCnt}", WarningEnum.Low, true);
//}
}
}
#endregion
}
}
#endregion
#endif
#region 堆积显示
OnAutoRuning(new RunEventArgs(_matList1.Count, _matList2.Count, defectLib.GetDefectInfo()));
//System.GC.Collect();
#endregion
#if Online
lock (lockCurrKey)
{
#region 换卷长度提示
if (confMgr.SysConfigParams.OpenLengthCount)
{
if (curRecord.ProductInfo.residueWarnningLen > 0 && yqjimi > curRecord.ProductInfo.residueWarnningLen)
{
Log($"告警", $"已经达到换卷长度最大值{curRecord.ProductInfo.residueWarnningLen}-当前长度{yqjimi}-", WarningEnum.High);
}
}
#endregion
#region 测厚停止
if (confMgr.SysConfigParams.OpenLengthCount && curRecord.ProductInfo.OpenThicknessDetection)
{
if (curRecord.ProductInfo.ThicknessDetectionStopDis > 0 && (yqjimi - cehouDis) > curRecord.ProductInfo.ThicknessDetectionStopDis)
{
Stop();
Log($"测厚提示", $"已经达到测厚位置{curRecord.ProductInfo.ThicknessDetectionStopDis}-当前前进长度{(yqjimi - cehouDis)}-", WarningEnum.High);
}
}
#endregion
}
}
#endif
Thread.Sleep(200);
} while (!isBreakProcessRun());
//暂停中断
//stopWatch.Stop();
//pStopWatch.Stop();
//_isRuning = false;
}
Thread.Sleep(10);
}
catch (Exception e)
{
_isRuning = false;
Log("运行报警", "计米流程运行出错:" + e.Message + "\n", WarningEnum.High);
}
}
}
///
/// 相机1采图预处理
///
private void Cam1ThreadFunction()
{
int errStep = 0;
int marginWidth0 = 0;
int marginException = 0;
#if Online
#else
string imgfilePath = "D:\\CPL\\img\\L1.bmp";
Mat timg = new Mat(imgfilePath);
timg = timg.Flip(FlipMode.XY);
#endif
while (true)
{
try
{
if (_cts.IsCancellationRequested)
break;
if (IsRuning)
{
////暂停开始
//stopWatch.Start();
do
{
#region 实时采图
#if Online
//采集图片
AcquisitionMat acq = _LinecamDev1.GetFrames(100);
if (acq.GrabStatus == "GrabPass")
{
#else
Thread.Sleep(2500);
AcquisitionMat acq = new AcquisitionMat();
{
acq.GrabStatus = "GrabPass";
acq.Image = timg.Clone();
Log($"图像预处理", $"模拟相机1-{Cam1Cnt}", WarningEnum.Normal, true);
}
if (acq.GrabStatus == "GrabPass")
{
#endif
//专用二次判断处理
#if true
#region 处理2次判定
if (!confMgr.SysConfigParams.OpenLengthCountStop)
{
//处理2次判定
//暂停:瑕疵二次判断
if (DefectPauseForUser )
{
errStep = 11;
Records curRecord = Hashtable.Synchronized(htTask)[currKey] as Records;
int liPhotoIndex = Cam1Cnt - confMgr.SysConfigParams.StopImageCnt;
#if false
var havePause = curRecord.dicPhoto_Defect.Where(x => x.Key <= liPhotoIndex && x.Value == true);
if(havePause != null)
{
foreach (var item in havePause)
{
liPhotoIndex = item.Key;
break;
}
}
#endif
//Log($"二次判断2", $"图像{scanPhotos0.photoIndex} {liPhotoIndex}={scanPhotos0.photoIndex}-{confMgr.SysConfigParams.StopImageCnt};{JsonConvert.SerializeObject(curRecord.dicPhoto_Defect)}", WarningEnum.Normal, false);
if (liPhotoIndex >= 0 && curRecord.dicPhoto_Defect.ContainsKey(liPhotoIndex) && curRecord.dicPhoto_Defect[liPhotoIndex] )
{
if (defectPuaseList.Count > 0)
{
errStep = 12;
List lstEditDefect = GetDefectListInfo(liPhotoIndex);
Log($"二次判断2", $"(图像{liPhotoIndex})已达观察台,瑕疵二次判断=》({string.Join(",", lstEditDefect.Select(m => m.Code).ToArray())})是否包含在({string.Join(",", DefectItemsPuaseNameList.ToArray())})或({string.Join(",", curRecord.ProductInfo.DefectPauseOption.ToArray())})中。", WarningEnum.Normal, false);
//瑕疵选项过滤
if (curRecord.ProductInfo.DefectPauseOption.Count == 0 || lstEditDefect.Where(x => curRecord.ProductInfo.DefectPauseOption.Contains(x.Code)).Count() > 0)
{
Log($"二次判断2", $"(图像{liPhotoIndex})需瑕疵二次判断,已达观察台,进入暂停。速度:{GetSpd()},停车缺陷数:{lstEditDefect.Where(x => DefectItemsPuaseNameList.Contains(x.Name)).Count()}");
// if (lstEditDefect.Where(x => x.Code == "jietou").Count() > 0)
//if (lstEditDefect.Where(x => DefectItemsPuaseNameList.Contains(x.Name)).Count() > 0)
{
Stop();
//获取完整数据
Thread.Sleep(500);
lstEditDefect = GetDefectListInfo(liPhotoIndex);
//获取完整数据
#region 二级界面
#region 加载界面
if (defectPuaseImgList.ContainsKey(liPhotoIndex))
{
Log($"二次判断2", $"(图像{liPhotoIndex})需瑕疵二次判断,缺陷数:{lstEditDefect.Count}");
var pmat = defectPuaseImgList[liPhotoIndex].Clone();
OnAutoRuning(new RunEventArgs(liPhotoIndex, lstEditDefect, curRecord, pmat));
#if false
var pimage = (Bitmap)defectPuaseImgList[liPhotoIndex].ToBitmap().Clone();
Task.Run(() =>
{
int liDefectCount = lstEditDefect.Count;
ImageShowFrm frmDefect = new ImageShowFrm(liPhotoIndex, lstEditDefect, pimage);
//if (frmDefect.ShowDialog(_FatherFrm) == DialogResult.OK)
if (frmDefect.ShowDialog() == DialogResult.OK)
{
SysMgr.Instance.DelDefectEdit(curRecord, frmDefect.lstDel);
OnAutoRuning(new RunEventArgs(liPhotoIndex, lstEditDefect, curRecord, pmat, frmDefect.lstDel));
Log($"二次检测2", $"本次忽略{frmDefect.lstDel.Count}个瑕疵,本张图由{liDefectCount} -> {lstEditDefect.Count},总数{curRecord.DefectInfoList.Count}");
}
else
{
OnAutoRuning(new RunEventArgs(liPhotoIndex, lstEditDefect, curRecord, pmat, null));
}
});
#endif
}
else
Log($"二次检测2", $"本次图像已检测完成");
#endregion
//OnAutoRuning(new RunEventArgs(liPhotoIndex, lstEditDefect, curRecord, defectPuaseImgList[liPhotoIndex]));
#endregion
}
errStep = 18;
}
Log($"二次判断删除", $"{liPhotoIndex}-{testCnt}", WarningEnum.Normal, false);
lstEditDefect = defectPuaseList.Where(m => m.PhotoIndex == liPhotoIndex).ToList();
if (lstEditDefect.Count > 0 && defectPuaseImgList.Count > 0)
{
Mat mt;
defectPuaseImgList.TryRemove(lstEditDefect[0].PhotoIndex, out mt);
}
//foreach (var item in lstEditDefect)
{
lock (lock_defectPuase)
{
defectPuaseList.RemoveAll(m => m.PhotoIndex == liPhotoIndex);
//defectPuaseList.Remove(item);
}
}
}
else
Log($"二次判断2", $"(图像{liPhotoIndex})-缺陷未获得,是否包含在({string.Join(",", DefectItemsPuaseNameList.ToArray())})或({string.Join(",", curRecord.ProductInfo.DefectPauseOption.ToArray())})中。", WarningEnum.Low, false);
#if false
curRecord.dicPhoto_Defect.TryUpdate(liPhotoIndex, false, true);
#endif
}
//else
// Log($"二次判断2", $"(图像{liPhotoIndex})-处理未跟上", WarningEnum.Low, false);
}
//time += $"->处理2次判定({stopWatch.ElapsedMilliseconds})";
}
#endregion
#endif
//预处理
Stopwatch stopWatch = new Stopwatch();
//Log($"图像预处理", $"相机1-{Cam1Cnt}", WarningEnum.Normal, false);
string time = "";
stopWatch.Start();
Mat img = acq.Image.Clone();
//图像镜像
if (confMgr.SysConfigParams.Cam1_flipX && confMgr.SysConfigParams.Cam1_flipY)
{
img = img.Flip(FlipMode.XY);
//Cv2.Flip(img, img, FlipMode.XY);//翻转
}
else if (confMgr.SysConfigParams.Cam1_flipX)
{
img = img.Flip(FlipMode.X);
//Cv2.Flip(img, img, FlipMode.X);//翻转
}
else if (confMgr.SysConfigParams.Cam1_flipY)
{
img = img.Flip(FlipMode.Y);
//Cv2.Flip(img, img, FlipMode.Y);//翻转
}
time += $"->相机1翻转({stopWatch.ElapsedMilliseconds})";
//显示
//OnAutoRuning(new RunEventArgs(1, img));
//lock (_lockOpenCV)
{
//存在数据队列
if (currKey != 0 || htTask.ContainsKey(currKey))
{
//保存图片
if (confMgr.SysConfigParams.CamImag.AutoSave && !string.IsNullOrEmpty(confMgr.SysConfigParams.CamImag.SavePath))
{
Records curRecord = Hashtable.Synchronized(htTask)[currKey] as Records;
string dirPath = Util.CreateSubDir(confMgr.SysConfigParams.CamImag.SavePath, new List { $"{curRecord.BarCode}_{curRecord.BarCodeName}_{ImgDirSN}" });
//OpenCvSharp.Extensions.BitmapConverter.ToBitmap(img).Save($"{dirPath}Cam1-{Cam1Cnt}.bmp", ImageFormat.Bmp);
AddImageSave($"{dirPath}Cam1-{Cam1Cnt}.bmp", img);
}
if (_matList1.Count > listCntMax)
{
Log($"堆积过多", $"相机1-缓存{_matList1.Count}大于{listCntMax}", WarningEnum.High);
//_matList1.Dequeue();
System.GC.Collect();
}
Mat mat = img;
try
{
errStep = 1;
//反转+相机索引调换
//lock (_lockOpenCV)
{
//裁边,两侧和中间重合部分
if (confMgr.SysConfigParams.MidCoin > 0)//中间重合部分
{
errStep = 3;
int width = mat.Width - confMgr.SysConfigParams.MidCoin / 2;
mat = OpencvUtils.CutImage(mat, 0, 0, width, mat.Height);
time += $"->相机1-去重({stopWatch.ElapsedMilliseconds})";
}
}
errStep = 4;
//左裁边
mat = OpencvUtils.getMaxInsetRect2(mat, true, confMgr.SysConfigParams.HolePx, out marginWidth0);
//存储裁边异常相机图 差异5cm
if (_marginWidth1 == 0)
{
_marginWidth1 = marginWidth0;
marginException = 0;
}
if (!confMgr.SysConfigParams.CamImag.AutoSave && Math.Abs(marginWidth0 - _marginWidth1) > (10 * confMgr.SysConfigParams.Cm2px_x) && !string.IsNullOrEmpty(confMgr.SysConfigParams.CamImag.SavePath))
{
//边缘异常计数
marginException++;
Records curRecord = Hashtable.Synchronized(htTask)[currKey] as Records;
string dirPath = Util.CreateSubDir(confMgr.SysConfigParams.CamImag.SavePath, new List { $"{curRecord.BarCode}_{curRecord.BarCodeName}_{ImgDirSN}" });
AddImageSave($"{dirPath}Cam1-{Cam1Cnt}.bmp", img);
Log($"图像预处理", $"(相机1-图像{Cam1Cnt})-裁边异常:{marginWidth0}-{_marginWidth1} 》 {10 * confMgr.SysConfigParams.Cm2px_x}", WarningEnum.Normal, false);
}
else
{
marginException = 0;
_marginWidth1 = marginWidth0;
}
errStep = 5;
time += $"->相机1裁边({stopWatch.ElapsedMilliseconds})";
Log($"图像预处理", $"(相机1-图像{Cam1Cnt})-左图去重后:{mat.Width}*{mat.Height}," + $"重复值:{confMgr.SysConfigParams.MidCoin / 2} + 时间{time}", WarningEnum.Normal, false);
//System.GC.Collect();
}
catch (Exception e)
{
Log($"图像处理", $"异常({errStep}):(相机1-图像{Cam1Cnt})-{e.Message}", WarningEnum.High);
}
//Log($"图像1入队列", $"相机1-{Cam1Cnt}", WarningEnum.Normal, false);
//Cv2.Flip(img, img, FlipMode.XY);//翻转
_matList1.Enqueue(new ScanPhotoInfo(0, Cam1Cnt++, mat.Clone(), marginException < 1));
}
else
Log($"相机1", $"(图像)-未扫码,图像丢弃!", WarningEnum.Low);
}
}
#endregion
//System.GC.Collect();
Thread.Sleep(50);
} while (!isBreakProcessRun());
//暂停中断
//stopWatch.Stop();
pStopWatch.Stop();
//_isRuning = false;
}
else
{
//防止内存爆满
AcquisitionMat acq = _LinecamDev1.GetFrames(10);
}
Thread.Sleep(50);
}
catch (Exception e)
{
_isRuning = false;
Log("运行报警", $"相机1流程运行出错{errStep}:" + e.Message + "\n", WarningEnum.High);
}
}
}
///
/// 相机2采图预处理
///
private void Cam2ThreadFunction()
{
int errStep = 0;
int marginWidth0 = 0;
int marginException = 0;
#if Online
#else
string imgfilePath = "D:\\CPL\\img\\R1.bmp";
Mat timg = new Mat(imgfilePath);
timg = timg.Flip(FlipMode.XY);
#endif
while (true)
{
try
{
if (_cts.IsCancellationRequested)
break;
if (IsRuning)
{
////暂停开始
//stopWatch.Start();
do
{
#region 实时采图
#if Online
//采集图片
AcquisitionMat acq = _LinecamDev2.GetFrames(10);
if (acq.GrabStatus == "GrabPass")
{
#else
Thread.Sleep(2500);
AcquisitionMat acq = new AcquisitionMat();
{
acq.GrabStatus = "GrabPass";
acq.Image = timg;
Log($"图像预处理", $"模拟相机2-{Cam2Cnt}", WarningEnum.Normal, true);
}
if (acq.GrabStatus == "GrabPass")
{
#endif
Mat img = acq.Image.Clone();
//预处理
Stopwatch stopWatch = new Stopwatch();
//Log($"图像预处理", $"相机2-{Cam2Cnt}", WarningEnum.Normal, false);
string time = "";
stopWatch.Start();
//图像镜像
if (confMgr.SysConfigParams.Cam2_flipX && confMgr.SysConfigParams.Cam2_flipY)
{
img = img.Flip(FlipMode.XY);
//Cv2.Flip(img, img, FlipMode.XY);//翻转
}
else if (confMgr.SysConfigParams.Cam2_flipX)
{
img = img.Flip(FlipMode.X);
//Cv2.Flip(img, img, FlipMode.X);//翻转
}
else if (confMgr.SysConfigParams.Cam2_flipY)
{
img = img.Flip(FlipMode.Y);
//Cv2.Flip(img, img, FlipMode.Y);//翻转
}
time += $"->相机2翻转({stopWatch.ElapsedMilliseconds})";
//显示
//OnAutoRuning(new RunEventArgs(2, img));
//lock (_lockOpenCV)
{
//存在数据队列
if (currKey != 0 || htTask.ContainsKey(currKey))
{
//保存图片
if (confMgr.SysConfigParams.CamImag.AutoSave && !string.IsNullOrEmpty(confMgr.SysConfigParams.CamImag.SavePath))
{
Records curRecord = Hashtable.Synchronized(htTask)[currKey] as Records;
string dirPath = Util.CreateSubDir(confMgr.SysConfigParams.CamImag.SavePath, new List { $"{curRecord.BarCode}_{curRecord.BarCodeName}_{ImgDirSN}" });
//OpenCvSharp.Extensions.BitmapConverter.ToBitmap(img).Save($"{dirPath}Cam2-{Cam2Cnt}.bmp", ImageFormat.Bmp);
AddImageSave($"{dirPath}Cam2-{Cam2Cnt}.bmp", img);
}
if (_matList2.Count > listCntMax)
{
Log($"堆积过多", $"相机2-缓存{_matList2.Count}大于{listCntMax}", WarningEnum.High);
//_matList2.Dequeue();
System.GC.Collect();
}
Mat mat = img;
try
{
errStep = 1;
//反转+相机索引调换
//lock (_lockOpenCV)
{
//裁边,两侧和中间重合部分
if (confMgr.SysConfigParams.MidCoin > 0)//中间重合部分
{
errStep = 3;
int width = mat.Width - confMgr.SysConfigParams.MidCoin / 2;
mat = OpencvUtils.CutImage(mat, confMgr.SysConfigParams.MidCoin / 2, 0, width, mat.Height);
time += $"->相机2-去重({stopWatch.ElapsedMilliseconds})";
}
}
errStep = 4;
//右裁边
mat = OpencvUtils.getMaxInsetRect2(mat, false, confMgr.SysConfigParams.HolePx, out marginWidth0);
//存储裁边异常相机图 差异5cm
if (_marginWidth2 == 0)
{
marginException = 0;
_marginWidth2 = marginWidth0;
}
if (!confMgr.SysConfigParams.CamImag.AutoSave && Math.Abs(marginWidth0 - _marginWidth2) > (10 * confMgr.SysConfigParams.Cm2px_x) && !string.IsNullOrEmpty(confMgr.SysConfigParams.CamImag.SavePath))
{
//边缘异常计数
marginException++;
Records curRecord = Hashtable.Synchronized(htTask)[currKey] as Records;
string dirPath = Util.CreateSubDir(confMgr.SysConfigParams.CamImag.SavePath, new List { $"{curRecord.BarCode}_{curRecord.BarCodeName}_{ImgDirSN}" });
AddImageSave($"{dirPath}Cam2-{Cam2Cnt}.bmp", img);
Log($"图像预处理", $"(相机2-图像{Cam2Cnt})-裁边异常:{marginWidth0}-{_marginWidth2} 》 {10 * confMgr.SysConfigParams.Cm2px_x}", WarningEnum.Normal, false);
}
else
{
_marginWidth2 = marginWidth0;
}
errStep = 5;
time += $"->相机2裁边({stopWatch.ElapsedMilliseconds})";
Log($"图像预处理", $"(相机2-图像{Cam2Cnt})-右图去重后:{mat.Width}*{mat.Height}," + $"重复值:{confMgr.SysConfigParams.MidCoin / 2} + 时间{time}", WarningEnum.Normal, false);
}
catch (Exception e)
{
Log($"图像处理", $"异常({errStep}):(相机2-图像{Cam2Cnt})-{e.Message}", WarningEnum.High);
}
//Log($"图像2入队列", $"相机2-{Cam1Cnt}", WarningEnum.Normal, false);
//Cv2.Flip(img, img, FlipMode.XY);//翻转
_matList2.Enqueue(new ScanPhotoInfo(1, Cam2Cnt++, mat.Clone(), marginException < 1));
//System.GC.Collect();
}
else
Log($"相机2", $"(图像)-未扫码,图像丢弃!", WarningEnum.Low);
}
}
#endregion
//System.GC.Collect();
Thread.Sleep(50);
} while (!isBreakProcessRun());
//暂停中断
//stopWatch.Stop();
pStopWatch.Stop();
//_isRuning = false;
}
else
{
//防止内存爆满
AcquisitionMat acq = _LinecamDev2.GetFrames(10);
}
Thread.Sleep(50);
}
catch (Exception e)
{
_isRuning = false;
Log("运行报警", "相机1流程运行出错:" + e.Message + "\n", WarningEnum.High);
}
}
}
int testCnt = 0;
///
/// 后台运行主线程
///
private void MainThreadFunction()
{
Mat acq1 = new Mat();
Mat acq2 = new Mat();
#if Online
#else
string imgfilePath1 = "D:\\CPL\\img\\L1.bmp";
string imgfilePath2 = "D:\\CPL\\img\\R1.bmp";
Mat timg1 = new Mat(imgfilePath1);
timg1 = timg1.Flip(FlipMode.XY);
Mat timg2 = new Mat(imgfilePath2);
timg2 = timg1.Flip(FlipMode.XY);
#endif
while (true)
{
int errStep = 0;
try
{
if (_cts.IsCancellationRequested)
break;
if (IsRuning)
{
////暂停开始
//stopWatch.Start();
do
{
#if Online_One
#region 等待图片
#if Online
//采集图片
AcquisitionMat varacq1 = _LinecamDev1.GetFrames(10);
AcquisitionMat varacq2 = _LinecamDev2.GetFrames(10);
#else
AcquisitionMat varacq1 = new AcquisitionMat();
{
varacq1.GrabStatus = "GrabPass";
varacq1.Image = timg1;
Log($"图像预处理", $"模拟相机1-{Cam1Cnt}", WarningEnum.Normal, true);
}
AcquisitionMat varacq2 = new AcquisitionMat();
{
varacq2.GrabStatus = "GrabPass";
varacq2.Image = timg2;
Log($"图像预处理", $"模拟相机2-{Cam2Cnt}", WarningEnum.Normal, true);
}
#endif
if (varacq1.GrabStatus == "GrabPass")
{
acq1 = varacq1.Image.Clone();
_isHaveImgL = true;
Cam1Cnt++;
}
if (varacq2.GrabStatus == "GrabPass")
{
acq2 = varacq2.Image.Clone();
_isHaveImgR = true;
Cam2Cnt++;
}
if (_isHaveImgL && _isHaveImgR)
{
errStep = 1;
Stopwatch stopWatch = new Stopwatch();
string time = "";
Records curRecord = Hashtable.Synchronized(htTask)[currKey] as Records;
try
{
if (Cam1Cnt != Cam2Cnt)
{
Log($"图像预处理", $"图像错位{Cam1Cnt}-{Cam2Cnt}", WarningEnum.High);
continue;
}
#region 处理2次判定
if (!confMgr.SysConfigParams.OpenLengthCountStop)
{
//处理2次判定
//暂停:瑕疵二次判断
if (DefectPauseForUser)
{
stopWatch.Restart();
errStep = 2;
int liPhotoIndex = Cam1Cnt - confMgr.SysConfigParams.StopImageCnt - 1;
if (liPhotoIndex >= 0 && curRecord.dicPhoto_Defect.ContainsKey(liPhotoIndex) && curRecord.dicPhoto_Defect[liPhotoIndex] && curRecord.DefectInfoList != null)
{
if (defectPuaseList.Count > 0)
{
errStep = 3;
List lstEditDefect = defectPuaseList.Where(m => m.PhotoIndex == liPhotoIndex).ToList();
Log($"二次判断2", $"(图像{liPhotoIndex})已达观察台,瑕疵二次判断=》({string.Join(",", lstEditDefect.Select(m => m.Code).ToArray())})是否包含在({string.Join(",", curRecord.ProductInfo.DefectPauseOption.ToArray())})中。", WarningEnum.Normal, false);
//瑕疵选项过滤
if (curRecord.ProductInfo.DefectPauseOption.Count == 0 || lstEditDefect.Where(x => curRecord.ProductInfo.DefectPauseOption.Contains(x.Code)).Count() > 0)
{
Log($"二次判断2", $"(图像{liPhotoIndex})需瑕疵二次判断,已达观察台,进入暂停。速度:{GetSpd()}");
// if (lstEditDefect.Where(x => x.Code == "jietou").Count() > 0)
if (lstEditDefect.Where(x => DefectItemsPuaseNameList.Contains(x.Name)).Count() > 0)
{
Stop();
//获取完整数据
Thread.Sleep(500);
lstEditDefect = defectPuaseList.Where(m => m.PhotoIndex == liPhotoIndex).ToList();
//获取完整数据
#region 二级界面
#region 加载界面
if (defectPuaseImgList.ContainsKey(liPhotoIndex))
{
var pimage = (Bitmap)defectPuaseImgList[liPhotoIndex].ToBitmap().Clone();
var pmat = defectPuaseImgList[liPhotoIndex].Clone();
Task.Run(() =>
{
int liDefectCount = lstEditDefect.Count;
ImageShowFrm frmDefect = new ImageShowFrm(lstEditDefect, pimage);
//frmDefect.Show();
if (frmDefect.ShowDialog(_FatherFrm) == DialogResult.OK)
{
SysMgr.Instance.DelDefectEdit(curRecord, frmDefect.lstDel);
OnAutoRuning(new RunEventArgs(liPhotoIndex, lstEditDefect, curRecord, pmat, frmDefect.lstDel));
//double len = (double)this.lblLen.Tag;
//this.reDrawDefectPoints(curRecord.DefectInfoList, new double[] { 0, Math.Round(curRecord.FaceWidthMax + 0.005f, 2) }, new double[] { 0, len });
Log($"二次检测2", $"本次忽略{frmDefect.lstDel.Count}个瑕疵,本张图由{liDefectCount} -> {lstEditDefect.Count},总数{curRecord.DefectInfoList.Count}");
}
else
{
OnAutoRuning(new RunEventArgs(liPhotoIndex, lstEditDefect, curRecord, pmat, null));
}
});
}
else
Log($"二次检测2", $"本次图像已检测完成");
#endregion
//OnAutoRuning(new RunEventArgs(liPhotoIndex, lstEditDefect, curRecord, defectPuaseImgList[liPhotoIndex]));
#endregion
}
errStep = 3;
}
Log($"二次判断删除", $"{liPhotoIndex}-{testCnt}", WarningEnum.Normal, false);
lstEditDefect = defectPuaseList.Where(m => m.PhotoIndex == liPhotoIndex).ToList();
if (lstEditDefect.Count > 0 && defectPuaseImgList.Count > 0)
{
Mat mt;
defectPuaseImgList.TryRemove(lstEditDefect[0].PhotoIndex, out mt);
}
//foreach (var item in lstEditDefect)
{
lock (lock_defectPuase)
{
defectPuaseList.RemoveAll(m => m.PhotoIndex == liPhotoIndex);
//defectPuaseList.Remove(item);
}
}
}
else
Log($"二次判断2", $"(图像{liPhotoIndex})-缺陷未获得", WarningEnum.Low, false);
}
Log($"图像预处理", $"(图像{Cam1Cnt - 1})-处理2次判定:{stopWatch.ElapsedMilliseconds}", WarningEnum.Normal, false);
//else
// Log($"二次判断2", $"(图像{liPhotoIndex})-处理未跟上", WarningEnum.Low, false);
}
//time += $"->处理2次判定({stopWatch.ElapsedMilliseconds})";
}
#endregion
#region 相机图片保存
errStep = 4;
//保存图片
if (confMgr.SysConfigParams.CamImag.AutoSave && !string.IsNullOrEmpty(confMgr.SysConfigParams.CamImag.SavePath))
{
stopWatch.Restart();
string dirPath = Util.CreateSubDir(confMgr.SysConfigParams.CamImag.SavePath, new List { $"{curRecord.BarCode}_{curRecord.BarCodeName}" });
AddImageSave($"{dirPath}Cam1-{Cam1Cnt}.bmp", acq1);
AddImageSave($"{dirPath}Cam2-{Cam2Cnt}.bmp", acq2);
Log($"图像预处理", $"(图像{Cam1Cnt - 1})-相机图片保存:{stopWatch.ElapsedMilliseconds}", WarningEnum.Normal, false);
}
if (_matList2.Count > listCntMax)
{
Log($"堆积过多", $"相机-缓存{_matList2.Count}大于{listCntMax}", WarningEnum.High);
//_matList2.Dequeue();
System.GC.Collect();
}
#endregion
//预处理
stopWatch.Restart();
#region 去重
if (confMgr.SysConfigParams.MidCoin > 0)//中间重合部分
{
errStep = 6;
int width = acq1.Width - confMgr.SysConfigParams.MidCoin / 2;
acq1 = OpencvUtils.CutImage(acq1, confMgr.SysConfigParams.MidCoin / 2, 0, width, acq1.Height);
acq2 = OpencvUtils.CutImage(acq2, 0, 0, width, acq2.Height);
time += $"->相机-去重({stopWatch.ElapsedMilliseconds})";
}
#endregion
#region 裁边
errStep = 7;
//左裁边
int marginWidth0;
acq1 = OpencvUtils.getMaxInsetRect2(acq1, false, confMgr.SysConfigParams.HolePx, out marginWidth0);
//右裁边
acq2 = OpencvUtils.getMaxInsetRect2(acq2, true, confMgr.SysConfigParams.HolePx, out marginWidth0);
time += $"->相机裁边({stopWatch.ElapsedMilliseconds})";
#endregion
#region 拼接
errStep = 8;
//水平合并l
Mat mat;
mat = OpencvUtils.MergeImage_sameSize(new Mat[] { acq2, acq1 });
time += $"->图1+2合并({stopWatch.ElapsedMilliseconds})";
#endregion
#region 镜像
errStep = 5;
//图像镜像
mat = mat.Flip(FlipMode.XY);
time += $"->相机翻转({stopWatch.ElapsedMilliseconds})";
#endregion
#region 填充
errStep = 9;
//比例缩放图片
int xw;
int resizeWidth = OpencvUtils.GetWidthForResize(acq1.Width + acq2.Width - confMgr.SysConfigParams.MidCoin);
if (resizeWidth == 0)
throw new Exception("GetWidthForResize result 0 失败!");
var resize = new System.Drawing.Size(resizeWidth, OpencvUtils.image_height * 2);//固定8192*2张*4096
mat = OpencvUtils.Resize(mat, resize.Width, resize.Height, out xw);
time += $"->填充({stopWatch.ElapsedMilliseconds})";
#endregion
#region 处理
errStep = 10;
defectLib.add(new DefectTask()
{
modelName = curRecord.ProductInfo.ModelName,
record = curRecord,
bmp = mat,
bmpTag = mat.Clone(),
photoIndex = Cam1Cnt - 1,//0-n 首张必需为0,因下面计算长度是从0开始
widthRatio = 1.0f,//等比例缩放,高度不变
qualifiedLimitList = curRecord.ProductInfo.QualifiedLimitList,
labelDic = GetDefectCode(),
finishEvent = callBackDefectEvent,
xw = xw,
cm2px_x = confMgr.SysConfigParams.Cm2px_x,
cm2px_y = confMgr.SysConfigParams.Cm2px_y,
expand_pixel = confMgr.SysConfigParams.Expand_pixel,
});
curRecord.ScannerPhotoCount++;
errStep = 11;
time += $"->加入瑕疵待检队列({stopWatch.ElapsedMilliseconds})";
#endregion
#region 门幅
float faceWidthX_cm = (float)Math.Round((Cam1Cnt) * mat.Height * 1.0f / confMgr.SysConfigParams.Cm2px_y, 2);
float faceWidthY_cm = (float)Math.Round((mat.Width + confMgr.SysConfigParams.HolePx * 2) * 1.0f / confMgr.SysConfigParams.Cm2px_x, 2);
if (curRecord.FaceWidthMin == 0 || curRecord.FaceWidthMin > faceWidthY_cm)
curRecord.FaceWidthMin = faceWidthY_cm;
if (curRecord.FaceWidthMax < faceWidthY_cm)
curRecord.FaceWidthMax = faceWidthY_cm;
var point = new float[] { faceWidthX_cm, faceWidthY_cm };
curRecord.FacePointList.Add(point);
errStep = 12;
//判定门幅
//if (x < XSizeRange[0])
// Log($"绘图", $"门幅宽度超限 1!!!! {x}<{XSizeRange[0]}", WarningEnum.High);
//if (x > XSizeRange[1])
// Log($"绘图", $"门幅宽度超限 2!!!! {x}>{XSizeRange[1]}", WarningEnum.High);
//if (item[1] < YSizeRange[0])
// Log($"绘图", $"门幅宽度超限 3!!!! {item[1]}<{YSizeRange[0]}", WarningEnum.High);
//if (item[1] > YSizeRange[1])
// Log($"绘图", $"门幅宽度超限 4!!!! {item[1]}>{YSizeRange[1]}", WarningEnum.High);
//显示门幅绘图
OnAutoRuning(new RunEventArgs(curRecord.FacePointList));
errStep = 13;
time += $"->门幅刷新({stopWatch.ElapsedMilliseconds})";
#endregion
#region 长度剩余提醒
errStep = 14;
//长度剩余提醒
if (CurrProductModel.residueWarnningLen > 0 && curRecord.ErpLen > 0 && CurrProductModel.residueWarnningLen >= curRecord.ErpLen - curRecord.Len)
{
Log($"长度告警", $"已达剩余长度不足提醒!({curRecord.ErpLen - curRecord.Len}<={CurrProductModel.residueWarnningLen})", WarningEnum.Low);
}
#endregion
}
catch (Exception ex)
{
curRecord.ScannerPhotoFinishCount++;//失败时不能因数量不一致无法保存
Log($"图像预处理", $"异常({errStep}):(图像{Cam1Cnt-1})-{ex.Message}", WarningEnum.High);
//string dirPath = FileUtil.initFolder($"{Config.ImagePath}{curRecord.BatchId}_{curRecord.ReelId}\\Err\\");
//OpenCvSharp.Extensions.BitmapConverter.ToBitmap(scanPhotos0.mat).Save($"{dirPath}{scanPhotos0.photoIndex}_0_Step{errStep}.bmp", ImageFormat.Bmp);
//OpenCvSharp.Extensions.BitmapConverter.ToBitmap(scanPhotos1.mat).Save($"{dirPath}{scanPhotos1.photoIndex}_1_Step{errStep}.bmp", ImageFormat.Bmp);
}
finally
{
Log($"图像预处理", $"(图像{Cam1Cnt - 1})-进度计时:{time}", WarningEnum.Normal, false);
//task = null;
//System.GC.Collect();
}
}
else
continue;
#endregion
#else
#region 长度剩余提醒
//长度剩余提醒
Records curRecord = Hashtable.Synchronized(htTask)[currKey] as Records;
if (CurrProductModel.residueWarnningLen > 0 && curRecord.ErpLen > 0 && CurrProductModel.residueWarnningLen >= curRecord.ErpLen - curRecord.Len)
{
Log($"长度告警", $"已达剩余长度不足提醒!({curRecord.ErpLen - curRecord.Len}<={CurrProductModel.residueWarnningLen})", WarningEnum.Low);
}
#endregion
#region 图像裁边预处理
//预处理,队列都有数据,且数据长度一致
#if Online_defect
ScanPhotoInfo peek1;
ScanPhotoInfo peek2;
if (_matList1.Count > 0 && _matList2.Count > 0 )
{
_matList1.TryPeek(out peek1);
_matList2.TryPeek(out peek2);
if (peek1 != null && peek2 !=null && peek1.photoIndex != peek2.photoIndex)
continue;
Stopwatch stopWatch = new Stopwatch();
ScanPhotoInfo scanPhotos0;
if(!_matList1.TryDequeue(out scanPhotos0))
Log($"图像出队列", $"异常相机1队列出队失败", WarningEnum.High);
ScanPhotoInfo scanPhotos1;
if(!_matList2.TryDequeue(out scanPhotos1))
Log($"图像出队列", $"异常相机2队列出队失败", WarningEnum.High);
//Log($"图像出队列", $"相机1-{scanPhotos0.photoIndex}", WarningEnum.Normal, false);
curRecord.dicPhoto_Defect.TryAdd(scanPhotos0.photoIndex, false);//加入索引,默认无瑕疵
//Log($"图像拼接处理", $"相机1-{scanPhotos0.photoIndex},相机2-{scanPhotos1.photoIndex}", WarningEnum.Normal, false);
string time = "";
stopWatch.Start();
try
{
Mat mat;
Mat mat0;
Mat mat1;
//lock (_lockOpenCV)
{
if (scanPhotos0.mat.Height != scanPhotos1.mat.Height)
{
Log($"警告", $"两相机采集图高度不一致({scanPhotos0.photoIndex}),dev1.Height={scanPhotos0.mat.Height},dev2.Height={scanPhotos1.mat.Height},重新resize...", WarningEnum.Low);
if (scanPhotos0.mat.Height > scanPhotos1.mat.Height)
scanPhotos1.mat = OpencvUtils.ResizeMat(scanPhotos1.mat, scanPhotos0.mat.Width, scanPhotos0.mat.Height);
else
scanPhotos0.mat = OpencvUtils.ResizeMat(scanPhotos0.mat, scanPhotos1.mat.Width, scanPhotos1.mat.Height);
}
errStep = 1;
//反转+相机索引调换
mat1 = scanPhotos1.mat;
mat0 = scanPhotos0.mat;
//水平合并l
mat = OpencvUtils.MergeImage_sameSize(new Mat[] { mat0, mat1 });//这里相机反装,左右反转下
//Log($"合并", $"(图像{scanPhotos0.photoIndex})-裁边去孔洞后:({mat0.Width}+{mat1.Width});合并后(去孔洞):{mat.Width}*{mat.Height}", WarningEnum.Normal, false);
//float widthRatio = mat.Width * 1.0f / resize.Width;//宽度比例
time += $"->图1+2合并({stopWatch.ElapsedMilliseconds})";
}
errStep = 2;
//门幅更新(含两侧孔洞)x,y cm
float faceWidthX_cm = (float)Math.Round((scanPhotos0.photoIndex + 1) * mat.Height * 1.0f / confMgr.SysConfigParams.Cm2px_y, 2);
float faceWidthY_cm = (float)Math.Round((mat.Width + confMgr.SysConfigParams.HolePx * 2) * 1.0f / confMgr.SysConfigParams.Cm2px_x, 2);
#else
string imgfilePath = "C:\\Users\\fang\\Desktop\\新建文件夹\\boyi lou";
if (!Directory.Exists(imgfilePath))
{
Log($"图像处理", $"模拟错误-路径错误{imgfilePath}", WarningEnum.High);
break;
}
string[] files = Directory.GetFiles(imgfilePath, $"*.bmp", SearchOption.TopDirectoryOnly);
if (files.Length > 0 && Cam1Cnt < files.Length)
{
Stopwatch stopWatch = new Stopwatch();
string time = "";
//stopWatch.Start();
ScanPhotoInfo scanPhotos0 = new ScanPhotoInfo(0, Cam1Cnt, new Mat(4096, 4096 * 2, MatType.CV_8UC3, new Scalar(0, 0, 0)));
ScanPhotoInfo scanPhotos1 = new ScanPhotoInfo(1, Cam1Cnt, new Mat(4096, 4096 * 2, MatType.CV_8UC3, new Scalar(0, 0, 0)));
stopWatch.Start();
errStep = 0;
try
{
Log($"图像处理", $"模拟{files[Cam1Cnt]}");
Mat mat = new Mat(files[Cam1Cnt]);
Cam1Cnt++;
Mat mat0 = scanPhotos1.mat;
Mat mat1 = scanPhotos0.mat;
float faceWidthX_cm = (float)Math.Round((scanPhotos0.photoIndex + 1) * mat.Height * 1.0f / confMgr.SysConfigParams.Cm2px_y, 2);
float faceWidthY_cm = (float)Math.Round((mat.Width + confMgr.SysConfigParams.HolePx * 2) * 1.0f / confMgr.SysConfigParams.Cm2px_x, 2);
#endif
//显示图片
//OnAutoRuning(new RunEventArgs(mat.Clone()));
//faceWidthX_cm = (float)Math.Round(faceWidthX_cm, 2);
//faceWidthY_cm = (float)Math.Round(faceWidthY_cm, 2);
if (curRecord.FaceWidthMin == 0 || curRecord.FaceWidthMin > faceWidthY_cm)
curRecord.FaceWidthMin = faceWidthY_cm;
if (curRecord.FaceWidthMax < faceWidthY_cm)
curRecord.FaceWidthMax = faceWidthY_cm;
var point = new float[] { faceWidthX_cm, faceWidthY_cm };// new System.Drawing.PointF(faceWidthX_cm, faceWidthY_cm);
//Log($"门幅", $"(图像{scanPhotos0.photoIndex})-({scanPhotos0.photoIndex})位置:{point[0]}; 幅宽:{point[1]}", WarningEnum.Normal, false);
curRecord.FacePointList.Add(point);
errStep = 3;
//判定门幅
//if (x < XSizeRange[0])
// Log($"绘图", $"门幅宽度超限 1!!!! {x}<{XSizeRange[0]}", WarningEnum.High);
//if (x > XSizeRange[1])
// Log($"绘图", $"门幅宽度超限 2!!!! {x}>{XSizeRange[1]}", WarningEnum.High);
//if (item[1] < YSizeRange[0])
// Log($"绘图", $"门幅宽度超限 3!!!! {item[1]}<{YSizeRange[0]}", WarningEnum.High);
//if (item[1] > YSizeRange[1])
// Log($"绘图", $"门幅宽度超限 4!!!! {item[1]}>{YSizeRange[1]}", WarningEnum.High);
//显示门幅绘图
OnAutoRuning(new RunEventArgs(curRecord.FacePointList));
errStep = 7;
time += $"->门幅刷新({stopWatch.ElapsedMilliseconds})";
//去除两侧孔洞(门幅计算时不能去除)
//if (Config.MarginHoleWidth > 0)
// mat = OpenCVUtil.cutImage(mat, Config.MarginHoleWidth, 0, mat.Width - Config.MarginHoleWidth * 2, mat.Height);
#region 速度
//计算速度
if (!confMgr.SysConfigParams.OpenLengthCount)
{
double lenMi = Math.Round(faceWidthX_cm / 100, 2);
curRecord.Len = lenMi;
curRecord.TimeLen = pStopWatch.ElapsedMilliseconds / 1000.0d / 60.0d;//总时间 分
double aveSpd = Math.Round(lenMi / curRecord.TimeLen, 2);
//显示平均速度
OnAutoRuning(new RunEventArgs(lenMi, aveSpd));
errStep = 9;
time += $"->速度刷新({stopWatch.ElapsedMilliseconds})";
}
#endregion
#if false
#region 处理2次判定
if (!confMgr.SysConfigParams.OpenLengthCountStop)
{
//处理2次判定
//暂停:瑕疵二次判断
if (DefectPauseForUser && defectPuaseList.Count > 0)
{
errStep = 11;
int liPhotoIndex = scanPhotos0.photoIndex - confMgr.SysConfigParams.StopImageCnt;
//Log($"二次判断2", $"图像{scanPhotos0.photoIndex} {liPhotoIndex}={scanPhotos0.photoIndex}-{confMgr.SysConfigParams.StopImageCnt};{JsonConvert.SerializeObject(curRecord.dicPhoto_Defect)}", WarningEnum.Normal, false);
if (liPhotoIndex >= 0 && curRecord.dicPhoto_Defect[liPhotoIndex] && curRecord.DefectInfoList != null)
{
errStep = 12;
List lstEditDefect = defectPuaseList.Where(m => m.PhotoIndex == liPhotoIndex).ToList();
Log($"二次判断2", $"(图像{liPhotoIndex})已达观察台,瑕疵二次判断=》({string.Join(",", lstEditDefect.Select(m => m.Code).ToArray())})是否包含在({string.Join(",", curRecord.ProductInfo.DefectPauseOption.ToArray())})中。", WarningEnum.Normal, false);
//瑕疵选项过滤
if (curRecord.ProductInfo.DefectPauseOption.Count == 0 || lstEditDefect.Where(x => curRecord.ProductInfo.DefectPauseOption.Contains(x.Code)).Count() > 0)
{
Log($"二次判断2", $"(图像{liPhotoIndex})需瑕疵二次判断,已达观察台,进入暂停。");
// if (lstEditDefect.Where(x => x.Code == "jietou").Count() > 0)
if (lstEditDefect.Where(x => DefectItemsPuaseNameList.Contains(x.Name)).Count() > 0)
{
Stop();
//获取完整数据
Thread.Sleep(500);
lstEditDefect = defectPuaseList.Where(m => m.PhotoIndex == liPhotoIndex).ToList();
//获取完整数据
#region 二级界面
#region 加载界面
if (defectPuaseImgList.ContainsKey(liPhotoIndex))
{
var pimage = (Bitmap)defectPuaseImgList[liPhotoIndex].ToBitmap().Clone();
Task.Run(() =>
{
int liDefectCount = lstEditDefect.Count;
ImageShowFrm frmDefect = new ImageShowFrm(lstEditDefect, pimage);
//frmDefect.Show();
if (frmDefect.ShowDialog() == DialogResult.OK)
{
SysMgr.Instance.DelDefectEdit(curRecord, frmDefect.lstDel);
OnAutoRuning(new RunEventArgs(liPhotoIndex, lstEditDefect, curRecord, defectPuaseImgList[liPhotoIndex], frmDefect.lstDel));
//double len = (double)this.lblLen.Tag;
//this.reDrawDefectPoints(curRecord.DefectInfoList, new double[] { 0, Math.Round(curRecord.FaceWidthMax + 0.005f, 2) }, new double[] { 0, len });
Log($"二次检测2", $"本次忽略{frmDefect.lstDel.Count}个瑕疵,本张图由{liDefectCount} -> {lstEditDefect.Count},总数{curRecord.DefectInfoList.Count}");
}
else
{
OnAutoRuning(new RunEventArgs(liPhotoIndex, lstEditDefect, curRecord, defectPuaseImgList[liPhotoIndex], null));
}
});
}
else
Log($"二次检测2", $"本次图像已检测完成");
#endregion
//OnAutoRuning(new RunEventArgs(liPhotoIndex, lstEditDefect, curRecord, defectPuaseImgList[liPhotoIndex]));
#endregion
}
errStep = 18;
}
Log($"二次判断删除", $"{liPhotoIndex}-{testCnt}", WarningEnum.Normal, false);
lock (lock_defectPuase)
{
lstEditDefect = defectPuaseList.Where(m => m.PhotoIndex == liPhotoIndex).ToList();
if (lstEditDefect.Count > 0 && defectPuaseImgList.Count > 0)
defectPuaseImgList.Remove(lstEditDefect[0].PhotoIndex);
foreach (var item in lstEditDefect)
{
defectPuaseList.Remove(item);
}
}
}
}
time += $"->处理2次判定({stopWatch.ElapsedMilliseconds})";
}
#endregion
#endif
//幅宽判断是否为结束
if (scanPhotos0.photoIndex > 5 && Math.Abs(_NarmalWidth - faceWidthY_cm) > confMgr.SysConfigParams.EndEdgeOffset && _DefectEnd >= 1)
{
//出现第二次判断没有边缘
Log($"图像处理", $"边缘异常或者未找到边缘当作空跑处理:(图像{scanPhotos0.photoIndex})", WarningEnum.Normal, true);
}
else if (scanPhotos1.EdgeSts == false && scanPhotos0.EdgeSts == false && _DefectEnd >= 1)
{
//出现第二次判断没有边缘
Log($"图像处理", $"边缘异常或者未找到边缘当作空跑处理:(图像{scanPhotos0.photoIndex})", WarningEnum.Normal, true);
}
else
{
if (scanPhotos0.photoIndex > 5 && Math.Abs(_NarmalWidth - faceWidthY_cm) > confMgr.SysConfigParams.EndEdgeOffset)
_DefectEnd++;//没边计数
else if (scanPhotos1.EdgeSts == false && scanPhotos0.EdgeSts == false)
_DefectEnd++;//没边计数
else
{
_DefectEnd = 0; //有边的情况重置
//计算正常幅宽
_NarmalWidth = faceWidthY_cm;
}
//----缺陷队列
//比例缩放图片
int xw;
int resizeWidth = OpencvUtils.GetWidthForResize(mat0.Width + mat1.Width - confMgr.SysConfigParams.MidCoin);
if (resizeWidth == 0)
throw new Exception("GetWidthForResize result 0 失败!");
var resize = new System.Drawing.Size(resizeWidth, OpencvUtils.image_height * 2);//固定8192*2张*4096
mat = OpencvUtils.Resize(mat, resize.Width, resize.Height, out xw);
//Log($"图像处理", $"(图像{scanPhotos0.photoIndex})-合成图resize后:{mat.Width}*{mat.Height}", WarningEnum.Normal, false);
defectLib.add(new DefectTask()
{
modelName = curRecord.ProductInfo.ModelName,
record = curRecord,
bmp = mat,
bmpTag = mat.Clone(),
photoIndex = scanPhotos0.photoIndex,//0-n 首张必需为0,因下面计算长度是从0开始
widthRatio = 1.0f,//等比例缩放,高度不变
qualifiedLimitList = curRecord.ProductInfo.QualifiedLimitList,
labelDic = GetDefectCode(),
finishEvent = callBackDefectEvent,
xw = xw,
cm2px_x = confMgr.SysConfigParams.Cm2px_x,
cm2px_y = confMgr.SysConfigParams.Cm2px_y,
expand_pixel = confMgr.SysConfigParams.Expand_pixel,
});
curRecord.ScannerPhotoCount++;
errStep = 10;
time += $"->加入瑕疵待检队列({stopWatch.ElapsedMilliseconds})";
}
}
catch (Exception ex)
{
curRecord.ScannerPhotoFinishCount++;//失败时不能因数量不一致无法保存
Log( $"图像处理", $"异常({errStep}):(图像{scanPhotos0.photoIndex})-{ex.Message}", WarningEnum.High);
//string dirPath = FileUtil.initFolder($"{Config.ImagePath}{curRecord.BatchId}_{curRecord.ReelId}\\Err\\");
//OpenCvSharp.Extensions.BitmapConverter.ToBitmap(scanPhotos0.mat).Save($"{dirPath}{scanPhotos0.photoIndex}_0_Step{errStep}.bmp", ImageFormat.Bmp);
//OpenCvSharp.Extensions.BitmapConverter.ToBitmap(scanPhotos1.mat).Save($"{dirPath}{scanPhotos1.photoIndex}_1_Step{errStep}.bmp", ImageFormat.Bmp);
}
finally
{
Log($"图像处理", $"(图像{scanPhotos0.photoIndex})-进度计时:{time}", WarningEnum.Normal, false);
scanPhotos0.mat.Dispose();
scanPhotos1.mat.Dispose();
scanPhotos0 = scanPhotos1 = null;
//task = null;
//System.GC.Collect();
}
}
#endregion
#endif
Thread.Sleep(20);
} while (!isBreakProcessRun());
//暂停中断
//stopWatch.Stop();
pStopWatch.Stop();
_isRuning = false;
}
#if Online_One
else
{
//防止内存爆满
AcquisitionMat tacq1 = _LinecamDev1.GetFrames(10);
AcquisitionMat tacq2 = _LinecamDev2.GetFrames(10);
}
#endif
Thread.Sleep(20);
}
catch (Exception e)
{
_isRuning = false;
Log("运行报警", $"流程运行出错{errStep}:" + e.Message + "\n", WarningEnum.High);
}
}
}
#endregion
#region 模型label
private JArray _defectItemList;
///
/// 获取模型对应标签信息
///
private void GetDefectAllLabel()
{
string labels = CurrProductModel.ModelName.Replace(".trt", ".json");
string configPath = confMgr.SysConfigParams.AIModelPath + $"\\{labels}";
string lsTmp = File.ReadAllText(configPath);
JArray defectItemList = JArray.Parse(lsTmp);
_defectItemList = defectItemList;
//var item = defectItemList.FirstOrDefault(m => m.Value("id") == id);
//if (item == null)
// return null;
//return (JObject)item;
}
public JArray GetDefectItemList()
{ return _defectItemList; }
///
/// 根据id获取标签信息
///
///
///
public JObject GetDefectLabel(int id)
{
if (_defectItemList != null && _defectItemList.Count > 0)
{
var item = _defectItemList.FirstOrDefault(m => m.Value("id") == id);
if (item == null)
return null;
return (JObject)item;
}
else
return null;
}
///
/// 根据name获取标签信息
///
///
///
public JObject GetDefectLabel(string name)
{
if (_defectItemList != null && _defectItemList.Count > 0)
{
var item = _defectItemList.FirstOrDefault(m => m.Value("name") == name);
if (item == null)
return null;
return (JObject)item;
}
else
return null;
}
public JObject GetDefectLabel(string modelName, string name)
{
string labels = modelName.Replace(".trt", ".json");
string configPath = confMgr.SysConfigParams.AIModelPath + $"\\{labels}";
string lsTmp = File.ReadAllText(configPath);
JArray defectItemList = JArray.Parse(lsTmp);
if (defectItemList != null && defectItemList.Count > 0)
{
var item = defectItemList.FirstOrDefault(m => m.Value("name") == name);
if (item == null)
return null;
return (JObject)item;
}
else
return null;
}
public string GetDefectName(string code)
{
if (_defectItemList != null && _defectItemList.Count > 0)
{
var item = _defectItemList.FirstOrDefault(m => m.Value("code") == code);
if (item == null)
return null;
return item.Value("name");
}
else
return null;
}
public string GetDefectName(string modelName, string code)
{
string labels = modelName.Replace(".trt", ".json");
string configPath = confMgr.SysConfigParams.AIModelPath + $"\\{labels}";
string lsTmp = File.ReadAllText(configPath);
JArray defectItemList = JArray.Parse(lsTmp);
if (defectItemList != null && defectItemList.Count > 0)
{
var item = defectItemList.FirstOrDefault(m => m.Value("code") == code);
if (item == null)
return null;
return item.Value("name");
}
else
return null;
}
public Dictionary GetDefectCode()
{
Dictionary dic = new Dictionary();
for (int i = 0; i < _defectItemList.Count; i++)
{
var tt = _defectItemList[i];
dic.Add(tt.Value("id"), tt.Value("code"));
}
return dic;
}
#endregion
#region 推理完成处理
private void callBackDefectEvent(DefectTask res)
{
{
int step = 0;
try
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string time = "";
//Log($"检测完成", $"图像队列:{res.record.ScannerPhotoFinishCount + 1}/{res.record.ScannerPhotoCount} (图像{res.photoIndex})检测结果:{res.isSucceed}", WarningEnum.Normal, false);
//string dirPath = FileUtil.initFolder($"{Config.ImagePath}{res.record.BatchId}_{res.record.ReelId}\\");
//string dirSourcePath = FileUtil.initFolder($"{Config.ImagePath}{res.record.BatchId}_{res.record.ReelId}\\源图\\");
//Cv2.Flip(res.bmp, res.bmp, FlipMode.XY);//翻转
//显示打标图片
if (res.excelTable.Rows.Count > 0)
OnAutoRuning(new RunEventArgs(res.bmpTag));
else
OnAutoRuning(new RunEventArgs(res.bmp));
string dirPath = Util.CreateSubDir(confMgr.SysConfigParams.DefectSrcImag.SavePath, new List { $"{ res.record.BarCode}_{ res.record.BarCodeName}_{ImgDirSN}" });
if (confMgr.SysConfigParams.DefectSrcImag.AutoSave)//保存所有原图
{
AddImageSave($"{dirPath}{res.photoIndex}.bmp", res.bmp);
//OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.bmp).Save($"{dirPath}{res.photoIndex}.bmp", ImageFormat.Bmp);
}
if (res.isSucceed)
{
step = 1;
Log($"检测完成", $"(图像{res.photoIndex})-瑕疵检测完成,共{res.excelTable.Rows.Count}个瑕疵!各环节用时:{string.Join(",", res.stopwatch)}", WarningEnum.Normal, false);
//AddTextEvent(DateTime.Now,$"打标完成", $"第 ({res.photoIndex}) 张照片,计算过程:{res.resultInfo}");
//if (!Config.IsSaveAllImage && Config.IsSaveDefectSourceImage)
// OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.bmp).Save($"{dirSourcePath}{res.photoIndex}.bmp", ImageFormat.Bmp);
time += $"(图像{res.photoIndex})";
step = 2;
if (res.excelTable.Rows.Count > 0)
{
res.record.dicPhoto_Defect[res.photoIndex] = true;//改为此图有瑕疵
step = 3;
res.record.DefectTotalCount += res.excelTable.Rows.Count;
if (res.record.DefectInfoList == null)
res.record.DefectInfoList = new List();
step = 4;
JObject defectNameInfo;
DefectInfo defectInfo = null;
List