#define Online
using BarTenderPrint;
using CCWin.Win32.Const;
using GeBoShi.ImageDefect;
using HalconDotNet;
using HZH_Controls.Forms;
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.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using ToolKits.Disk;
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 UserMgr userMgr;
public 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 int listCntMax = 5;
private int Cam1Cnt = 0;
private int Cam2Cnt = 0;
#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)
{
devIndex = _devIndex;
photoIndex = _photoIndex;
mat = _mat;
}
public int devIndex { get; set; }
///
/// 0-n
///
public int photoIndex { get; set; }
public string path { get; set; }
public Mat mat { get; set; }
}
#endregion
private Queue _matList1 = new Queue();
private Queue _matList2 = new Queue();
private Service.ProductService PdtService = new Service.ProductService();
private Service.RecordsService RecordService = new Service.RecordsService();
#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 CancellationTokenSource _cts;
#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 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 = "";
InitLog("系统开始初始化...");
//Thread.Sleep(200);
// 加载系统配置
InitLog("加载系统参数...");
ret = confMgr.LoadSystemConfig();
if (!ret)
{
throw new Exception("系统参数加载失败...");
}
InitLog("系统参数加载完成!");
//根据llog路径,开始记录日志
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();
_Cam1Thread = new Thread(() =>
{
Cam1ThreadFunction();
});
_Cam1Thread.IsBackground = true;
_Cam1Thread.Start();
_Cam2Thread = new Thread(() =>
{
Cam2ThreadFunction();
});
_Cam2Thread.IsBackground = true;
_Cam2Thread.Start();
}
#endregion
#region 后台
///
/// 中断工序运行
///
///
private bool isBreakProcessRun()
{
return statusMgr.Status == SystemStsEnum.Pause || statusMgr.Warning == WarningEnum.High;
}
///
/// 相机1采图预处理
///
private void Cam1ThreadFunction()
{
while (true)
{
try
{
if (_cts.IsCancellationRequested)
break;
if (IsRuning)
{
////暂停开始
//stopWatch.Start();
do
{
#region 实时采图
#if Online
//采集图片
Acquisition acq = _LinecamDev1.GetFrames(1, 10);
if (acq.GrabStatus == "GrabPass")
{
//显示
OnAutoRuning(new RunEventArgs(1, acq.Image));
lock (lockCurrKey)
{
//存在数据队列
if (currKey != 0 || htTask.ContainsKey(currKey))
{
Mat img = CamDev.HImageToMat(acq.Image.CopyObj(1, -1));
if (_matList1.Count > listCntMax)
{
_matList1.Dequeue();
System.GC.Collect();
}
//预处理
Stopwatch stopWatch = new Stopwatch();
Log($"图像预处理", $"相机1-{Cam1Cnt}");
string time = "";
stopWatch.Start();
int errStep = 0;
Mat mat = img;
try
{
errStep = 1;
//反转+相机索引调换
//裁边,两侧和中间重合部分
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})";
}
Log($"裁边", $"(相机1-图像{Cam1Cnt})-左图去重后:{mat.Width}*{mat.Height}," + $"重复值:{confMgr.SysConfigParams.MidCoin / 2}");
errStep = 4;
//左裁边
int marginWidth0;
mat = OpencvUtils.getMaxInsetRect2(mat, true, confMgr.SysConfigParams.HolePx, out marginWidth0);
errStep = 5;
time += $"->相机1裁边({stopWatch.ElapsedMilliseconds})";
}
catch (Exception e)
{
Log($"图像处理", $"异常({errStep}):(相机1-图像{Cam1Cnt})-{e.Message}", WarningEnum.High);
}
//Cv2.Flip(img, img, FlipMode.XY);//翻转
_matList1.Enqueue(new ScanPhotoInfo(0, Cam1Cnt++, mat.Clone()));
}
else
Log($"相机1", $"(图像)-未扫码,图像丢弃!", WarningEnum.Low);
}
}
#endif
#endregion
Thread.Sleep(50);
} while (!isBreakProcessRun());
//暂停中断
//stopWatch.Stop();
pStopWatch.Stop();
//_isRuning = false;
}
Thread.Sleep(10);
}
catch (Exception e)
{
_isRuning = false;
Log("运行报警", "相机1流程运行出错:" + e.Message + "\n", WarningEnum.High);
}
}
}
///
/// 相机2采图预处理
///
private void Cam2ThreadFunction()
{
while (true)
{
try
{
if (_cts.IsCancellationRequested)
break;
if (IsRuning)
{
////暂停开始
//stopWatch.Start();
do
{
#region 实时采图
#if Online
//采集图片
Acquisition acq = _LinecamDev2.GetFrames(1, 10);
if (acq.GrabStatus == "GrabPass")
{
//显示
OnAutoRuning(new RunEventArgs(2, acq.Image));
lock (lockCurrKey)
{
//存在数据队列
if (currKey != 0 || htTask.ContainsKey(currKey))
{
Mat img = CamDev.HImageToMat(acq.Image.CopyObj(1, -1));
if (_matList2.Count > listCntMax)
{
_matList2.Dequeue();
System.GC.Collect();
}
//预处理
Stopwatch stopWatch = new Stopwatch();
Log($"图像预处理", $"相机2-{Cam2Cnt}");
string time = "";
stopWatch.Start();
int errStep = 0;
Mat mat = img;
try
{
errStep = 1;
//反转+相机索引调换
//裁边,两侧和中间重合部分
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})";
}
Log($"裁边", $"(相机2-图像{Cam2Cnt})-右图去重后:{mat.Width}*{mat.Height}," + $"重复值:{confMgr.SysConfigParams.MidCoin / 2}");
errStep = 4;
//右裁边
int marginWidth0;
mat = OpencvUtils.getMaxInsetRect2(mat, false, confMgr.SysConfigParams.HolePx, out marginWidth0);
errStep = 5;
time += $"->相机2裁边({stopWatch.ElapsedMilliseconds})";
}
catch (Exception e)
{
Log($"图像处理", $"异常({errStep}):(相机2-图像{Cam2Cnt})-{e.Message}", WarningEnum.High);
}
//Cv2.Flip(img, img, FlipMode.XY);//翻转
_matList2.Enqueue(new ScanPhotoInfo(1, Cam2Cnt++, mat.Clone()));
}
else
Log($"相机2", $"(图像)-未扫码,图像丢弃!", WarningEnum.Low);
}
}
#endif
#endregion
Thread.Sleep(50);
} while (!isBreakProcessRun());
//暂停中断
//stopWatch.Stop();
pStopWatch.Stop();
//_isRuning = false;
}
Thread.Sleep(10);
}
catch (Exception e)
{
_isRuning = false;
Log("运行报警", "相机1流程运行出错:" + e.Message + "\n", WarningEnum.High);
}
}
}
///
/// 后台运行主线程
///
private void MainThreadFunction()
{
while (true)
{
try
{
if (_cts.IsCancellationRequested)
break;
if (IsRuning)
{
////暂停开始
//stopWatch.Start();
do
{
#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 处理2次判定
//处理2次判定
#endregion
#region 图像裁边预处理
//预处理,队列都有数据,且数据长度一致
#if Online
if (_matList1.Count > 0 && _matList2.Count > 0 && (_matList1.Count == _matList2.Count))
{
Stopwatch stopWatch = new Stopwatch();
ScanPhotoInfo scanPhotos0 = _matList1.Dequeue();
ScanPhotoInfo scanPhotos1 = _matList2.Dequeue();
Log($"图像拼接处理", $"相机1-{scanPhotos0.photoIndex},相机2-{scanPhotos1.photoIndex}");
string time = "";
stopWatch.Start();
int errStep = 0;
try
{
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;
//反转+相机索引调换
Mat mat0 = scanPhotos1.mat;
Mat mat1 = scanPhotos0.mat;
//水平合并l
Mat mat = OpencvUtils.MergeImage_sameSize(new Mat[] { mat0, mat1 });//这里相机反装,左右反转下
Log($"合并", $"(图像{scanPhotos0.photoIndex})-裁边去孔洞后:({mat0.Width}+{mat1.Width});合并后(去孔洞):{mat.Width}*{mat.Height}");
//float widthRatio = mat.Width * 1.0f / resize.Width;//宽度比例
time += $"->图1+2合并({stopWatch.ElapsedMilliseconds})";
//门幅更新(含两侧孔洞)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 = "E:\\CPL\\测试代码\\革测试\\1-1\\现场原图";
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();
int 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]}");
curRecord.FacePointList.Add(point);
//判定门幅
//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);
//计算速度
double lenMi = Math.Round(faceWidthX_cm / 100, 2);
curRecord.Len = lenMi;
curRecord.TimeLen = pStopWatch.ElapsedMilliseconds / 1000.0d / 60.0d;//总时间 分
//显示速度
OnAutoRuning(new RunEventArgs(lenMi, Math.Round(lenMi / curRecord.TimeLen, 2)));
errStep = 9;
time += $"->速度刷新({stopWatch.ElapsedMilliseconds})";
//----缺陷队列
//比例缩放图片
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}");
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,
});
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}");
scanPhotos0.mat.Dispose();
scanPhotos1.mat.Dispose();
scanPhotos0 = scanPhotos1 = null;
//task = null;
System.GC.Collect();
}
}
#endregion
Thread.Sleep(50);
} while (!isBreakProcessRun());
//暂停中断
//stopWatch.Stop();
pStopWatch.Stop();
_isRuning = false;
}
Thread.Sleep(10);
}
catch (Exception e)
{
_isRuning = false;
Log("运行报警", "流程运行出错:" + 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;
}
///
/// 根据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 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 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
{
Log($"检测完成", $"图像队列:{res.record.ScannerPhotoFinishCount + 1}/{res.record.ScannerPhotoCount} (图像{res.photoIndex})检测结果:{res.isSucceed}");
//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);//翻转
string dirPath = Util.CreateSubDir(confMgr.SysConfigParams.DefectSrcImag.SavePath, new List { $"{ res.record.BatchId }_{ res.record.ReelId }" });
if (confMgr.SysConfigParams.DefectSrcImag.AutoSave)//保存所有原图
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)}");
//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);
step = 2;
if (res.excelTable.Rows.Count > 0)
{
res.record.dicPhoto_Defect[res.photoIndex] = true;//改为此图有瑕疵
//有瑕疵打标图必需保存 Jpeg
dirPath = Util.CreateSubDir(confMgr.SysConfigParams.DefectSplicImag.SavePath, new List { $"{res.record.BatchId}_{res.record.ReelId}" });
if (confMgr.SysConfigParams.DefectSplicImag.AutoSave)//保存瑕疵图
OpenCvSharp.Extensions.BitmapConverter.ToBitmap(res.bmpTag).Save($"{dirPath}{res.photoIndex}_tag.jpg", ImageFormat.Jpeg);
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