392 lines
18 KiB
C#
392 lines
18 KiB
C#
using HalconDotNet;
|
||
using Microsoft.ML.OnnxRuntime;
|
||
using Microsoft.ML.OnnxRuntime.Tensors;
|
||
using Newtonsoft.Json;
|
||
using Newtonsoft.Json.Linq;
|
||
using OpenCvSharp;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Drawing;
|
||
using System.Drawing.Imaging;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using Yolo5;
|
||
|
||
namespace ProductionControl.Device
|
||
{
|
||
public class SizeLib : IDisposable
|
||
{
|
||
public Action<WarningEnum, string> WarningEvent;
|
||
/// <summary>
|
||
/// 检测结果JSON(原图,结果)
|
||
/// </summary>
|
||
public Action<SizeTask> finishEvent;
|
||
/// <summary>
|
||
/// 是否打开设备成功
|
||
/// </summary>
|
||
public bool IsInit { get; private set; } = false;
|
||
//private System.Timers.Timer timer = new System.Timers.Timer();
|
||
|
||
//配置
|
||
HDevEngine MyEngine = new HDevEngine();
|
||
|
||
//777时用
|
||
Yolo_Class yolo5 =new Yolo_Class();
|
||
|
||
private Thread t_task;
|
||
public SizeLib()
|
||
{
|
||
}
|
||
public bool start(string enginePath)
|
||
{
|
||
try
|
||
{
|
||
IsInit = true;
|
||
taskList.Clear();
|
||
MyEngine.SetProcedurePath(enginePath);
|
||
|
||
t_task = new System.Threading.Thread(run);
|
||
t_task.IsBackground = true;
|
||
t_task.Start();
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
WarningEvent?.Invoke(WarningEnum.High,ex.Message);
|
||
return false;
|
||
}
|
||
}
|
||
public void stop()
|
||
{
|
||
if (!IsInit) return;
|
||
|
||
try
|
||
{
|
||
IsInit = false;
|
||
//timer.Elapsed -= Timer_Elapsed;
|
||
|
||
MyEngine.Dispose();
|
||
}
|
||
catch { }
|
||
|
||
}
|
||
|
||
private bool _debug = false;
|
||
public bool setDebug {
|
||
get { return _debug; }
|
||
set {
|
||
if (!IsInit) return;
|
||
|
||
_debug=value;
|
||
if (_debug)
|
||
MyEngine.StartDebugServer();
|
||
else
|
||
MyEngine.StopDebugServer();
|
||
}
|
||
}
|
||
//流程:111,222,444,333,777,777,777,。。。
|
||
|
||
private void run()
|
||
{
|
||
int taskCount;
|
||
while (IsInit)
|
||
{
|
||
lock (taskList)
|
||
{
|
||
taskCount = taskList.Count;
|
||
}
|
||
if (taskCount < 1)
|
||
{
|
||
Thread.Sleep(10);
|
||
continue;
|
||
}
|
||
|
||
////
|
||
int step = 0;
|
||
var task = pop();
|
||
try
|
||
{
|
||
if (task != null)
|
||
{
|
||
var Program1 = new HDevProcedure(task.engineName);
|
||
HDevProcedureCall ProcCall1_PI_PT = new HDevProcedureCall(Program1);
|
||
step = 1;
|
||
//
|
||
HObject image;
|
||
if (task.bmp != null)
|
||
Bitmap2HObjectBpp24(out image, task.bmp);
|
||
else
|
||
HOperatorSet.ReadImage(out image, task.file_path);
|
||
step = 2;
|
||
//设置外部函数输入
|
||
//if (task.index < 100)
|
||
{
|
||
ProcCall1_PI_PT.SetInputIconicParamObject("Image1", image.Clone());
|
||
ProcCall1_PI_PT.SetInputCtrlParamTuple("index", task.index);//参数1-9
|
||
ProcCall1_PI_PT.SetInputCtrlParamTuple("posX", task.posX);
|
||
ProcCall1_PI_PT.SetInputCtrlParamTuple("posY", task.posY);
|
||
ProcCall1_PI_PT.SetInputCtrlParamTuple("GerberPath",new HTuple( task.drawingPagePath));//美尚没有
|
||
|
||
//设置外部函数输入
|
||
if ((task.PTandLinePos != null) && (task.PTandLinePos[0] != 0))
|
||
{
|
||
double[] posarray = new double[23];
|
||
posarray[0] = task.PTandLinePos[0];
|
||
posarray[1] = task.PTandLinePos[2];
|
||
posarray[2] = task.PTandLinePos[4];
|
||
posarray[3] = task.PTandLinePos[6];
|
||
posarray[4] = task.PTandLinePos[8];
|
||
for (int i = 0; i < 18; i++)
|
||
{
|
||
posarray[5 + i] = task.PTandLinePos[10 + i];
|
||
}
|
||
|
||
ProcCall1_PI_PT.SetInputCtrlParamTuple("UserPose", posarray);
|
||
/////
|
||
///
|
||
//string directory = Config.LogPath + "\\" + DateTime.Now.ToString("yyyyMM") + "\\";
|
||
//if (!System.IO.Directory.Exists(directory))
|
||
// System.IO.Directory.CreateDirectory(directory);
|
||
|
||
//File.AppendAllText(directory + "sizeData.log", "data:" + string.Join(",", posarray) + "\r\n");
|
||
}
|
||
else
|
||
{
|
||
double[] posarray = new double[23];
|
||
ProcCall1_PI_PT.SetInputCtrlParamTuple("UserPose", posarray);
|
||
}
|
||
}
|
||
if (task.index == 777)
|
||
{
|
||
ProcCall1_PI_PT.SetInputIconicParamObject("ContoursAffineTrans1", task.ContoursAffineTrans1_Out);
|
||
}
|
||
else
|
||
{
|
||
HObject ContoursAffineTrans1;
|
||
HOperatorSet.GenEmptyObj(out ContoursAffineTrans1);
|
||
ProcCall1_PI_PT.SetInputIconicParamObject("ContoursAffineTrans1", ContoursAffineTrans1);
|
||
}
|
||
|
||
|
||
step = 3;
|
||
ProcCall1_PI_PT.Execute();//执行外部函数
|
||
step = 4;
|
||
//获取外部函数输出
|
||
switch (task.index)
|
||
{
|
||
case 777://比对结果
|
||
step = 10;
|
||
task.CompResult = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("RES") == 1;//结果,1为true,0为false
|
||
step = 11;
|
||
if (!task.CompResult)
|
||
{
|
||
var Defects_X = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_X");
|
||
var Defects_Y = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_Y");
|
||
var Defects_LeftTop_X = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_LeftTop_X");
|
||
var Defects_LeftTop_Y = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_LeftTop_Y");
|
||
var Defects_RightBottom_X = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_RightBottom_X");
|
||
var Defects_RightBottom_Y = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_RightBottom_Y");
|
||
var Contour_Image = ProcCall1_PI_PT.GetOutputIconicParamObject("Contour_Image");
|
||
//var Zoom_Image = ProcCall1_PI_PT.GetOutputIconicParamObject("Zoom_Image");
|
||
|
||
var Defects_Type = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_Type");
|
||
var Defects_Index = ProcCall1_PI_PT.GetOutputCtrlParamTuple("Defects_Index");
|
||
|
||
step = 12;
|
||
//对比打标图:显示在UI上,以后修复台用
|
||
//task.Zoom_Image_mat = yolo5.DrawContour_Opencv(Contour_Image, Zoom_Image, Defects_LeftTop_X, Defects_LeftTop_Y, Defects_RightBottom_X, Defects_RightBottom_Y);
|
||
//新YOLO.DLL
|
||
task.defectInfor2RestorationDesk = new List<List<string>>();
|
||
task.Zoom_Image_mat = yolo5.DrawContour_Opencv(Contour_Image, image, Defects_LeftTop_X, Defects_LeftTop_Y,
|
||
Defects_RightBottom_X, Defects_RightBottom_Y, Defects_Type, Defects_Index, Defects_X, Defects_Y, out task.defectInfor2RestorationDesk);
|
||
//WarningEvent?.Invoke(WarningEnum.Normal, $"SizeLib 777 call DrawContour_Opencv(),Defects_LeftTop_X={Defects_LeftTop_X}," +
|
||
// $"Defects_LeftTop_Y={Defects_LeftTop_Y},Defects_RightBottom_X={Defects_RightBottom_X},Defects_RightBottom_Y={Defects_RightBottom_Y}," +
|
||
// $"Defects_Type={Defects_Type},Defects_Index={Defects_Index},Defects_X={Defects_X},Defects_Y={Defects_Y}," +
|
||
// $"defectInfor2RestorationDesk={JsonConvert.SerializeObject(task.defectInfor2RestorationDesk)}");
|
||
step = 13;
|
||
task.Zoom_Image_mat = yolo5.ResizesMat_4(task.Zoom_Image_mat);
|
||
|
||
//大图缺陷坐标转换到图纸坐标
|
||
step = 14;
|
||
if (!string.IsNullOrWhiteSpace(task.drawingPagePath) && task.defectInfor2RestorationDesk != null && task.defectInfor2RestorationDesk.Count > 0)
|
||
task.defectInfor2RestorationDeskPage = yolo5.DefectDrawGerberImage(task.drawingPagePath, task.defectInfor2RestorationDesk);
|
||
}
|
||
break;
|
||
case 111:
|
||
task.MarkPointList[0] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkX_1");
|
||
task.MarkPointList[1] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkY_1");
|
||
break;
|
||
case 222:
|
||
task.MarkPointList[2] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkX_2");
|
||
task.MarkPointList[3] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkY_2");
|
||
break;
|
||
case 333:
|
||
task.MarkPointList[4] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkX_3");
|
||
task.MarkPointList[5] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkY_3");//ContoursAffineTrans1
|
||
task.ContoursAffineTrans1_Out = ProcCall1_PI_PT.GetOutputIconicParamObject("ContoursAffineTrans1_Out");
|
||
break;
|
||
case 444:
|
||
task.MarkPointList[6] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkX_4");
|
||
task.MarkPointList[7] = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("PoseMarkY_4");
|
||
break;
|
||
case 3333: //Tag使用,同时继续获取使用default时时校正和其它值
|
||
step = 80;
|
||
if (!string.IsNullOrWhiteSpace( task.sizeTag))
|
||
task.posePT= ProcCall1_PI_PT.GetOutputCtrlParamTuple("posePT").DArr;
|
||
goto default;
|
||
default:
|
||
step = 90;
|
||
task.PT1 = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("DistancePT1");//index=8 PT1=PT2
|
||
task.PT2 = ProcCall1_PI_PT.GetOutputCtrlParamTuple("DistancePT2");
|
||
task.Shanxian = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("Distance3Median");
|
||
//task.RowP = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("RowP");
|
||
task.Circle_Ymm = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("Circle_Ymm");
|
||
task.Circle_Xmm = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("Circle_Xmm");
|
||
task.offsetX = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("offsetX");
|
||
task.offsetY = (double)ProcCall1_PI_PT.GetOutputCtrlParamTuple("offsetY");
|
||
break;
|
||
}
|
||
step = 100;
|
||
ProcCall1_PI_PT.Dispose();
|
||
Program1.Dispose();
|
||
|
||
step = 101;
|
||
task.isSucceed = true;
|
||
task.resultInfo = "成功";
|
||
callback(task);
|
||
step = 102;
|
||
}
|
||
Thread.Sleep(5);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
WarningEvent?.Invoke(WarningEnum.Low, $"SizeLib task err({step}) index({task.index}):"+ ex.Message);
|
||
task.isSucceed = false;
|
||
task.resultInfo = $"(errcode:{step}):{ex.Message}";
|
||
callback(task);
|
||
}
|
||
}
|
||
}
|
||
private void callback(SizeTask 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 = (SizeTask)o;
|
||
task.finishEvent(task);
|
||
});
|
||
//=======task list
|
||
private List<SizeTask> taskList = new List<SizeTask>();
|
||
public class SizeTask
|
||
{
|
||
public int stepIndex;//只为回调记录当前工序信息
|
||
public string processName;//只为回调记录当前工序信息
|
||
|
||
public string engineName,sizeTag;
|
||
/// <summary>
|
||
/// 源文件
|
||
/// </summary>
|
||
public string file_path;
|
||
public double posX,posY;
|
||
public Bitmap bmp;
|
||
public string drawingPagePath = "";//.gbx图纸路径
|
||
|
||
//2023-10-27 新增图纸选择pt点位与线宽点位
|
||
public double[] PTandLinePos;
|
||
/// <summary>
|
||
/// 比对(index=777); 计算Mark(111/222/333/444); 尺寸(1-9); 轴偏移调整(10,20,30...)
|
||
/// </summary>
|
||
public int index; //index=8 PT1=PT2
|
||
/// <summary>
|
||
/// 完成后回调
|
||
/// </summary>
|
||
public Action<SizeTask> finishEvent;
|
||
public long createTime = DateTime.Now.Ticks;
|
||
|
||
//==结果返回
|
||
/// <summary>
|
||
/// 比对结果(index=777)
|
||
/// </summary>
|
||
public bool CompResult;
|
||
public Mat Zoom_Image_mat;//对比打标图:777比对失败时计算得出,后面显示到UI 以后修复台用
|
||
public List<List<string>> defectInfor2RestorationDesk, defectInfor2RestorationDeskPage;//对比未通过坐标信息,合并到缺陷检测中的 //打标缺陷转为图纸的坐标;
|
||
//MARK点
|
||
public double[] MarkPointList = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||
public HObject ContoursAffineTrans1_Out;//index=333时输出,供后面多个777比对时输入使用
|
||
public double[] posePT;//index=3333 && !isEmpty(sizeTag) 才取此数组值,len为0时急停
|
||
//
|
||
public double PT1,PT2, Shanxian, Circle_Ymm, Circle_Xmm, offsetX, offsetY;
|
||
public bool isSucceed;//转换是否成功
|
||
public string resultInfo = "";//成功或失败信息
|
||
}
|
||
|
||
public void add(SizeTask task)
|
||
{
|
||
lock (taskList)
|
||
taskList.Add(task);
|
||
}
|
||
private SizeTask pop()
|
||
{
|
||
lock (taskList)
|
||
{
|
||
if (taskList.Count < 1)
|
||
return null;
|
||
|
||
var task = taskList[0];
|
||
taskList.RemoveAt(0);
|
||
return task;
|
||
}
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
stop();
|
||
}
|
||
/// <summary>
|
||
/// Bitmap转HObject灰度图
|
||
/// </summary>
|
||
/// <param name="bmp">Bitmap图像</param>
|
||
/// <param name="image">HObject图像</param>
|
||
private void Bitmap2HObjectBpp8( out HObject image,Bitmap bmp)
|
||
{
|
||
try
|
||
{
|
||
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
|
||
|
||
BitmapData srcBmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
|
||
|
||
HOperatorSet.GenImage1(out image, "byte", bmp.Width, bmp.Height, srcBmpData.Scan0);
|
||
bmp.UnlockBits(srcBmpData);
|
||
}
|
||
catch (Exception)
|
||
{
|
||
image = null;
|
||
}
|
||
}
|
||
public void Bitmap2HObjectBpp24( out HObject image, Bitmap bmp)
|
||
{
|
||
try
|
||
{
|
||
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
|
||
|
||
BitmapData srcBmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
|
||
HOperatorSet.GenImageInterleaved(out image, srcBmpData.Scan0, "bgr", bmp.Width, bmp.Height, 0, "byte", 0, 0, 0, 0, -1, 0);
|
||
bmp.UnlockBits(srcBmpData);
|
||
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
image = null;
|
||
}
|
||
}
|
||
}
|
||
}
|