geboshi_V1/LeatherProject/LeatherApp/Device/DefectLib.cs

1347 lines
71 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using HalconDotNet;
using System.Windows.Forms.VisualStyles;
using LeatherApp.Utils;
using Models;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using PG_Detect;
using SqlSugar;
using HZH_Controls;
namespace LeatherApp.Device
{
public class DefectLib : IDisposable
{
//private const string dll_path = "yoloOrt.dll";
//[DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
//extern static IntPtr CreateDetector(string model_path, string labels_path, bool is_gpu, int numberThreads);
private const string dll_path = "yolo_trt.dll";
[DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
static extern IntPtr CreateDetector(string model_path);
[DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
extern static bool DestroyDetector(IntPtr detector);
/// <summary>
/// 非0值表示成功0表示失败 返回小图张数
/// </summary>
/// <param name="detector"></param>
/// <returns></returns>
[DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
static extern int GetBatchSize(IntPtr detector);
//[DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
//extern static bool Detect1(IntPtr detector, ref byte bgrs_data,
// int image_num, int width, int height, int channels,
// float conf_threshold, float iou_threshold,
// ref int output, int output_size, ref int object_num);
[DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
static extern bool Detect(IntPtr detector, ref byte bgrs_data,
int image_num, int width, int height, int channels,
float conf_threshold, float iou_threshold,
ref float output, int output_size, ref int object_num,
int expand_pixel);
//-----
//private const string dll_path = "yolo_trt .dll";
//[DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
//static extern IntPtr CreateDetector(string model_path);
//[DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
//static extern bool DestroyDetector(IntPtr detector);
//[DllImport(dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
//static extern bool Detect(IntPtr detector, ref byte bgrs_data,
// int image_num, int width, int height, int channels,
// float conf_threshold, float iou_threshold,
// ref int output, int output_size, ref int object_num);
//---
private IntPtr detector = IntPtr.Zero;
private readonly int image_width = 2048;
private readonly int image_hight = 2048;
private readonly int image_channels = 3;
private readonly int image_bytes = 2048 * 2048 * 3;
private readonly int detect_elem_size = 7; //维度数据结果x y w h conf classid
private readonly int detect_max_object_num = 20;//这个指的是一张子图可能最多给你返回的目标个球
//
public Action<int, int> QueueCountEvent;//0/1/2, 数量
public Action<DateTime,WarningEnum, string> WarningEvent;
/// <summary>
/// 检测结果JSON(原图,结果)
/// </summary>
public Action<DefectTask> finishEvent;
/// <summary>
/// 是否打开设备成功
/// </summary>
public bool IsInit { get; private set; } = false;
string rootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
private Thread t_task, t_task_operation ,t_task_maketag;
//=======task list
private List<DefectTask> taskList = new List<DefectTask>();
private List<DefectTask> taskOperationList = new List<DefectTask>();
private List<DefectTask> taskMakeTagList = new List<DefectTask>();
private string preModelName = "";
//传统算法核心
private PGDetect tPGDetect = new PGDetect();
public DefectLib()
{
}
public bool start()
{
try
{
//detector = CreateDetector(Config.model_path, Config.labels_path, true, 6);
//if (detector == IntPtr.Zero)
// throw new Exception("模型初始化失败!");
preModelName = "";
IsInit = true;
taskList.Clear();
taskOperationList.Clear();
taskMakeTagList.Clear();
t_task = new System.Threading.Thread(runStep);
t_task.IsBackground = true;
t_task.Start();
t_task_operation = new System.Threading.Thread(run2);
t_task_operation.IsBackground = true;
t_task_operation.Start();
t_task_maketag = new System.Threading.Thread(run3);
t_task_maketag.IsBackground = true;
t_task_maketag.Start();
return true;
}
catch (Exception ex)
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, ex.Message);
return false;
}
}
public void stop()
{
if (!IsInit) return;
try
{
IsInit = false;
//timer.Elapsed -= Timer_Elapsed;
preModelName = "";
//释放模型
if (detector != IntPtr.Zero)
{
DestroyDetector(detector);
detector = IntPtr.Zero;
}
if (t_task != null)
{
bool b = t_task.Join(5000);
if (!b) t_task.Abort();
t_task = null;
}
if (t_task_operation != null)
{
bool b = t_task_operation.Join(5000);
if (!b) t_task_operation.Abort();
t_task_operation = null;
}
if (t_task_maketag != null)
{
bool b = t_task_maketag.Join(5000);
if (!b) t_task_maketag.Abort();
t_task_maketag = null;
}
taskList.Clear();
taskOperationList.Clear();
taskMakeTagList.Clear();
}
catch { }
}
/// <summary>
///
/// </summary>
/// <param name="sumWidth">多个相机图像总宽(外部去除重合部分)</param>
/// <returns></returns>
public int GetWidthForResize(int sumWidth)
{
int count =(int) Math.Round(sumWidth * 1.0f / image_width, 0);
count = 8;
return count * image_width;
//int count = sumWidth / image_width;
////int remainder = sumWidth % image_width;
//if (count % 2 == 0)
// return count * image_width;
//else
// return count * image_width+ image_width;
}
/// <summary>
/// 保存图片
/// </summary>
/// <param name="Img"></param>图片
/// <param name="pictureUrl"></param>保存路径
/// <param name="pictureName"></param>保存名称
private void SaveImage(Bitmap Img, string pictureUrl, string pictureName)
{
if (!Directory.Exists(pictureUrl))
{
Directory.CreateDirectory(pictureUrl);
}
FileInfo FileUrl = new FileInfo(pictureUrl);//防止路径中有日期导致路径错误
try
{
using (Bitmap bitmap = new Bitmap(Img))
{
using (MemoryStream stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Bmp);
System.Drawing.Image img = System.Drawing.Image.FromStream(stream);
//img.Save(FileUrl +"\\"+ pictureName);
//img.Dispose();
string szURL = FileUrl + "\\" + pictureName;
img.Save(szURL, ImageFormat.Bmp);
img.Dispose();
}
}
}
catch (Exception)
{
if (Img != null)
{
Img.Dispose();
}
}
}
public bool LoadModel(string modelPath)
{
int step = 0;
try
{
if (!Config.OpenHalconDefect)
{
if (preModelName != modelPath)
{
//WarningEvent?.Invoke(DateTime.Now, WarningEnum.Normal, $"模型加载({modelPath})" );
step = 3;
//先释放模型
if (detector != IntPtr.Zero)
{
step = 4;
DestroyDetector(detector);
detector = IntPtr.Zero;
}
step = 5;
detector = CreateDetector($"./models/{modelPath}");
if (detector == IntPtr.Zero)
throw new Exception($"模型({modelPath})初始化失败!");
step = 6;
preModelName = modelPath;
}
}
else
{
HObject obj = new HObject();
Mat mat = new Mat($"./init.bmp");
OpenCVUtil.MatToHObject(mat, out obj);
//HOperatorSet.GenImageConst(out obj, "byte", 2048 * 8, 2048 * 2);//生成一幅图像用byte格式默认是黑色
//Mat initMat = new Mat(2048 * 2, 2048 * 8, MatType.CV_8UC3);
if (!tPGDetect.IniOptimization(obj, Config.HalconParamPath))
throw new Exception($"传统算法({Config.HalconParamPath})初始化失败!");
}
return true;
}
catch (Exception e)
{
WarningEvent?.Invoke(DateTime.Now, WarningEnum.Low, $"Load Model err({step}):" + e.Message);
return false;
}
}
private void runStep()
{
int step = 0;
while (IsInit)
{
if (taskList.Count < 1)
{
Thread.Sleep(20);
continue;
}
//
step = 1;
var task = pop();
try
{
if (task != null)
{
Stopwatch stopwatch = Stopwatch.StartNew();
step =2;
LoadModel(task.modelName);
//源图
//Bitmap bmp = yolo1.Read2Bmp(file_path);
//切割图像输入图像格式14208*10640
stopwatch.Start();
if (!Config.OpenHalconDefect)
{
//task.resizeBmp = OpenCVUtil.resize( task.bmp.Clone(), task.resize.Width, task.resize.Height);//在外面已做了resize
//Cv2.CvtColor(task.bmp, task.bmpBgr2rgb, ColorConversionCodes.BGR2RGB);
//task.bmps_cut = OpenCVToCutsMat(task.bmpBgr2rgb, image_width, image_hight); //这里cut时之前加的clone
step = 7;
task.bmps_cut = OpenCVToCutsMat(task.bmp, image_width, image_hight); //这里cut时之前加的clone
stopwatch.Stop();
task.stopwatch[0] = stopwatch.ElapsedMilliseconds;
//Resize图像
//stopwatch.Restart();
//task.bmps_resize = yolo1.OpenCVToResizesMat(task.bmps_cut, task.resize.Width, task.resize.Height);
//stopwatch.Stop();
//task.stopwatch[1] = stopwatch.ElapsedMilliseconds;
//预处理模型
//stopwatch.Restart();
//task.tensors = yolo1.PreprocessImageMat(task.bmps_resize);
//stopwatch.Stop();
//task.stopwatch[2] = stopwatch.ElapsedMilliseconds;
step = 8;
lock (taskOperationList)
{
taskOperationList.Add(task);
QueueCountEvent?.BeginInvoke(1, taskOperationList.Count, null, null);
}
step = 9;
}
else
{
step = 20;
int object_num = 0;
//转换
OpenCVUtil.MatToHObject(task.bmp, out task.ho_Img);
stopwatch.Stop();
task.stopwatch[0] = stopwatch.ElapsedMilliseconds;
stopwatch.Restart();
step = 21;
//预处理
tPGDetect.Processing(task.ho_Img, out task.ho_imgG, out task.ho_ImageResult3, out task.ho_ImageSub,
Config.HalconParamPath,
out task.hv_RES, out task.hv_gauss_filter1, out task.hv_gauss_filter2,
out task.hv_Energy_value, out task.hv_Region_S_value, out task.hv_AreaThr, out task.hv_class);
stopwatch.Stop();
task.stopwatch[1] = stopwatch.ElapsedMilliseconds;
lock (taskOperationList)
{
taskOperationList.Add(task);
QueueCountEvent?.BeginInvoke(1, taskOperationList.Count, null, null);
}
}
}
}
catch (Exception ex)
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"DefectLib task1 err({step}):" + ex.Message);
task.isSucceed = false;
task.resultInfo = ex.Message;
callback(task);
}
Thread.Sleep(5);
}
}
//推理
private void run2()
{
QualifiedLimit qualifiedLimit;
while (IsInit)
{
if (taskOperationList.Count < 1)
{
Thread.Sleep(20);
continue;
}
//
var task = pop2();
int cut_count=0,step = 0;
try
{
if (task != null && !Config.OpenHalconDefect && task.bmps_cut.Count()>0 )
{
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, "DefectLib tasks 运行推理...");
cut_count = task.bmps_cut.Count();
Stopwatch stopwatch = Stopwatch.StartNew();
//====推理(必需单队列)
stopwatch.Start();
// 把数据转为byte数组【h, w, c】的bgr格式第一张在前第二张在后
byte[] imgData = new byte[image_bytes * cut_count];
for (int i = 0; i < cut_count; i++)
Marshal.Copy(task.bmps_cut[i].Data, imgData, image_bytes * i, image_bytes);
step = 1;
stopwatch.Stop();
task.stopwatch[1] = stopwatch.ElapsedMilliseconds;
stopwatch.Restart();
task.output = new float[cut_count * detect_elem_size * detect_max_object_num];
task.output_num = new int[cut_count];
//执行推理
step =2;
bool ok = Detect(detector, ref imgData[0], cut_count, image_width, image_hight, image_channels,
0.25f, 0.45f, ref task.output[0], task.output.Length, ref task.output_num[0],Config.expand_pixel);
//bool ok = Detect(_detector, ref imgData[0], imgs.Count, ImageWidth, image_hight, image_channels,
// 0.25f, 0.45f, ref output[0], output.Length, ref output_num[0]);
step = 3;
stopwatch.Stop();
task.stopwatch[2] = stopwatch.ElapsedMilliseconds;
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"DefectLib tasks 结果推理={ok}");
for (int i = 0; i < cut_count; i++)
task.bmps_cut[i].Dispose();
if (ok == false)
throw new Exception($"推理失败或者输入数组太小({cut_count}");
//
lock (taskMakeTagList)
{
taskMakeTagList.Add(task);
QueueCountEvent?.BeginInvoke(2, taskMakeTagList.Count, null, null);
}
}
else
{
Stopwatch stopwatch = Stopwatch.StartNew();
stopwatch.Start();
step = 22;
//算法处理
tPGDetect.Detect(task.ho_Img, task.ho_imgG, task.ho_ImageResult3, task.ho_ImageSub,
task.hv_Energy_value, task.hv_Region_S_value, task.hv_AreaThr, task.hv_class,
out task.hv_defectinfo, out task.object_num);
stopwatch.Stop();
task.stopwatch[2] = stopwatch.ElapsedMilliseconds;
lock (taskMakeTagList)
{
taskMakeTagList.Add(task);
QueueCountEvent?.BeginInvoke(2, taskMakeTagList.Count, null, null);
}
}
}
catch (Exception ex)
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"DefectLib task2 err({step}):({cut_count}){ ex.Message}");
task.isSucceed = false;
task.resultInfo = ex.Message;
callback(task);
}
Thread.Sleep(5);
}
}
private class DefectLabelInfo
{
public int x { get; set; }
public int y { get; set; }
public int w { get; set; }
public int h { get; set; }
public int classId { get; set; }
public double confidence { get; set; } //置信度
public double contrast { get; set; }//对比度
public double cmW { get; set; }
public double cmH { get; set; }
public int i { get; set; }//小图index
public int j { get; set; }//缺陷index
}
private double ContrastLow = 0.8;
private double ContrastTop = 1.2;
//private double ContrastToPercent(double val)
//{
// if (val < ContrastLow)
// return 0;
// else if (val > ContrastTop)
// return 100;
// double temp = 100 / (ContrastTop - ContrastLow);
// return temp * (val - ContrastLow);
//}
//private double PercentToContrast(double val)
//{
// double temp = val * (ContrastTop - ContrastLow);
// return temp + ContrastLow;
//}
private double ContrastToPercent(double val)
{
if (val < ContrastLow)
return 0;
else if (val > ContrastTop)
return 100;
double temp = 100 / (ContrastTop - ContrastLow);
return Math.Round(temp * (val - ContrastLow), 2);
}
private double PercentToContrast(double val)
{
double tt = 1;
if (val > 100)
tt = 100;
else if (val < 0)
tt = 0;
else
tt = val;
double temp = tt / 100 * (ContrastTop - ContrastLow);
return temp + ContrastLow;
}
private List<DefectLabelInfo> HeBingDefect(string modelName, int Width, List<DefectLabelInfo> DefectLabelInfoList)
{
List<DefectLabelInfo> outList = new List<DefectLabelInfo>();
List<DefectLabelInfo> HeBingList = new List<DefectLabelInfo>();
List<DefectLabelInfo> XcHeBingList = new List<DefectLabelInfo>();
List<int> xPos = new List<int>();
List<int> yPos = new List<int>();
List<double> ZXD = new List<double>();
List<DefectLabelInfo> HeBingList2 = new List<DefectLabelInfo>();
List<DefectLabelInfo> XcHeBingList2 = new List<DefectLabelInfo>();
List<int> xPos2 = new List<int>();
List<int> yPos2 = new List<int>();
List<double> ZXD2 = new List<double>();
List<DefectLabelInfo> HeBingList3 = new List<DefectLabelInfo>();
List<DefectLabelInfo> XcHeBingList3 = new List<DefectLabelInfo>();
List<int> xPos3 = new List<int>();
List<int> yPos3 = new List<int>();
List<double> ZXD3 = new List<double>();
List<DefectLabelInfo> HeBingList4 = new List<DefectLabelInfo>();
List<DefectLabelInfo> XcHeBingList4 = new List<DefectLabelInfo>();
List<int> xPos4 = new List<int>();
List<int> yPos4 = new List<int>();
List<double> ZXD4 = new List<double>();
DefectLabelInfo stpoint = DefectLabelInfoList[0];
int colNum = Width / image_width;
//寻找在一条线上
for (int q = 0; q < DefectLabelInfoList.Count; q++)
{
if (Config.getDefectCode(modelName, DefectLabelInfoList[q].classId) == "jietou")
{
int max = stpoint.y + 2000;
int min = stpoint.y - 2000 > 0? stpoint.y - 2000 : 0;
if (DefectLabelInfoList[q].y >= min && DefectLabelInfoList[q].y <= max)
{
HeBingList.Add(DefectLabelInfoList[q]);
xPos.Add((DefectLabelInfoList[q].i % colNum) * image_width + DefectLabelInfoList[q].x);
yPos.Add((DefectLabelInfoList[q].i / colNum) * image_hight + DefectLabelInfoList[q].y);
ZXD.Add(DefectLabelInfoList[q].confidence);
}
else
XcHeBingList.Add(DefectLabelInfoList[q]);
}
else if (Config.getDefectCode(modelName, DefectLabelInfoList[q].classId) == "hengdang")
{
int max = stpoint.y + 2000;
int min = stpoint.y - 2000 > 0 ? stpoint.y - 2000 : 0;
if (DefectLabelInfoList[q].y >= min && DefectLabelInfoList[q].y <= max)
{
HeBingList2.Add(DefectLabelInfoList[q]);
xPos2.Add((DefectLabelInfoList[q].i % colNum) * image_width + DefectLabelInfoList[q].x);
yPos2.Add((DefectLabelInfoList[q].i / colNum) * image_hight + DefectLabelInfoList[q].y);
ZXD2.Add(DefectLabelInfoList[q].confidence);
}
else
XcHeBingList2.Add(DefectLabelInfoList[q]);
}
else if (Config.getDefectCode(modelName, DefectLabelInfoList[q].classId) == "jt")
{
int max = stpoint.y + 2000;
int min = stpoint.y - 2000 > 0 ? stpoint.y - 2000 : 0;
if (DefectLabelInfoList[q].y >= min && DefectLabelInfoList[q].y <= max)
{
HeBingList3.Add(DefectLabelInfoList[q]);
xPos3.Add((DefectLabelInfoList[q].i % colNum) * image_width + DefectLabelInfoList[q].x);
yPos3.Add((DefectLabelInfoList[q].i / colNum) * image_hight + DefectLabelInfoList[q].y);
ZXD3.Add(DefectLabelInfoList[q].confidence);
}
else
XcHeBingList3.Add(DefectLabelInfoList[q]);
}
else if (Config.getDefectCode(modelName, DefectLabelInfoList[q].classId) == "tcy")
{
int max = stpoint.y + 2000;
int min = stpoint.y - 2000 > 0 ? stpoint.y - 2000 : 0;
if (DefectLabelInfoList[q].y >= min && DefectLabelInfoList[q].y <= max)
{
HeBingList4.Add(DefectLabelInfoList[q]);
xPos4.Add((DefectLabelInfoList[q].i % colNum) * image_width + DefectLabelInfoList[q].x);
yPos4.Add((DefectLabelInfoList[q].i / colNum) * image_hight + DefectLabelInfoList[q].y);
ZXD4.Add(DefectLabelInfoList[q].confidence);
}
else
XcHeBingList4.Add(DefectLabelInfoList[q]);
}
else
outList.Add(DefectLabelInfoList[q]);
}
//递归下次合并数据
List<DefectLabelInfo> dg1 = new List<DefectLabelInfo>();
List<DefectLabelInfo> dg2 = new List<DefectLabelInfo>();
List<DefectLabelInfo> dg3 = new List<DefectLabelInfo>();
List<DefectLabelInfo> dg4 = new List<DefectLabelInfo>();
if (XcHeBingList.Count >0)
dg1 = HeBingDefect(modelName, Width, XcHeBingList);
if (XcHeBingList2.Count > 0)
dg2 = HeBingDefect(modelName, Width, XcHeBingList2);
if (XcHeBingList3.Count > 0)
dg3 = HeBingDefect(modelName, Width, XcHeBingList3);
if (XcHeBingList4.Count > 0)
dg4 = HeBingDefect(modelName, Width, XcHeBingList4);
//多个jietou合并
if (HeBingList.Count>0)
{
var stIt = HeBingList.Find(x => (x.i % colNum) * image_width + x.x == xPos.Min());
var edIt = HeBingList.Find(x => (x.i % colNum) * image_width + x.x == xPos.Max());
var stIty = HeBingList.Find(x => ((x.i / colNum) * image_hight + x.y) == yPos.Min());
var edIty = HeBingList.Find(x => ((x.i / colNum) * image_hight + x.y) == yPos.Max());
var eZXD = HeBingList.Find(x => x.confidence == ZXD.Max());
int newW = Math.Abs(((edIt.i % colNum) * image_width + edIt.x) - ((stIt.i % colNum) * image_width + stIt.x)) + edIt.w;
int newh = Math.Abs(((edIt.i / colNum) * image_hight + edIt.y) - ((stIt.i / colNum) * image_hight + stIt.y)) + edIt.h;
outList.Add(new DefectLabelInfo() {
x=stIt.x,
y= edIty.y,
w = newW, //多图叠加
h = newh,
classId = eZXD.classId,
confidence = eZXD.confidence,
contrast = eZXD.contrast,
cmH = Math.Round(edIt.h * 1.0 / Config.cm2px_y, 2),
cmW = Math.Round(newW * 1.0 / Config.cm2px_x, 2),
i = stIt.i,
j = stIt.j,
});
}
//多个hengdang合并
if (HeBingList2.Count > 0)
{
var stIt = HeBingList2.Find(x => (x.i % colNum) * image_width + x.x == xPos2.Min());
var edIt = HeBingList2.Find(x => (x.i % colNum) * image_width + x.x == xPos2.Max());
var stIty = HeBingList2.Find(x => ((x.i / colNum) * image_hight + x.y) == yPos2.Min());
var edIty = HeBingList2.Find(x => ((x.i / colNum) * image_hight + x.y) == yPos2.Max());
var eZXD = HeBingList2.Find(x => x.confidence == ZXD2.Max());
int newW = Math.Abs(((edIt.i % colNum) * image_width + edIt.x) - ((stIt.i % colNum) * image_width + stIt.x)) + edIt.w;
int newh = Math.Abs(((edIt.i / colNum) * image_hight + edIt.y) - ((stIt.i / colNum) * image_hight + stIt.y)) + edIt.h;
outList.Add(new DefectLabelInfo()
{
x = stIt.x,
y = edIty.y,
w = newW, //多图叠加
h = newh,
classId = eZXD.classId,
confidence = eZXD.confidence,
contrast = eZXD.contrast,
cmH = Math.Round(edIt.h * 1.0 / Config.cm2px_y, 2),
cmW = Math.Round(newW * 1.0 / Config.cm2px_x, 2),
i = stIt.i,
j = stIt.j,
});
}
//多个jt合并
if (HeBingList3.Count > 0)
{
var stIt = HeBingList3.Find(x => (x.i % colNum) * image_width + x.x == xPos3.Min());
var edIt = HeBingList3.Find(x => (x.i % colNum) * image_width + x.x == xPos3.Max());
var stIty = HeBingList3.Find(x => ((x.i / colNum) * image_hight + x.y) == yPos3.Min());
var edIty = HeBingList3.Find(x => ((x.i / colNum) * image_hight + x.y) == yPos3.Max());
var eZXD = HeBingList3.Find(x => x.confidence == ZXD3.Max());
int newW = Math.Abs(((edIt.i % colNum) * image_width + edIt.x) - ((stIt.i % colNum) * image_width + stIt.x)) + edIt.w;
int newh = Math.Abs(((edIt.i / colNum) * image_hight + edIt.y) - ((stIt.i / colNum) * image_hight + stIt.y)) + edIt.h;
outList.Add(new DefectLabelInfo()
{
x = stIt.x,
y = edIty.y,
w = newW, //多图叠加
h = newh,
classId = eZXD.classId,
confidence = eZXD.confidence,
contrast = eZXD.contrast,
cmH = Math.Round(edIt.h * 1.0 / Config.cm2px_y, 2),
cmW = Math.Round(newW * 1.0 / Config.cm2px_x, 2),
i = stIt.i,
j = stIt.j,
});
}
//多个tcy合并
if (HeBingList4.Count > 0)
{
var stIt = HeBingList4.Find(x => (x.i % colNum) * image_width + x.x == xPos4.Min());
var edIt = HeBingList4.Find(x => (x.i % colNum) * image_width + x.x == xPos4.Max());
var stIty = HeBingList4.Find(x => ((x.i / colNum) * image_hight + x.y) == yPos4.Min());
var edIty = HeBingList4.Find(x => ((x.i / colNum) * image_hight + x.y) == yPos4.Max());
var eZXD = HeBingList4.Find(x => x.confidence == ZXD4.Max());
int newW = Math.Abs(((edIt.i % colNum) * image_width + edIt.x) - ((stIt.i % colNum) * image_width + stIt.x)) + edIt.w;
int newh = Math.Abs(((edIt.i / colNum) * image_hight + edIt.y) - ((stIt.i / colNum) * image_hight + stIt.y)) + edIt.h;
outList.Add(new DefectLabelInfo()
{
x = stIt.x,
y = edIty.y,
w = newW, //多图叠加
h = newh,
classId = eZXD.classId,
confidence = eZXD.confidence,
contrast = eZXD.contrast,
cmH = Math.Round(edIt.h * 1.0 / Config.cm2px_y, 2),
cmW = Math.Round(newW * 1.0 / Config.cm2px_x, 2),
i = stIt.i,
j = stIt.j,
});
}
outList = outList.Concat(dg1).ToList<DefectLabelInfo>();//保留重复项
outList = outList.Concat(dg2).ToList<DefectLabelInfo>();//保留重复项
outList = outList.Concat(dg3).ToList<DefectLabelInfo>();//保留重复项
outList = outList.Concat(dg4).ToList<DefectLabelInfo>();//保留重复项
return outList;
}
//打标
private void run3()
{
QualifiedLimit qualifiedLimit;
while (IsInit)
{
if (taskMakeTagList.Count < 1)
{
Thread.Sleep(20);
continue;
}
//
var task = pop3();
int liStep = 0;
try
{
Stopwatch stopwatch = Stopwatch.StartNew();
stopwatch.Restart();
int colNum = task.bmp.Width / image_width;
int rowNum = task.bmp.Height / image_hight;
int count = 0;
liStep = 3;
if (!Config.OpenHalconDefect)
{
int cut_count = task.bmps_cut.Count();//上面bmps_cut已销毁
//车用革去除接头处横档误判
bool haveJieTou = false;
List<DefectLabelInfo> DefectLabelInfoList = new List<DefectLabelInfo>();
for (int i = 0; i < cut_count; i++)
{
liStep = i * 100;
//task.resultInfo += $"第 {i}/{cut_count} 张小图(大图索引{task.photoIndex}): 缺陷数 = {task.output_num[i]}\n";
//task.resultInfo +=$"大图({task.tag})[{task.bmp.Width}*{task.bmp.Height}],第 {i + 1}/{cut_count} 张小图[{task.bmps_cut[i].Width}*{task.bmps_cut[i].Height}]: 瑕疵output_num = {output_num[i]}\n";
#region
for (int j = 0; j < task.output_num[i]; j++)//缺陷数
{
liStep += j;//0
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"-------");
int index = count * detect_elem_size;
// 打印输出信息(示例代码,根据实际情况进行修改和格式化)
// 获取输出信息
int x = (int)task.output[index];
int y = (int)task.output[index + 1];
int w = (int)task.output[index + 2];
int h = (int)task.output[index + 3];
int classId = (int)task.output[index + 4];
double confidence = Math.Round(task.output[index + 5], 2); //置信度
double contrast = Math.Round(task.output[index + 6], 3);//对比度
//y = image_hight-y-h;//转到右下角为原点
count++;
//var cmW = Math.Round(w * task.widthRatio / Config.cm2px_x, 2);
//var cmH = Math.Round(h * task.widthRatio / Config.cm2px_y, 2);
var cmW = Math.Round(w * 1.0 / Config.cm2px_x, 2);
var cmH = Math.Round(h * 1.0 / Config.cm2px_y, 2);
// 打印输出信息
//task.resultInfo += $"----{i}----col:{i % colNum}/{colNum} row:{i / colNum}/{colNum}-----------\n目标:{j + 1} 类别ID:{classId} 置信度:{confidence} 对比度:{contrast} 坐标:({x},{y})-({x + w},{y + h}) 宽高:w={w},h={h}; \n";
DefectLabelInfoList.Add(new DefectLabelInfo()
{
x = (int)task.output[index],
y = (int)task.output[index + 1],
w = (int)task.output[index + 2],
h = (int)task.output[index + 3],
classId = (int)task.output[index + 4],
confidence = Math.Round(task.output[index + 5], 2), //置信度
contrast = ContrastToPercent(Math.Round(task.output[index + 6], 3)),//对比度
//cmW = Math.Round(w * task.widthRatio / Config.cm2px_x, 2),
//cmH = Math.Round(h * task.widthRatio / Config.cm2px_y, 2),
cmW = Math.Round(w * 1.0 / Config.cm2px_x, 2),
cmH = Math.Round(h * 1.0 / Config.cm2px_y, 2),
i = i,
j = j,
});
}
#endregion
#if false
for (int j = 0; j < task.output_num[i]; j++)//缺陷数
{
liStep += j;//0
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"-------");
int index = count * detect_elem_size;
// 打印输出信息(示例代码,根据实际情况进行修改和格式化)
// 获取输出信息
int x = (int)task.output[index];
int y = (int)task.output[index + 1];
int w = (int)task.output[index + 2];
int h = (int)task.output[index + 3];
int classId = (int)task.output[index + 4];
double confidence = Math.Round(task.output[index + 5],2); //置信度
double contrast = Math.Round(task.output[index + 6], 3);//对比度
//y = image_hight-y-h;//转到右下角为原点
count++;
var cmW = Math.Round(w * task.widthRatio / Config.cm2px_x, 2);
var cmH = Math.Round(h * task.widthRatio / Config.cm2px_y, 2);
// 打印输出信息
task.resultInfo += $"----{i}----col:{i % colNum}/{colNum} row:{i / colNum}/{colNum}-----------\n目标:{j + 1} 类别ID:{classId} 置信度:{confidence} 对比度:{contrast} 坐标:({x},{y})-({x + w},{y + h}) 宽高:w={w},h={h}; \n";
//是否满足此产品标准
if (task.qualifiedLimitList != null && task.qualifiedLimitList.Count > 0)
{
qualifiedLimit = task.qualifiedLimitList.FirstOrDefault(m => m.Code == Config.getDefectCode(classId));
if (qualifiedLimit != null)
{
//if ((qualifiedLimit.ZXD > 0 && qualifiedLimit.ZXD > confidence)
// || (qualifiedLimit.ContrastTop + qualifiedLimit.ContrastLower > 0 && x> qualifiedLimit.ContrastLower && x < qualifiedLimit.ContrastTop)
// || (qualifiedLimit.Area > 0 && qualifiedLimit.Area > cmW * cmH))
if (confidence <= qualifiedLimit.ZXD)//confidence > qualifiedLimit.ZXD 是瑕疵 才继续判断下面的两个条件
{
task.resultInfo += $" 置信度不满足此产品瑕疵标准,跳过! \n";
continue;
}
//下限<对比度<上限:不是瑕疵
var ContrastTotal = qualifiedLimit.ContrastTop + qualifiedLimit.ContrastLower;
if (qualifiedLimit.IsOR)
{
if (!(
(qualifiedLimit.Area <= 0 || cmW * cmH >= qualifiedLimit.Area) ||
(ContrastTotal <= 0 || (contrast < qualifiedLimit.ContrastLower || contrast > qualifiedLimit.ContrastTop))))
{
task.resultInfo += $" 不满足此产品瑕疵标准,跳过! \n";
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"判断不是瑕疵类别ID:{classId} 置信度({confidence},[{qualifiedLimit.ZXD}]); isOr({qualifiedLimit.IsOR}); 面积({cmW * cmH},[{ qualifiedLimit.Area}]); 对比度({contrast},[{qualifiedLimit.ContrastLower}-{qualifiedLimit.ContrastTop}])");
continue;
}
}
else
{
if (!(
(qualifiedLimit.Area<=0 || cmW * cmH >= qualifiedLimit.Area) &&
(ContrastTotal <=0 || (contrast < qualifiedLimit.ContrastLower || contrast > qualifiedLimit.ContrastTop))))
{
task.resultInfo += $" 不满足此产品瑕疵标准,跳过! \n";
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"判断不是瑕疵类别ID:{classId} 置信度({confidence},[{qualifiedLimit.ZXD}]); isOr({qualifiedLimit.IsOR}); 面积({cmW * cmH},[{ qualifiedLimit.Area}]); 对比度({contrast},[{qualifiedLimit.ContrastLower}-{qualifiedLimit.ContrastTop}])");
continue;
}
}
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"判断是瑕疵类别ID:{classId} 置信度({confidence},[{qualifiedLimit.ZXD}]); isOr({qualifiedLimit.IsOR}); 面积({cmW * cmH},[{ qualifiedLimit.Area}]); 对比度({contrast},[{qualifiedLimit.ContrastLower}-{qualifiedLimit.ContrastTop}])");
}
}
liStep++;//1
//打标
var point1 = new OpenCvSharp.Point((i % colNum) * image_width + x, (i / colNum) * image_hight + y);
var point2 = new OpenCvSharp.Point(point1.X + w, point1.Y + h);
liStep++;//2
task.resultInfo += $" 转换到大图坐标(px)p1={point1.X},{point1.Y}; p2={point2.X},{point2.Y}\n";
Cv2.Rectangle(task.bmpTag, point1, point2, new Scalar(0.0, 0.0, 255.0), 1);//画打标点
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"保存第 {count} 行缺陷信息;");
var cmX = Math.Round(point1.X * task.widthRatio / Config.cm2px_x, 2);
var cmY = Math.Round((task.bmp.Height-point1.Y-h) * task.widthRatio / Config.cm2px_y, 2);//外面计Y从右下角为原点
liStep++;//3
task.resultInfo += $" 转换到大图坐标(cm)[widthRatio={task.widthRatio}]x={cmX},y={cmY}; w={cmW},h={cmH}\n";
task.excelTable.Rows.Add($"{task.photoIndex}", cmX, cmY, cmW, cmH, j + 1, classId, confidence, contrast);
liStep++;//4
//切缺陷小图
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"保存第 {count} 个缺陷小图;");
int left, top, decX, decY;
decX = (w > 236 ? 20 : 256 - w) / 2;
decY = (h > 236 ? 20 : 256 - h) / 2;
left = point1.X - decX;
top = point1.Y - decY;
if (left < 0) left = 0;
if (top < 0) top = 0;
int width = w + decX * 2;
int height = h + decY * 2;
if (left + width > task.bmp.Width - 1) width = task.bmp.Width - left - 1;
if (top + height > task.bmp.Height - 1) height = task.bmp.Height - top - 1;
liStep++;//5
Rect roi = new Rect(left, top, width, height);
liStep++;//6
if (height < 1 || width < 1)
{
task.resultInfo += $" 打标到大图坐标Rect(px)left={left},top={top}; width={width},height={height}\n";
task.resultInfo += $" test point1.Y={point1.Y},h={h}; top={top},mat.Height={ task.bmp.Height}\n================\n";
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Normal, task.resultInfo);
}
//保存
//string filename = $"{Config.appBasePath}\\temp\\{task.tag}\\{task.tag}_X{mmX.ToString()}_Y{mmY.ToString()}_W{mmW.ToString()}_H{mmH.ToString()}_目标{j + 1}_类别{classId}_置信度{confidence}.bmp";
//OpenCvSharp.Extensions.BitmapConverter.ToBitmap(new Mat(task.bmp, roi)).Save(filename, ImageFormat.Jpeg);
task.lstDefectBmp.Add(new Mat(task.bmpTag, roi).Clone());
liStep++;//7
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"缺陷小图数量:{task.lstDefectBmp.Count}");
}
#endif
}
#region
liStep = 3000;
if (DefectLabelInfoList.Count > 0)
DefectLabelInfoList = HeBingDefect(task.modelName, task.bmp.Width, DefectLabelInfoList);
liStep++;
#endregion
//结果过滤
#region
//降序排序,先得到是否有接头检出
List<DefectLabelInfo> DefectLabelInfoListByDefect = new List<DefectLabelInfo>();
List<DefectLabelInfo> DefectLabelInfoListByClassID = DefectLabelInfoList.OrderByDescending(t => t.classId).ToList();//降序
for (int q = 0; q < DefectLabelInfoListByClassID.Count; q++)
{
//是否满足此产品标准
if (task.qualifiedLimitList != null && task.qualifiedLimitList.Count > 0)
{
qualifiedLimit = task.qualifiedLimitList.FirstOrDefault(m => m.Code == Config.getDefectCode(task.modelName, DefectLabelInfoListByClassID[q].classId));
if (qualifiedLimit != null)
{
// 打印输出信息
task.resultInfo += $"----{DefectLabelInfoListByClassID[q].i}----col:{DefectLabelInfoListByClassID[q].i % colNum}/{colNum} row:{DefectLabelInfoListByClassID[q].i / colNum}/{colNum}-----------\n目标:{DefectLabelInfoListByClassID[q].j + 1} 类别ID:{DefectLabelInfoListByClassID[q].classId} 置信度:{DefectLabelInfoListByClassID[q].confidence} 对比度:{DefectLabelInfoListByClassID[q].contrast}\n";
//if ((qualifiedLimit.ZXD > 0 && qualifiedLimit.ZXD > confidence)
// || (qualifiedLimit.ContrastTop + qualifiedLimit.ContrastLower > 0 && x> qualifiedLimit.ContrastLower && x < qualifiedLimit.ContrastTop)
// || (qualifiedLimit.Area > 0 && qualifiedLimit.Area > cmW * cmH))
if (DefectLabelInfoListByClassID[q].confidence <= qualifiedLimit.ZXD)//confidence > qualifiedLimit.ZXD 是瑕疵 才继续判断下面的两个条件
{
task.resultInfo += $" 置信度不满足此产品瑕疵标准,跳过! \n";
continue;
}
//下限<对比度<上限:不是瑕疵
var ContrastTotal = qualifiedLimit.ContrastTop + qualifiedLimit.ContrastLower;
if (qualifiedLimit.IsOR)
{
//if (!(
// (ContrastTotal <= 0 || (PercentToContrast(DefectLabelInfoListByClassID[q].contrast) < qualifiedLimit.ContrastLower || PercentToContrast(DefectLabelInfoListByClassID[q].contrast) > qualifiedLimit.ContrastTop))))
//{
// task.resultInfo += $" 不满足此产品瑕疵标准,跳过! \n";
// //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"判断不是瑕疵类别ID:{classId} 置信度({confidence},[{qualifiedLimit.ZXD}]); isOr({qualifiedLimit.IsOR}); 面积({cmW * cmH},[{ qualifiedLimit.Area}]); 对比度({contrast},[{qualifiedLimit.ContrastLower}-{qualifiedLimit.ContrastTop}])");
// continue;
//}
}
else
{
if (!(ContrastTotal <= 0 || (PercentToContrast(DefectLabelInfoListByClassID[q].contrast) < qualifiedLimit.ContrastLower || PercentToContrast(DefectLabelInfoListByClassID[q].contrast) > qualifiedLimit.ContrastTop)))
{
task.resultInfo += $" 不满足此产品瑕疵标准,跳过! \n";
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"判断不是瑕疵类别ID:{classId} 置信度({confidence},[{qualifiedLimit.ZXD}]); isOr({qualifiedLimit.IsOR}); 面积({cmW * cmH},[{ qualifiedLimit.Area}]); 对比度({contrast},[{qualifiedLimit.ContrastLower}-{qualifiedLimit.ContrastTop}])");
continue;
}
}
if (qualifiedLimit.Area > 0 && DefectLabelInfoListByClassID[q].cmW * DefectLabelInfoListByClassID[q].cmH < qualifiedLimit.Area)
{
task.resultInfo += $" 不满足此产品瑕疵标准面积,跳过! \n";
continue;
}
if (Config.getDefectCode(task.modelName, DefectLabelInfoListByClassID[q].classId) == "jietou")
haveJieTou = true;
if (haveJieTou && (Config.getDefectCode(task.modelName, DefectLabelInfoListByClassID[q].classId) == "hengdang"))
{
task.resultInfo += $" 判断为接头处横档,跳过! \n";
continue;
}
if (Config.getDefectCode(task.modelName, DefectLabelInfoListByClassID[q].classId) == "na")
{
task.resultInfo += $" 判断为正向标签na跳过 \n";
continue;
}
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"判断是瑕疵类别ID:{classId} 置信度({confidence},[{qualifiedLimit.ZXD}]); isOr({qualifiedLimit.IsOR}); 面积({cmW * cmH},[{ qualifiedLimit.Area}]); 对比度({contrast},[{qualifiedLimit.ContrastLower}-{qualifiedLimit.ContrastTop}])");
}
}
//检测缺陷
DefectLabelInfoListByDefect.Add(DefectLabelInfoListByClassID[q]);
liStep++;//1
}
//y方向位置排序
List<DefectLabelInfo> DefectLabelInfoListByYdis = DefectLabelInfoListByDefect.OrderByDescending(t => (t.i / colNum) * image_hight + t.y).ToList();//降序
for (int q = 0; q < DefectLabelInfoListByYdis.Count; q++)
{
//打标
int penLine = 50;
int xx = (DefectLabelInfoListByYdis[q].i % colNum) * image_width + DefectLabelInfoListByYdis[q].x - 2 * penLine;
int yy = (DefectLabelInfoListByYdis[q].i / colNum) * image_hight + DefectLabelInfoListByYdis[q].y - 2 * penLine;
var point1 = new OpenCvSharp.Point(xx >0? xx:0, yy >0? yy:0);
var point2 = new OpenCvSharp.Point(point1.X + DefectLabelInfoListByYdis[q].w + 4 * penLine, point1.Y + DefectLabelInfoListByYdis[q].h + 4 * penLine);
liStep++;//2
//task.resultInfo += $" 转换到大图坐标(px)p1={point1.X},{point1.Y}; p2={point2.X},{point2.Y}\n";
Cv2.Rectangle(task.bmpTag, point1, point2, new Scalar(0.0, 0.0, 255.0), penLine);//画打标点
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"保存第 {count} 行缺陷信息;");
int px = (point1.X - task.xw) > 0 ? (point1.X - task.xw) : 0;
//var cmX = Math.Round(px * task.widthRatio / Config.cm2px_x, 2);
var cmX = Math.Round((double)px / Config.cm2px_x, 2);
//var cmY = Math.Round((task.bmp.Height - point1.Y - DefectLabelInfoListByClassID[q].h) * task.widthRatio / Config.cm2px_y, 2);//外面计Y从右下角为原点
var cmY = Math.Round((task.bmp.Height - point1.Y - DefectLabelInfoListByYdis[q].h) * 1.0 / Config.cm2px_y, 2);//外面计Y从右下角为原点
liStep++;//3
//task.resultInfo += $" 转换到大图坐标(cm)[widthRatio={task.widthRatio}]x={cmX},y={cmY}; w={DefectLabelInfoList[q].cmW},h={DefectLabelInfoList[q].cmH}\n";
task.excelTable.Rows.Add($"{task.photoIndex}", cmX, cmY, DefectLabelInfoListByYdis[q].cmW, DefectLabelInfoListByYdis[q].cmH, DefectLabelInfoListByYdis[q].j + 1, DefectLabelInfoListByYdis[q].classId, DefectLabelInfoListByYdis[q].confidence, DefectLabelInfoListByYdis[q].contrast);
liStep++;//4
//切缺陷小图
//WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"保存第 {count} 个缺陷小图;");
int left, top, decX, decY;
decX = ((DefectLabelInfoListByYdis[q].w + 4 * penLine) > 236 ? 20 : (256 - DefectLabelInfoListByYdis[q].w - 4 * penLine)) / 2;
decY = ((DefectLabelInfoListByYdis[q].h + 4 * penLine) > 236 ? 20 : (256 - DefectLabelInfoListByYdis[q].h - 4 * penLine)) / 2;
//left = point1.X - decX;
//top = point1.Y - decY;
left = point1.X - 20;
top = point1.Y - 20;
if (left < 0) left = 0;
if (top < 0) top = 0;
//int width = DefectLabelInfoListByClassID[q].w + decX * 2;
//int height = DefectLabelInfoListByClassID[q].h + decY * 2;
int width = point2.X - point1.X + 20 * 2;
int height = point2.Y - point1.Y + 20 * 2;
if (left + width > task.bmp.Width - 1) width = task.bmp.Width - left - 1;
if (top + height > task.bmp.Height - 1) height = task.bmp.Height - top - 1;
liStep++;//5
Rect roi = new Rect(left, top, width, height);
liStep++;//6
if (height < 1 || width < 1)
{
//task.resultInfo += $" 打标到大图坐标Rect(px)left={left},top={top}; width={width},height={height}\n";
//task.resultInfo += $" test point1.Y={point1.Y},h={DefectLabelInfoList[q].h}; top={top},mat.Height={task.bmp.Height}\n================\n";
WarningEvent?.Invoke(DateTime.Now, WarningEnum.Normal, task.resultInfo);
}
//保存
//string filename = $"{Config.appBasePath}\\temp\\{task.tag}\\{task.tag}_X{mmX.ToString()}_Y{mmY.ToString()}_W{mmW.ToString()}_H{mmH.ToString()}_目标{j + 1}_类别{classId}_置信度{confidence}.bmp";
//OpenCvSharp.Extensions.BitmapConverter.ToBitmap(new Mat(task.bmp, roi)).Save(filename, ImageFormat.Jpeg);
task.lstDefectBmp.Add(new Mat(task.bmpTag, roi).Clone());
liStep++;//7
}
#endregion
}
else
{
stopwatch.Restart();
//打标
var defectinfo = task.hv_defectinfo.ToOArr();
List<DefectLabelInfo> DefectLabelInfoList = new List<DefectLabelInfo>();
for (int i = 0; i < task.object_num; i++)
{
liStep = 23 + i;
#region
int index = i * 6;
// 打印输出信息(示例代码,根据实际情况进行修改和格式化)
// 获取输出信息
int x = (int)defectinfo[index].ToInt();
int y = (int)defectinfo[index + 1].ToInt();
int w = (int)defectinfo[index + 2].ToInt();
int h = (int)defectinfo[index + 3].ToInt();
int classId = -99;//(int)defectinfo[index + 4].ToInt();
double confidence = Math.Round(defectinfo[index + 5].ToDouble(), 2); //置信度
int px = (x - task.xw) > 0 ? (x - task.xw) : 0; ;
var cmX = Math.Round(px * 1.0 / Config.cm2px_x, 2);
var cmY = Math.Round((task.bmp.Height - y - h) * 1.0 / Config.cm2px_y, 2);//外面计Y从右下角为原点
DefectLabelInfoList.Add(new DefectLabelInfo()
{
x = x,
y = y,
w = w,
h = h,
classId = classId,
confidence = confidence, //置信度
cmW = Math.Round(w * 1.0 / Config.cm2px_x, 2),
cmH = Math.Round(h * 1.0 / Config.cm2px_y, 2),
i = i,
j = i,
});
//y = image_hight-y-h;//转到右下角为原点
task.excelTable.Rows.Add($"{task.photoIndex}", cmX, cmY,
Math.Round(w * 1.0 / Config.cm2px_x, 2), Math.Round(h * 1.0 / Config.cm2px_y, 2),
i, classId, confidence, 0);
int penLine = 20;
//打标
int xx = x - 2 * penLine;
int yy = y - 2 * penLine;
var point1 = new OpenCvSharp.Point(xx >0? xx:0, yy >0?yy:0);
var point2 = new OpenCvSharp.Point(point1.X + w + 4* penLine , point1.Y + h + 4 * penLine);
Cv2.Rectangle(task.bmpTag, point1, point2, new Scalar(0.0, 0.0, 255.0), penLine);//画打标点
//切小图
int left, top, decX, decY;
//int tdecX = (w / 2) / 2;
//int tdecY = w / h > 4 ? w / 8 : (h / 1) / 2;
//decX = (w > 236 ? tdecX : 256 - w) / 2;
//decY = (h > 236 ? tdecY : 256 - h) / 2;
//left = point1.X - decX;
//top = point1.Y - decY;
left = point1.X - 20;
top = point1.Y - 20;
if (left < 0) left = 0;
if (top < 0) top = 0;
//int width = w + decX * 2;
//int height = h + decY * 2;
int width = point2.X - point1.X + 20 * 2;
int height = point2.Y - point1.Y + 20 * 2;
if (left + width > task.bmp.Width - 1) width = task.bmp.Width - left - 1;
if (top + height > task.bmp.Height - 1) height = task.bmp.Height - top - 1;
Rect roi = new Rect(left, top, width, height);
task.lstDefectBmp.Add(new Mat(task.bmpTag, roi).Clone());
#endregion
}
}
liStep = 99;
stopwatch.Stop();
task.stopwatch[3] = stopwatch.ElapsedMilliseconds;
task.isSucceed = true;
callback(task);
}
catch (Exception ex)
{
WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"DefectLib task3 err({liStep}):" + ex.Message);
task.isSucceed = false;
task.resultInfo = ex.Message;
callback(task);
}
Thread.Sleep(5);
}
}
private void callback(DefectTask task)
{
//返回成功/失败,异步调用
if (task.finishEvent != null || (task.finishEvent = finishEvent) != null)
//task.finishEvent.BeginInvoke(result, errInfo, res => task.finishEvent.EndInvoke(res), null);
System.Threading.ThreadPool.QueueUserWorkItem(waitCallback, task);
}
//异步回调
WaitCallback waitCallback = new WaitCallback(o =>
{
var task = (DefectTask)o;
task.finishEvent(task);
});
/// <summary>
/// 切割(先左右,后上下)
/// </summary>
/// <param name="mat"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
private Mat[] OpenCVToCutsMat(Mat mat, int width, int height)
{
Mat[] array = new Mat[mat.Width / width * mat.Height / height];
int num = 0;
for (int i = 0; i < mat.Height / height; i++)
{
for (int j = 0; j < mat.Width / width; j++)
{
int x = j * width;
int y = i * height;
System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle(x, y, width, height);
Rect roi = new Rect(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
array[num] = new Mat(mat, roi).Clone();
num++;
}
}
return array;
}
public class DefectTask
{
public DefectTask()
{
// 创建一个 DataTable 对象来存储数据
excelTable = new DataTable("MyData");
// 添加列到 DataTable
excelTable.Columns.Add("FileName", typeof(string));
excelTable.Columns.Add("X", typeof(decimal));
excelTable.Columns.Add("Y", typeof(decimal));
excelTable.Columns.Add("W", typeof(decimal));
excelTable.Columns.Add("H", typeof(decimal));
excelTable.Columns.Add("目标", typeof(int));
excelTable.Columns.Add("类别", typeof(int));
excelTable.Columns.Add("置信度", typeof(decimal));
excelTable.Columns.Add("对比度", typeof(decimal));
// 向 DataTable 中添加数据行
//excelTable.Rows.Add("John Doe", 30);
//excelTable.Rows.Add("Jane Smith", 25);
}
/// <summary>
/// 模型名字
/// </summary>
public string modelName;
public Models.Records record;
//public string bmpPath;//源图路径(仅目录)
/// <summary>
/// 源图(resize后的)
/// </summary>
public Mat bmp;
//public Mat bmpBgr2rgb=new Mat();
public System.Drawing.Size resize = new System.Drawing.Size(224, 224);
//public Mat resizeBmp;//resize后 BGR2RGB图只用于识别
public Mat bmpTag;
/// <summary>
/// 图片索引0-n
/// </summary>
public int photoIndex;//excel中对应的图像路径标识
public float widthRatio;//宽度比例resize前/resize后
//切割后
public Mat[] bmps_cut;
//用于比对参数 }//置信度 面积 对比度
public List<QualifiedLimit> qualifiedLimitList;
//推理后结果用于打标
public float[] output;
public int[] output_num;
//
/// <summary>
/// 完成后回调
/// </summary>
public Action<DefectTask> finishEvent;
//==结果返回
public bool isSucceed;//转换是否成功
public string resultInfo = "";//成功或失败信息
public List<Mat> lstDefectBmp=new List<Mat>();
/// <summary>
/// fileIndex,x_mm,y_mm,w_mm,h_mm,目标,类别ID,置信度
/// </summary>
public DataTable excelTable=new DataTable();
public long[] stopwatch = new long[4];
public int xw;
//传统算法使用
public HObject ho_Img = new HObject();
public HObject ho_imgG = new HObject();
public HObject ho_ImageResult3 = new HObject();
public HObject ho_ImageSub = new HObject();
public HTuple hv_RES, hv_gauss_filter1, hv_gauss_filter2, hv_Energy_value, hv_Region_S_value, hv_AreaThr, hv_class, hv_defectinfo;
public int object_num = 0;
//图片位置
public double CurrDis;
}
public void add(DefectTask task)
{
lock (taskList)
{
taskList.Add(task);
QueueCountEvent?.BeginInvoke(0, taskList.Count, null, null);
}
}
private DefectTask pop()
{
lock (taskList)
{
if (taskList.Count < 1)
return null;
//int index = 0;// taskList.FindIndex(p => { return p.isSync; });
//if (index < 0) index = 0;
var task = taskList[0];
taskList.RemoveAt(0);
QueueCountEvent?.BeginInvoke(0, taskList.Count, null, null);
return task;
}
}
private DefectTask pop2()
{
lock (taskOperationList)
{
if (taskOperationList.Count < 1)
return null;
//int index = 0;// taskList.FindIndex(p => { return p.isSync; });
//if (index < 0) index = 0;
var task = taskOperationList[0];
taskOperationList.RemoveAt(0);
QueueCountEvent?.BeginInvoke(1, taskOperationList.Count, null, null);
return task;
}
}
private DefectTask pop3()
{
lock (taskMakeTagList)
{
if (taskMakeTagList.Count < 1)
return null;
//int index = 0;// taskList.FindIndex(p => { return p.isSync; });
//if (index < 0) index = 0;
var task = taskMakeTagList[0];
taskMakeTagList.RemoveAt(0);
QueueCountEvent?.BeginInvoke(2, taskMakeTagList.Count, null, null);
return task;
}
}
public void Dispose()
{
stop();
}
}
}