2075 lines
81 KiB
C#
2075 lines
81 KiB
C#
/************************
|
||
* 作者:CVE-安翀岚
|
||
*
|
||
* Vision:1.0.23.1007 (发布使用)
|
||
* Windows10 X64(PaddleOCR不能部署在32位操作系统上)
|
||
* PaddleOCR 3.10
|
||
* Vpro: 9.5 SR2
|
||
*
|
||
***********************/
|
||
|
||
|
||
using AVP.CRobot;
|
||
using Bjcve.Comm.FFP;
|
||
using CLIDelegate;
|
||
using Cognex.VisionPro;
|
||
using Cognex.VisionPro.Comm;
|
||
using Cognex.VisionPro.ImageProcessing;
|
||
using Cognex.VisionPro.PMAlign;
|
||
using Cognex.VisionPro.QuickBuild;
|
||
using Cognex.VisionPro.ToolBlock;
|
||
using Cognex.VisionPro.ToolGroup;
|
||
using log4net;
|
||
using LogShowLib;
|
||
using OfficeOpenXml;
|
||
using OpenCvSharp;
|
||
using PaddleOCRSharp;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
using System.Data;
|
||
using System.Drawing;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Text.RegularExpressions;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using System.Windows.Documents;
|
||
using System.Windows.Forms;
|
||
using TetraParkOCR;
|
||
using ThridLibray;
|
||
|
||
namespace TetraPackOCR
|
||
{
|
||
public partial class Form1 : Form
|
||
{
|
||
public Form1()
|
||
{
|
||
InitializeComponent();
|
||
LogInit();
|
||
}
|
||
|
||
#region 字段 委托
|
||
|
||
|
||
//创建字段log
|
||
ILog log = LogManager.GetLogger(typeof(Form1));
|
||
/// <summary>
|
||
/// 声明一个cc24通讯对象
|
||
/// </summary>
|
||
CC24 cc24;
|
||
/// <summary>
|
||
/// 声明一个PaddleOCR对象
|
||
/// </summary>
|
||
PaddleOCREngine Engine;
|
||
|
||
/// <summary>
|
||
///对应表格"P2生成数据"这一页
|
||
/// </summary>
|
||
ExcelWorksheet sheet1;
|
||
/// <summary>
|
||
/// 对应表格"QSV对应产品规格和梯度"这一页
|
||
/// </summary>
|
||
ExcelWorksheet sheet2;
|
||
/// <summary>
|
||
/// 对应"产品规格对应排布方式"这一页
|
||
/// </summary>
|
||
ExcelWorksheet sheet3;
|
||
/// <summary>
|
||
/// 表格路径
|
||
/// </summary>
|
||
string execlFileName = AppDomain.CurrentDomain.BaseDirectory + "Data\\Excle\\OCR文件0602.xlsx";
|
||
|
||
/// <summary>
|
||
/// 共印依据 QSV Design, Layers, Colours,产品规格
|
||
/// </summary>
|
||
string m_ProductStandard;
|
||
/// <summary>
|
||
/// 幅数 包材宽 梯度 X距离 Y距离
|
||
/// </summary>
|
||
int NumberOfLanes;
|
||
double m_width, m_Gradient, m_DistX, m_DistY, m_height;
|
||
/// <summary>
|
||
/// 定位Vpp文件
|
||
/// </summary>
|
||
string vppdetFile = AppDomain.CurrentDomain.BaseDirectory + "Data\\VPPFile\\liledet.vpp";
|
||
/// <summary>
|
||
/// 存图路径
|
||
/// </summary>
|
||
string SaveImageFileOCR = System.IO.Path.GetPathRoot(Application.ExecutablePath) + "SaveImage\\OCR";//ocr存图
|
||
string SaveImageFileDET = System.IO.Path.GetPathRoot(Application.ExecutablePath) + "SaveImage\\Det";//ocr存图
|
||
private CogJobManager myJobManagerDET;
|
||
private CogJob myJobDET;
|
||
|
||
bool PlcContinueFlag = false; //PLC状态旗帜
|
||
int mMatchingStr = 0;//接收当前OCR拍照位置
|
||
|
||
List<float> ocrAcc = new List<float>();
|
||
/// <summary>
|
||
/// 相机对象 1和2
|
||
/// </summary>
|
||
IDevice m_dev_cam_ocr, m_dev_cam_det;
|
||
|
||
delegate void DetResultDelegate(Object Sender, CogJobManagerActionEventArgs e);
|
||
delegate void OcrResultDelegate(Bitmap bmp);
|
||
#endregion
|
||
|
||
#region 窗体加载和关闭
|
||
|
||
/// <summary>
|
||
/// 窗体加载
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void Form1_Load(object sender, EventArgs e)
|
||
{
|
||
try
|
||
{
|
||
btn_manualDet.Enabled = false;
|
||
btn_manualOcr.Enabled = false;
|
||
check_Autorun.Enabled = false;
|
||
btn_StarDet_manual.Enabled = false;
|
||
btn_StarDet_manual.BackColor = Color.LightGray;
|
||
button1.BackColor = Color.LightGray;
|
||
btn_OrderNum.Enabled = false;
|
||
btn_OrderNum.BackColor = Color.LightGray;
|
||
log.Info("软件正在加载...");
|
||
Enabled = false;
|
||
Action action = (() =>
|
||
{
|
||
InitializeCamerOCR();
|
||
InitializeCamerDET();
|
||
InitializePaddleOCR();
|
||
|
||
try
|
||
{
|
||
myJobManagerDET = CogSerializer.LoadObjectFromFile(vppdetFile) as CogJobManager;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
log.Error("定位VPP文件加载失败,请检查文件路径是否正确:" + ex.Message);
|
||
myJobManagerDET = null;
|
||
}
|
||
log.Info("定位VPP文件加载完成");
|
||
InitializeCC24();
|
||
|
||
log.Info("模型文件加载完成");
|
||
check_Autorun.BackgroundImage = Image.FromFile(Application.StartupPath + "\\logo_image\\ON.png");
|
||
ttls_SystemStatusShow.Visible = true;
|
||
ttls_CamStatusShow.Visible = true;
|
||
Invoke(new Action(() =>
|
||
{
|
||
btn_manualOcr.Enabled = true;
|
||
btn_manualDet.Enabled = true;
|
||
check_Autorun.Enabled = true;
|
||
Enabled = true;
|
||
btn_OrderNum.Enabled = true;
|
||
btn_OrderNum.BackColor = Color.DeepSkyBlue;
|
||
}));
|
||
});
|
||
|
||
|
||
|
||
Task myTask = new Task(action);
|
||
|
||
//实例化一个线程列表
|
||
List<Task> tsk = new List<Task>();
|
||
|
||
//将上面的加载vpp工作加入线程列表中
|
||
tsk.Add(myTask);
|
||
|
||
//读取线程列表内的工作让cpu为其开辟线程空间并执行程序
|
||
foreach (var iteam in tsk)
|
||
{
|
||
iteam.Start();
|
||
}
|
||
|
||
TaskFactory tskFactory = new TaskFactory();
|
||
tskFactory.ContinueWhenAll(tsk.ToArray(), FlashFormView =>
|
||
{
|
||
if (myJobManagerDET != null)
|
||
{
|
||
myJobDET = myJobManagerDET.Job(0);
|
||
|
||
// 注册结果队列事件
|
||
myJobManagerDET.UserResultAvailable += new CogJobManager.CogUserResultAvailableEventHandler(DetResult);
|
||
}
|
||
});
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
log.Error(ex.Message);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 窗体关闭
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
|
||
{
|
||
|
||
try
|
||
{
|
||
ClossCam();
|
||
|
||
//// 注销结果队列事件
|
||
myJobManagerDET.UserResultAvailable -= new CogJobManager.CogUserResultAvailableEventHandler(DetResult);
|
||
myJobManagerDET.Shutdown();
|
||
|
||
CloseCC24();
|
||
}
|
||
catch
|
||
{
|
||
Application.DoEvents();
|
||
System.Environment.Exit(0);
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 日志显示初始化
|
||
|
||
private void LogInit()
|
||
{
|
||
try
|
||
{
|
||
//实例化日志助手
|
||
LogShowLib.LogHelper lib = new LogShowLib.LogHelper();
|
||
//为log4net导入配置文件
|
||
//若传入目录未找到配置文件,将创建一个LogConfig.xml
|
||
|
||
log4net.Config.XmlConfigurator.Configure(lib.GetXMLStream(AppDomain.CurrentDomain.BaseDirectory));
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show(string.Format("配置日志出错:{0}", ex.Message));
|
||
}
|
||
}
|
||
|
||
|
||
|
||
#endregion
|
||
|
||
#region 相机初始化
|
||
|
||
#region 相机1 定义为OCR相机
|
||
private void InitializeCamerOCR()
|
||
{
|
||
try
|
||
{
|
||
camOCROpened = false;
|
||
List<IDeviceInfo> deviceList = Enumerator.EnumerateDevices(); //发现设备,搜索所有大华相机
|
||
m_dev_cam_ocr = Enumerator.GetDeviceByKey("Machine Vision:CK21686DAK00001");//通过"设备厂商名:设备序列号"获取
|
||
if (m_dev_cam_ocr == null)
|
||
{
|
||
log.Error("未发现OCR相机,请检查相机连接");
|
||
return;
|
||
}
|
||
m_dev_cam_ocr.CameraOpened += m_dev_cam_ocr_CameraOpened;
|
||
m_dev_cam_ocr.CameraClosed += m_dev_cam_ocr_CameraClosed;
|
||
m_dev_cam_ocr.ConnectionLost += m_dev_cam_ocr_ConnectionLost;
|
||
|
||
if (!m_dev_cam_ocr.Open())
|
||
{
|
||
MessageBox.Show("OCR相机打开失败");
|
||
}
|
||
// 设置图像格式
|
||
using (IEnumParameter p = m_dev_cam_ocr.ParameterCollection[ParametrizeNameSet.ImagePixelFormat])
|
||
{
|
||
p.SetValue("BayerRG8");
|
||
}
|
||
|
||
// 设置曝光
|
||
using (IFloatParameter p = m_dev_cam_ocr.ParameterCollection[ParametrizeNameSet.ExposureTime])
|
||
{
|
||
p.SetValue(800000);
|
||
}
|
||
// 设置增益
|
||
|
||
using (IFloatParameter p = m_dev_cam_ocr.ParameterCollection[ParametrizeNameSet.GainRaw])
|
||
{
|
||
p.SetValue(2.5);
|
||
}
|
||
using (IEnumParameter p = m_dev_cam_ocr.ParameterCollection[ParametrizeNameSet.AcquisitionMode])
|
||
{
|
||
p.SetValue("Continuous");
|
||
}
|
||
using (IEnumParameter p = m_dev_cam_ocr.ParameterCollection[ParametrizeNameSet.TriggerMode])
|
||
{
|
||
p.SetValue("On");
|
||
}
|
||
|
||
m_dev_cam_ocr.StreamGrabber.ImageGrabbed += StreamGrabber_ImageGrabbed_OCR;
|
||
m_dev_cam_ocr.StreamGrabber.GrabStarted += StreamGrabber_GrabStarted_OCR;
|
||
// 打开Software Trigger
|
||
// Set Software Trigger
|
||
m_dev_cam_ocr.TriggerSet.Open(TriggerSourceEnum.Software);
|
||
if (!m_dev_cam_ocr.GrabUsingGrabLoopThread())
|
||
{
|
||
// 开启采集失败
|
||
log.Error("开启采集失败");
|
||
return;
|
||
}
|
||
camOCROpened = true;
|
||
log.Info("OCR相机加载完毕");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
camOCROpened = false;
|
||
log.Error("OCR相机加载失败:" + ex.Message);
|
||
m_dev_cam_ocr = null;
|
||
}
|
||
}
|
||
private bool camOCROpened = false;
|
||
private bool camDETOpened = false;
|
||
#endregion
|
||
|
||
#region 相机1事件响应
|
||
|
||
void m_dev_cam_ocr_ConnectionLost(object sender, EventArgs e)
|
||
{
|
||
log.Error(m_dev_cam_ocr.DeviceInfo.Key + "OCR相机断线");
|
||
}
|
||
|
||
void m_dev_cam_ocr_CameraClosed(object sender, EventArgs e)
|
||
{
|
||
log.Error(m_dev_cam_ocr.DeviceInfo.Key + "OCR相机关闭");
|
||
}
|
||
|
||
void m_dev_cam_ocr_CameraOpened(object sender, EventArgs e)
|
||
{
|
||
|
||
}
|
||
|
||
void StreamGrabber_GrabStarted_OCR(object sender, EventArgs e)
|
||
{
|
||
log.Info("OCR相机启动码流");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 拍照完成后触发
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void StreamGrabber_ImageGrabbed_OCR(object sender, GrabbedEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
OCRResult(e.GrabResult.ToBitmap(true));
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
log.Error(ex.ToString());
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 相机2 定义为定位相机
|
||
private void InitializeCamerDET()
|
||
{
|
||
try
|
||
{
|
||
camDETOpened = false;
|
||
List<IDeviceInfo> deviceList = Enumerator.EnumerateDevices(); //发现设备,搜索所有大华相机
|
||
|
||
m_dev_cam_det = Enumerator.GetDeviceByKey("Machine Vision:BK27185BAK00038");//通过"设备厂商名:设备序列号"获取
|
||
if (m_dev_cam_det == null)
|
||
{
|
||
log.Error("未发现OCR相机,请检查相机连接");
|
||
return;
|
||
}
|
||
m_dev_cam_det.CameraOpened += m_dev_cam_det_CameraOpened;
|
||
m_dev_cam_det.CameraClosed += m_dev_cam_det_CameraClosed;
|
||
m_dev_cam_det.ConnectionLost += m_dev_cam_det_ConnectionLost;
|
||
|
||
if (!m_dev_cam_det.Open())
|
||
{
|
||
MessageBox.Show("定位相机打开失败");
|
||
}
|
||
// 设置图像格式
|
||
using (IEnumParameter p = m_dev_cam_det.ParameterCollection[ParametrizeNameSet.ImagePixelFormat])
|
||
{
|
||
p.SetValue("Mono");
|
||
}
|
||
|
||
// 设置曝光
|
||
using (IFloatParameter p = m_dev_cam_det.ParameterCollection[ParametrizeNameSet.ExposureTime])
|
||
{
|
||
p.SetValue(30000);
|
||
}
|
||
// 设置增益
|
||
using (IFloatParameter p = m_dev_cam_det.ParameterCollection[ParametrizeNameSet.GainRaw])
|
||
{
|
||
p.SetValue(1.0);
|
||
}
|
||
using (IEnumParameter p = m_dev_cam_det.ParameterCollection[ParametrizeNameSet.AcquisitionMode])
|
||
{
|
||
p.SetValue("Continuous");
|
||
}
|
||
using (IEnumParameter p = m_dev_cam_det.ParameterCollection[ParametrizeNameSet.TriggerMode])
|
||
{
|
||
p.SetValue("On");
|
||
}
|
||
m_dev_cam_det.StreamGrabber.ImageGrabbed += StreamGrabber_ImageGrabbed_DET;
|
||
m_dev_cam_det.StreamGrabber.GrabStarted += StreamGrabber_GrabStarted_DET;
|
||
// 打开Software Trigger
|
||
// Set Software Trigger
|
||
m_dev_cam_det.TriggerSet.Open(TriggerSourceEnum.Software);
|
||
if (!m_dev_cam_det.GrabUsingGrabLoopThread())
|
||
{
|
||
// 开启采集失败
|
||
log.Error("开启采集失败");
|
||
return;
|
||
}
|
||
camDETOpened = true;
|
||
log.Info("定位相机加载完毕");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
camDETOpened = false;
|
||
log.Error("定位相机加载失败:" + ex.Message);
|
||
m_dev_cam_det = null;
|
||
}
|
||
|
||
}
|
||
#endregion
|
||
|
||
#region 相机2事件响应
|
||
|
||
void m_dev_cam_det_ConnectionLost(object sender, EventArgs e)
|
||
{
|
||
log.Error(m_dev_cam_det.DeviceInfo.Key + "定位相机断线");
|
||
}
|
||
|
||
void m_dev_cam_det_CameraClosed(object sender, EventArgs e)
|
||
{
|
||
log.Error(m_dev_cam_det.DeviceInfo.Key + "定位相机关闭");
|
||
}
|
||
|
||
void m_dev_cam_det_CameraOpened(object sender, EventArgs e)
|
||
{
|
||
|
||
}
|
||
|
||
void StreamGrabber_GrabStarted_DET(object sender, EventArgs e)
|
||
{
|
||
log.Info("定位相机启动码流");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 拍照完成后触发
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void StreamGrabber_ImageGrabbed_DET(object sender, GrabbedEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
Bitmap bmp = null;
|
||
|
||
bmp = e.GrabResult.ToBitmap(true);
|
||
|
||
//Bitmap bmp = new Bitmap(cogimg.ToBitmap());
|
||
MemoryStream ms = new MemoryStream();
|
||
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
|
||
byte[] bytes = ms.GetBuffer();
|
||
ms.Close();
|
||
//保存DET图像
|
||
if (!Directory.Exists(SaveImageFileDET))
|
||
{
|
||
Directory.CreateDirectory(SaveImageFileDET);
|
||
}
|
||
string strTime = System.DateTime.Now.ToString("yyyyMMddHHmmss");
|
||
|
||
FileStream fs = new FileStream(SaveImageFileDET + '\\' + strTime + ".bmp", FileMode.Create);
|
||
BinaryWriter bw = new BinaryWriter(fs);
|
||
bw.Write(bytes, 0, bytes.Length);
|
||
bw.Close();
|
||
fs.Close();
|
||
log.Info("定位存图已完成");
|
||
|
||
|
||
CogImage8Grey cogimage = new CogImage8Grey(bmp);
|
||
|
||
//把图像给job中convertImagetool
|
||
CogToolGroup myTG = myJobDET.VisionTool as CogToolGroup;
|
||
CogToolBlock myTB = myTG.Tools["CogToolBlock1"] as CogToolBlock;
|
||
CogImageConvertTool cogImageConvert = myTB.Tools["CogImageConvertTool1"] as CogImageConvertTool;
|
||
|
||
cogImageConvert.InputImage = cogimage;
|
||
//运行jobmanager
|
||
myJobManagerDET.Run();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
EnableStartDetect();
|
||
log.Error(ex.ToString());
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
private void EnableStartDetect()
|
||
{
|
||
if (InvokeRequired)
|
||
{
|
||
BeginInvoke(new Action(EnableStartDetect));
|
||
return;
|
||
}
|
||
btn_StarDet_manual.Enabled = true;
|
||
btn_StarDet_manual.BackColor = Color.LimeGreen;
|
||
button1.Enabled = false;
|
||
button1.BackColor = Color.LightGray;
|
||
}
|
||
|
||
#region 相机关闭
|
||
void ClossCam()
|
||
{
|
||
//注销相机事件
|
||
if (m_dev_cam_ocr != null)
|
||
{
|
||
m_dev_cam_ocr.CameraOpened -= m_dev_cam_ocr_CameraOpened;
|
||
m_dev_cam_ocr.CameraClosed -= m_dev_cam_ocr_CameraClosed;
|
||
m_dev_cam_ocr.ConnectionLost -= m_dev_cam_ocr_ConnectionLost;
|
||
m_dev_cam_ocr.ShutdownGrab();
|
||
m_dev_cam_ocr.Dispose();
|
||
m_dev_cam_ocr = null;
|
||
}
|
||
if (m_dev_cam_det != null)
|
||
{
|
||
m_dev_cam_det.CameraOpened -= m_dev_cam_det_CameraOpened;
|
||
m_dev_cam_det.CameraClosed -= m_dev_cam_det_CameraClosed;
|
||
m_dev_cam_det.ConnectionLost -= m_dev_cam_det_ConnectionLost;
|
||
m_dev_cam_det.ShutdownGrab();
|
||
m_dev_cam_det.Dispose();
|
||
m_dev_cam_det = null;
|
||
}
|
||
}
|
||
#endregion
|
||
#endregion
|
||
|
||
#region OCR模型参数初始化
|
||
private void InitializePaddleOCR()
|
||
{
|
||
try
|
||
{
|
||
//模型初始化
|
||
OCRModelConfig config = new OCRModelConfig(); //创建一个模型参数设置对象
|
||
string rootPath = System.IO.Path.GetDirectoryName(typeof(OCRModelConfig).Assembly.Location); //程序的根目录
|
||
config.det_infer = rootPath + @"\Data\OCRModel\det_infer"; //文字检测模型路径
|
||
config.cls_infer = rootPath + @"\Data\OCRModel\cls_infer"; //文本角度模型路径
|
||
config.rec_infer = rootPath + @"\Data\OCRModel\rec_infer"; //文字内容识别模型路径
|
||
//以上三个模型参数的文件路径只需要写到存放的文件夹名称
|
||
//对于字典来说需要写全加上后缀
|
||
config.keys = rootPath + @"\Data\OCRModel\keys\ppocr_keys.txt"; //词典路径
|
||
|
||
//OCR参数设置
|
||
OCRParameter OcrParameter = new OCRParameter(); //创建一个检测参数设置对象
|
||
|
||
OcrParameter.cpu_math_library_num_threads = 8;//预测并发线程数
|
||
OcrParameter.enable_mkldnn = true;//web部署该值建议设置为0,否则出错,内存如果使用很大,建议该值也设置为0.
|
||
OcrParameter.cls = true; //是否执行文字方向分类;默认false
|
||
OcrParameter.det = true;//是否开启方向检测,用于检测识别180旋转
|
||
OcrParameter.rec = true;
|
||
OcrParameter.use_angle_cls = true;//是否开启方向检测,用于检测识别180旋转
|
||
OcrParameter.det_db_score_mode = true;//是否使用多段线,即文字区域是用多段线还是用矩形,
|
||
OcrParameter.det_db_unclip_ratio = 1.6f;
|
||
OcrParameter.max_side_len = 3800;
|
||
|
||
//初始化OCR
|
||
Engine = new PaddleOCREngine(config, OcrParameter);
|
||
log.Info("OCR模型初始化完成");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
log.Error(ex.Message + ex.StackTrace);
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 按钮事件
|
||
|
||
/// <summary>
|
||
/// 自动运行状态改变按钮
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void check_Autorun_CheckedChanged(object sender, EventArgs e)
|
||
{
|
||
if (check_Autorun.Checked)
|
||
{
|
||
log.Info("PC断开PLC连接,只可进行本地操作。");
|
||
check_Autorun.BackgroundImage = Image.FromFile(Application.StartupPath + "\\logo_image\\OFF.png");
|
||
panel_Manual.Visible = true;
|
||
btn_StarDet_manual.Enabled = false;
|
||
btn_StarDet_manual.BackColor = Color.LightGray;
|
||
ttls_PCLStatusShow.Visible = false;
|
||
}
|
||
else if (!check_Autorun.Checked)
|
||
{
|
||
log.Info("PC加载PLC已完成");
|
||
check_Autorun.BackgroundImage = Image.FromFile(Application.StartupPath + "\\logo_image\\ON.png");
|
||
panel_Manual.Visible = false;
|
||
if (orderLoaded)
|
||
{
|
||
btn_StarDet_manual.Enabled = true;
|
||
btn_StarDet_manual.BackColor = Color.LimeGreen;
|
||
}
|
||
ttls_PCLStatusShow.Visible = true;
|
||
}
|
||
}
|
||
private bool orderLoaded = false;
|
||
private Dictionary<int, List<string>> ocrTextRequest = new Dictionary<int, List<string>>();
|
||
private Dictionary<int, string> ocrTextDesign = new Dictionary<int, string>();
|
||
private Dictionary<string, bool> ocrTextResult = new Dictionary<string, bool>();
|
||
/// <summary>
|
||
/// 此按钮事件主要是获取excel表格内的数据
|
||
/// 包括定位偏移量,需要验证的字符
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void btn_OrderNum_Click(object sender, EventArgs e)
|
||
{
|
||
try
|
||
{
|
||
button1.Enabled = false;
|
||
orderLoaded = false;
|
||
btn_StarDet_manual.Enabled = false;
|
||
btn_StarDet_manual.BackColor = Color.LightGray;
|
||
listBox1.Items.Clear();
|
||
ocrTextRequest.Clear();
|
||
ocrTextDesign.Clear();
|
||
ClearData();
|
||
ClearDataShow();
|
||
Invoke(new Action(() =>
|
||
{
|
||
lbl_L1_verOcrRs.Text = "未启用";
|
||
lbl_L1_verOcrRs.BackColor = Color.Gray;
|
||
lbl_L2_verOcrRs.Text = "未启用";
|
||
lbl_L2_verOcrRs.BackColor = Color.Gray;
|
||
lbl_L3_verOcrRs.Text = "未启用";
|
||
lbl_L3_verOcrRs.BackColor = Color.Gray;
|
||
lbl_L4_verOcrRs.Text = "未启用";
|
||
lbl_L4_verOcrRs.BackColor = Color.Gray;
|
||
lbl_L5_verOcrRs.Text = "未启用";
|
||
lbl_L5_verOcrRs.BackColor = Color.Gray;
|
||
lbl_L6_verOcrRs.Text = "未启用";
|
||
lbl_L6_verOcrRs.BackColor = Color.Gray;
|
||
lbl_L7_verOcrRs.Text = "未启用";
|
||
lbl_L7_verOcrRs.BackColor = Color.Gray;
|
||
lbl_L8_verOcrRs.Text = "未启用";
|
||
lbl_L8_verOcrRs.BackColor = Color.Gray;
|
||
lbl_L9_verOcrRs.Text = "未启用";
|
||
lbl_L9_verOcrRs.BackColor = Color.Gray;
|
||
}));
|
||
btn_OrderNum.Enabled = false;
|
||
btn_OrderNum.BackColor = Color.LightGray;
|
||
//通过订单号获取表格中需要的值
|
||
string order = txt_OrderNum.Text;
|
||
if (string.IsNullOrEmpty(order))
|
||
{
|
||
log.Warn("订单号为空,请输入订单号。");
|
||
btn_OrderNum.Enabled = true;
|
||
btn_OrderNum.BackColor = Color.DeepSkyBlue;
|
||
return;
|
||
}
|
||
|
||
log.Info("当前订单号为:" + order);
|
||
//读取表格内容
|
||
ExcelPackage.License.SetNonCommercialOrganization("My Noncommercial organization");
|
||
using (ExcelPackage package = new ExcelPackage(execlFileName))
|
||
{
|
||
sheet1 = package.Workbook.Worksheets["P2生成数据"];
|
||
sheet2 = package.Workbook.Worksheets["QSV对应产品规格和梯度"];
|
||
sheet3 = package.Workbook.Worksheets["产品规格对应排布方式"];
|
||
//根据订单遍历sheet1 找Sequence QSV NumOFLanes 字符
|
||
string currentQSV = "";
|
||
for (int i = 1; i < sheet1.Dimension.Rows; i++)
|
||
{
|
||
if (sheet1.GetValue(i, 3) != null)
|
||
{
|
||
if (sheet1.Cells[i, 3].Value.ToString() == order)
|
||
{
|
||
currentQSV = sheet1.Cells[i, 4].Value.ToString();
|
||
lbl_QSV.Text = currentQSV;
|
||
log.Info("当前订单QSV:" + currentQSV);
|
||
NumberOfLanes = Convert.ToInt32(sheet1.Cells[i, 5].Value.ToString());
|
||
log.Info("当前订单Number Of Lanes:" + NumberOfLanes);
|
||
lbl_NO.Text = sheet1.Cells[i, 5].Value.ToString();
|
||
|
||
int num = 0;
|
||
for (int k = 0; k < 10; k++)
|
||
{
|
||
string lanes = sheet1.Cells[i + k, 6].Value.ToString();
|
||
string design = sheet1.Cells[i + k, 7].Value.ToString().Split('-')[1];
|
||
lanes = lanes.Substring(1, lanes.Length - 2);
|
||
string[] tmp = lanes.Split(',');
|
||
num += tmp.Length;
|
||
List<string> textOCR = ExecelGetOcrText(design, sheet1.Cells[i + k, 8].Value.ToString());
|
||
foreach (string lan in tmp)
|
||
{
|
||
int lanInt = Convert.ToInt32(lan);
|
||
ocrTextRequest[lanInt] = textOCR;
|
||
ocrTextDesign[lanInt] = design;
|
||
}
|
||
listBox1.Items.Add(sheet1.Cells[i + k, 6].Value.ToString());
|
||
listBox1.Items.Add(string.Join(",", textOCR));
|
||
|
||
if (num >= NumberOfLanes)
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(currentQSV))
|
||
{
|
||
string qsv;
|
||
//根据得到的QSV遍历sheet2 找产品规格和宽度梯度
|
||
for (int j = 1; j <= sheet2.Dimension.Rows; j++)
|
||
{
|
||
qsv = sheet2.Cells[j, 1].Value.ToString();
|
||
if (qsv == currentQSV)
|
||
{
|
||
m_ProductStandard = sheet2.Cells[j, 2].Value.ToString();
|
||
lbl_ProductStandard.Text = m_ProductStandard;
|
||
log.Info("当前订单产品编号:" + m_ProductStandard);
|
||
m_width = Convert.ToDouble(sheet2.Cells[j, 3].Value.ToString());
|
||
lbl_width.Text = sheet2.Cells[j, 3].Value.ToString();
|
||
log.Info("当前订单幅宽:" + m_width);
|
||
m_height = Convert.ToDouble(sheet2.Cells[j, 4].Value.ToString());
|
||
lbl_height.Text = sheet2.Cells[j, 4].Value.ToString();
|
||
log.Info("当前订单幅高:" + m_height);
|
||
m_Gradient = Convert.ToDouble(sheet2.Cells[j, 5].Value.ToString());
|
||
lbl_Gradient.Text = sheet2.Cells[j, 5].Value.ToString();
|
||
log.Info("当前订单梯度:" + m_Gradient);
|
||
break;
|
||
}
|
||
}
|
||
if (string.IsNullOrEmpty(m_ProductStandard))
|
||
{
|
||
log.Debug("ProductStandard未找到,请检查订单号是否正确");
|
||
btn_OrderNum.Enabled = true;
|
||
btn_OrderNum.BackColor = Color.DeepSkyBlue;
|
||
return;
|
||
}
|
||
//根据产品规格获取距离坐标
|
||
for (int n = 1; n < sheet3.Dimension.Rows; n++)
|
||
{
|
||
if (sheet3.GetValue(n, 1) != null)
|
||
{
|
||
if (sheet3.Cells[n, 1].Value.ToString() == m_ProductStandard)
|
||
{
|
||
string str = sheet3.Cells[n + ocrTextRequest[1].Count - 1, 4].Value.ToString();
|
||
string[] x_y = str.Split(',');
|
||
string[] X = x_y[0].Split(':');
|
||
string[] Y = x_y[1].Split(':');
|
||
m_DistX = Convert.ToDouble(X[1].Replace("mm", ""));
|
||
lbl_DistX.Text = X[1].Replace("mm", "");
|
||
log.Info("当前订单X偏移:" + m_DistX);
|
||
m_DistY = Convert.ToDouble(Y[1].Replace("mm", ""));
|
||
lbl_DistY.Text = Y[1].Replace("mm", "");
|
||
log.Info("当前订单Y偏移:" + m_DistY);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (m_DistX == 0 || m_DistY == 0)
|
||
{
|
||
log.Debug("DistX,DistY未找到,请检查订单号是否正确");
|
||
btn_OrderNum.Enabled = true;
|
||
btn_OrderNum.BackColor = Color.DeepSkyBlue;
|
||
return;
|
||
}
|
||
log.Info("相关数据已获取完成,且已显示在界面中,请查看。");
|
||
}
|
||
else
|
||
{
|
||
log.Debug("QSV未找到,请检查订单号是否正确");
|
||
btn_OrderNum.Enabled = true;
|
||
btn_OrderNum.BackColor = Color.DeepSkyBlue;
|
||
return;
|
||
}
|
||
}
|
||
|
||
//判断当前Lans决定结果显示数量
|
||
InitLableColumn();
|
||
|
||
btn_OrderNum.Enabled = true;
|
||
btn_OrderNum.BackColor = Color.DeepSkyBlue;
|
||
orderLoaded = true;
|
||
btn_StarDet_manual.Enabled = true;
|
||
btn_StarDet_manual.BackColor = Color.LimeGreen;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
log.Error("数据解析错误:" + ex.Message);
|
||
btn_OrderNum.Enabled = true;
|
||
btn_OrderNum.BackColor = Color.DeepSkyBlue;
|
||
}
|
||
}
|
||
private void InitLableColumn()
|
||
{
|
||
switch (NumberOfLanes)
|
||
{
|
||
case 1:
|
||
Invoke(new Action(() =>
|
||
{
|
||
lbl_L1_verOcrRs.Text = "启用";
|
||
lbl_L1_verOcrRs.BackColor = Color.Yellow;
|
||
}));
|
||
break;
|
||
case 2:
|
||
Invoke(new Action(() =>
|
||
{
|
||
lbl_L1_verOcrRs.Text = "启用";
|
||
lbl_L1_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L2_verOcrRs.Text = "启用";
|
||
lbl_L2_verOcrRs.BackColor = Color.Yellow;
|
||
}));
|
||
break;
|
||
case 3:
|
||
Invoke(new Action(() =>
|
||
{
|
||
lbl_L1_verOcrRs.Text = "启用";
|
||
lbl_L1_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L2_verOcrRs.Text = "启用";
|
||
lbl_L2_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L3_verOcrRs.Text = "启用";
|
||
lbl_L3_verOcrRs.BackColor = Color.Yellow;
|
||
}));
|
||
break;
|
||
case 4:
|
||
Invoke(new Action(() =>
|
||
{
|
||
lbl_L1_verOcrRs.Text = "启用";
|
||
lbl_L1_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L2_verOcrRs.Text = "启用";
|
||
lbl_L2_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L3_verOcrRs.Text = "启用";
|
||
lbl_L3_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L4_verOcrRs.Text = "启用";
|
||
lbl_L4_verOcrRs.BackColor = Color.Yellow;
|
||
}));
|
||
break;
|
||
case 5:
|
||
Invoke(new Action(() =>
|
||
{
|
||
lbl_L1_verOcrRs.Text = "启用";
|
||
lbl_L1_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L2_verOcrRs.Text = "启用";
|
||
lbl_L2_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L3_verOcrRs.Text = "启用";
|
||
lbl_L3_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L4_verOcrRs.Text = "启用";
|
||
lbl_L4_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L5_verOcrRs.Text = "启用";
|
||
lbl_L5_verOcrRs.BackColor = Color.Yellow;
|
||
}));
|
||
break;
|
||
case 6:
|
||
Invoke(new Action(() =>
|
||
{
|
||
lbl_L1_verOcrRs.Text = "启用";
|
||
lbl_L1_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L2_verOcrRs.Text = "启用";
|
||
lbl_L2_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L3_verOcrRs.Text = "启用";
|
||
lbl_L3_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L4_verOcrRs.Text = "启用";
|
||
lbl_L4_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L5_verOcrRs.Text = "启用";
|
||
lbl_L5_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L6_verOcrRs.Text = "启用";
|
||
lbl_L6_verOcrRs.BackColor = Color.Yellow;
|
||
|
||
}));
|
||
break;
|
||
case 7:
|
||
Invoke(new Action(() =>
|
||
{
|
||
lbl_L1_verOcrRs.Text = "启用";
|
||
lbl_L1_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L2_verOcrRs.Text = "启用";
|
||
lbl_L2_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L3_verOcrRs.Text = "启用";
|
||
lbl_L3_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L4_verOcrRs.Text = "启用";
|
||
lbl_L4_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L5_verOcrRs.Text = "启用";
|
||
lbl_L5_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L6_verOcrRs.Text = "启用";
|
||
lbl_L6_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L7_verOcrRs.Text = "启用";
|
||
lbl_L7_verOcrRs.BackColor = Color.Yellow;
|
||
}));
|
||
break;
|
||
case 8:
|
||
Invoke(new Action(() =>
|
||
{
|
||
lbl_L1_verOcrRs.Text = "启用";
|
||
lbl_L1_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L2_verOcrRs.Text = "启用";
|
||
lbl_L2_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L3_verOcrRs.Text = "启用";
|
||
lbl_L3_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L4_verOcrRs.Text = "启用";
|
||
lbl_L4_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L5_verOcrRs.Text = "启用";
|
||
lbl_L5_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L6_verOcrRs.Text = "启用";
|
||
lbl_L6_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L7_verOcrRs.Text = "启用";
|
||
lbl_L7_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L8_verOcrRs.Text = "启用";
|
||
lbl_L8_verOcrRs.BackColor = Color.Yellow;
|
||
}));
|
||
break;
|
||
case 9:
|
||
Invoke(new Action(() =>
|
||
{
|
||
lbl_L1_verOcrRs.Text = "启用";
|
||
lbl_L1_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L2_verOcrRs.Text = "启用";
|
||
lbl_L2_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L3_verOcrRs.Text = "启用";
|
||
lbl_L3_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L4_verOcrRs.Text = "启用";
|
||
lbl_L4_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L5_verOcrRs.Text = "启用";
|
||
lbl_L5_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L6_verOcrRs.Text = "启用";
|
||
lbl_L6_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L7_verOcrRs.Text = "启用";
|
||
lbl_L7_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L8_verOcrRs.Text = "启用";
|
||
lbl_L8_verOcrRs.BackColor = Color.Yellow;
|
||
lbl_L9_verOcrRs.Text = "启用";
|
||
lbl_L9_verOcrRs.BackColor = Color.Yellow;
|
||
}));
|
||
break;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 手动ocr
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void btn_manualOcr_Click(object sender, EventArgs e)
|
||
{
|
||
m_dev_cam_ocr?.ExecuteSoftwareTrigger();//相机1触发 = OCR拍照
|
||
log.Info("手动触发OCR");
|
||
}
|
||
/// <summary>
|
||
/// 手动定位
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void btn_manualDet_Click(object sender, EventArgs e)
|
||
{
|
||
m_dev_cam_det?.ExecuteSoftwareTrigger();
|
||
log.Info("手动触发定位");
|
||
}
|
||
private bool autorunFlag = false;
|
||
private bool debugFlag = false;
|
||
private void btn_StarDet_manual_Click(object sender, EventArgs e)
|
||
{
|
||
if (camOCROpened == false || camDETOpened == false)
|
||
{
|
||
MessageBox.Show("相机未打开,无法进行检测,请检查相机连接及状态!");
|
||
return;
|
||
}
|
||
|
||
if (PlcContinueFlag == false)
|
||
{
|
||
MessageBox.Show("PLC未处于运行状态,无法进行检测,请检查PLC连接及状态!");
|
||
return;
|
||
}
|
||
|
||
if (MessageBox.Show("确认OCR相机处于零点位置?", "提示", MessageBoxButtons.YesNo) == DialogResult.No)
|
||
{
|
||
return;
|
||
}
|
||
|
||
InitLableColumn();
|
||
|
||
ocrAcc.Clear();
|
||
debugFlag = checkBox1.Checked;
|
||
autorunFlag = check_Autorun.Checked;
|
||
btn_StarDet_manual.Enabled = false;
|
||
button1.Enabled = true;
|
||
btn_StarDet_manual.BackColor = Color.LightGray;
|
||
button1.BackColor = Color.LimeGreen;
|
||
m_dev_cam_det?.ExecuteSoftwareTrigger();
|
||
list_Log.Clear();
|
||
log.Info("手动触发开始");
|
||
}
|
||
|
||
private List<string> ExecelGetOcrText(string design, string layer)
|
||
{
|
||
List<string> result = new List<string>();
|
||
string[] ll = layer.Replace("[", "").Replace("]", "").Split(',');
|
||
for (int i = 0; i < ll.Length; i++)
|
||
{
|
||
ll[i] = ll[i].Replace(" ", "");
|
||
string[] str = ll[i].Split('-');
|
||
if (str.Length < 2)
|
||
continue;
|
||
result.Add(design + str[1] + str[0]);
|
||
}
|
||
return result;
|
||
}
|
||
/// <summary>
|
||
/// 清空上次订单数据
|
||
/// </summary>
|
||
void ClearData()
|
||
{
|
||
m_ProductStandard = null;
|
||
NumberOfLanes = 0; m_width = 0; m_Gradient = 0; m_DistX = 0; m_DistY = 0;
|
||
m_height = 0;
|
||
}
|
||
/// <summary>
|
||
/// 清空上次订单显示区
|
||
/// </summary>
|
||
void ClearDataShow()
|
||
{
|
||
lbl_QSV.Text = "";
|
||
lbl_NO.Text = "";
|
||
lbl_ProductStandard.Text = "";
|
||
lbl_width.Text = "";
|
||
lbl_Gradient.Text = "";
|
||
lbl_DistX.Text = "";
|
||
lbl_DistY.Text = "";
|
||
}
|
||
|
||
private void txt_OrderNum_KeyDown(object sender, KeyEventArgs e)
|
||
{
|
||
if (e.KeyCode == Keys.Enter)
|
||
{
|
||
btn_OrderNum_Click(sender, e);
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region OCR相机拍照触发处理函数
|
||
/// <summary>
|
||
/// OCR相机拍照信号过来需要进行的操作
|
||
/// </summary>
|
||
/// <param name="sender"></param>
|
||
/// <param name="e"></param>
|
||
private void OcrCamTriger()
|
||
{
|
||
try
|
||
{
|
||
log.Info("PLC触发OCR相机,正在拍照计算...");
|
||
m_dev_cam_ocr?.ExecuteSoftwareTrigger();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
log.Error(ex.Message);
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 结果处理
|
||
|
||
#region 定位结果处理
|
||
public void DetResult(object sender, CogJobManagerActionEventArgs e)
|
||
{
|
||
try
|
||
{
|
||
if (InvokeRequired)
|
||
{
|
||
Invoke(new DetResultDelegate(DetResult), new object[] { sender, e });
|
||
return;
|
||
}
|
||
//清除上次的结果显示
|
||
lbl_XShow.Text = "";
|
||
lbl_YShow.Text = "";
|
||
lbl_RShow.Text = "";
|
||
|
||
CogToolGroup myTG = myJobDET.VisionTool as CogToolGroup;
|
||
CogToolBlock myTB = myTG.Tools["CogToolBlock1"] as CogToolBlock;
|
||
CogPMAlignTool myPMA = myTB.Tools["CogPMAlignTool2"] as CogPMAlignTool;
|
||
CogImageConvertTool myImage = myTB.Tools["CogImageConvertTool1"] as CogImageConvertTool;
|
||
|
||
Location_Display.Image = myPMA.InputImage;
|
||
Location_Display.StaticGraphics.Clear();
|
||
Location_Display.InteractiveGraphics.Clear();
|
||
Location_Display.Fit();
|
||
if (myPMA.Results != null)
|
||
{
|
||
int i = GetXYRonRightDown(myPMA.Results);//获取视野中最右下边的K标志坐标的索引
|
||
double xx = myPMA.Results[i].GetPose().TranslationX;
|
||
double yy = myPMA.Results[i].GetPose().TranslationY;
|
||
double rr = CogMisc.RadToDeg(myPMA.Results[i].GetPose().Rotation);
|
||
|
||
lbl_XShow.Text = xx.ToString();
|
||
lbl_YShow.Text = yy.ToString();
|
||
lbl_RShow.Text = rr.ToString();
|
||
log.Info($"x:{xx} y:{yy} degree:{rr}");
|
||
|
||
//画模型轮廓
|
||
CogCompositeShape shape = myPMA.Results[i].CreateResultGraphics(CogPMAlignResultGraphicConstants.MatchFeatures);
|
||
CogCompositeShape shape1 = myPMA.Results[i].CreateResultGraphics(CogPMAlignResultGraphicConstants.CoordinateAxes);
|
||
Location_Display.InteractiveGraphics.Add(shape, "", false);
|
||
Location_Display.InteractiveGraphics.Add(shape1, "", false);
|
||
//画定位的十字点
|
||
CPMARunStatus.DrawPointMarker(xx, yy, CogMisc.DegToRad(rr), CogColorConstants.Orange, Location_Display, ".");
|
||
log.Info("定位计算已完成。");
|
||
sendToPLC(xx, yy, rr);
|
||
}
|
||
else
|
||
{
|
||
EnableStartDetect();
|
||
log.Info("没有定位到K标志,请查看图像或相机是否正常");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
EnableStartDetect();
|
||
log.Error(ex.Message + "未检测到K标志");
|
||
NoticePLCCompleteDet(DataConverter.FloatToByte(0.0f, true));
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取右下角定位标志坐标
|
||
/// </summary>
|
||
/// <param name="Results">PatMAX结果</param>
|
||
/// <returns></returns>
|
||
private int GetXYRonRightDown(CogPMAlignResults Results)
|
||
{
|
||
|
||
int i = 0;
|
||
double[] xx = new double[Results.Count], yy = new double[Results.Count], rr = new double[Results.Count];
|
||
//第一次循环将所有坐标取出
|
||
for (int j = 0; j < Results.Count; j++)
|
||
{
|
||
xx[j] = Results[j].GetPose().TranslationX;
|
||
yy[j] = Results[j].GetPose().TranslationY;
|
||
rr[j] = CogMisc.RadToDeg(Results[j].GetPose().Rotation);
|
||
}
|
||
if (Results.Count == 1)
|
||
{
|
||
i = 0;
|
||
}
|
||
else if (Results.Count == 2)
|
||
{
|
||
double Xdist, Ydist;
|
||
Xdist = Math.Abs(xx[0] - xx[1]);
|
||
Ydist = Math.Abs(yy[0] - yy[1]);
|
||
if (Xdist > Ydist)
|
||
{
|
||
i = Array.IndexOf(xx, xx.Min());
|
||
}
|
||
else if (Xdist < Ydist)
|
||
{
|
||
i = Array.IndexOf(yy, yy.Max());
|
||
}
|
||
}
|
||
else
|
||
{
|
||
double averageX = xx.Average();
|
||
//第二次循环保留x比平均x值小的元素
|
||
for (int j = 0; j < Results.Count; j++)
|
||
{
|
||
if (averageX < xx[j])
|
||
{
|
||
xx[j] = -9999;
|
||
yy[j] = -9999;
|
||
}
|
||
}
|
||
//找出保留元素中Y值最大的
|
||
i = Array.IndexOf(yy, yy.Max());
|
||
}
|
||
return i;
|
||
}
|
||
#endregion
|
||
|
||
#region 排序算法
|
||
List<Point> paixu(List<Point> points)
|
||
{
|
||
int rowDistance = 50;
|
||
List<List<Point>> rows = new List<List<Point>>();
|
||
|
||
for (int i = 0; i < points.Count; i++)
|
||
{
|
||
List<Point> row = new List<Point>();
|
||
row.Add(points[i]);
|
||
|
||
for (int j = i + 1; j < points.Count; j++)
|
||
{
|
||
if (Math.Abs(points[j].y - points[i].y) < rowDistance)
|
||
{
|
||
row.Add(points[j]);
|
||
}
|
||
}
|
||
rows.Add(row);
|
||
}
|
||
|
||
List<Point> sortedPoints = new List<Point>();
|
||
|
||
foreach (List<Point> row in rows)
|
||
{
|
||
row.Sort((x, y) => x.x - y.x);
|
||
foreach (Point point in row)
|
||
{
|
||
if (!sortedPoints.Contains(point))
|
||
{
|
||
sortedPoints.Add(point);
|
||
}
|
||
}
|
||
}
|
||
|
||
return sortedPoints;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region OCR结果处理
|
||
private void OCRResult(Bitmap bmp)
|
||
{
|
||
try
|
||
{
|
||
if (InvokeRequired)
|
||
{
|
||
Invoke(new OcrResultDelegate(OCRResult), new object[] { bmp });
|
||
return;
|
||
}
|
||
ocrTextResult = new Dictionary<string, bool>();
|
||
if (!ocrTextRequest.ContainsKey(mMatchingStr))
|
||
{
|
||
log.Error($"未知列{mMatchingStr},舍弃图片");
|
||
NoticePLCCompleteOCR();
|
||
return;
|
||
}
|
||
foreach (var item in ocrTextRequest[mMatchingStr])
|
||
{
|
||
ocrTextResult[item] = false;
|
||
}
|
||
MemoryStream ms = new MemoryStream();
|
||
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
|
||
byte[] bytes = ms.GetBuffer();
|
||
ms.Close();
|
||
string strtimef = DateTime.Now.ToString("yyyy-MM-dd");
|
||
//保存ocr图像
|
||
if (!Directory.Exists(SaveImageFileOCR + '\\' + strtimef))
|
||
{
|
||
Directory.CreateDirectory(SaveImageFileOCR + '\\' + strtimef);
|
||
}
|
||
string strTime = System.DateTime.Now.ToString("yyyyMMddHHmmss");
|
||
FileStream fs = new FileStream(SaveImageFileOCR + '\\' + strtimef + '\\' + strTime + ".bmp", FileMode.Create);
|
||
BinaryWriter bw = new BinaryWriter(fs);
|
||
bw.Write(bytes, 0, bytes.Length);
|
||
bw.Close();
|
||
fs.Close();
|
||
log.Info("OCR存图已完成");
|
||
|
||
CutPicture(SaveImageFileOCR + '\\' + strtimef + '\\' + strTime + ".bmp", 1000, 1800, 3800, 1600);
|
||
if (Engine == null)
|
||
{
|
||
log.Error("Engine未初始化");
|
||
NoticePLCCompleteOCR();
|
||
return;
|
||
}
|
||
|
||
GetOCRImage getOCRImage = new GetOCRImage();
|
||
GetOCRImage.FileTimeInfo file = getOCRImage.GetLatesFileImageName(SaveImageFileOCR + '\\' + strtimef, ".bmp");
|
||
if (file != null)
|
||
{
|
||
Mat bgr = Cv2.ImRead(file.FileName, ImreadModes.Color); // 读入 BGR
|
||
if (bgr.Empty())
|
||
{
|
||
log.Error("OCR图片转换失败");
|
||
NoticePLCCompleteOCR();
|
||
return;
|
||
}
|
||
Mat hsv = new Mat();
|
||
Cv2.CvtColor(bgr, hsv, ColorConversionCodes.BGR2HSV); // 1. 转 HSV
|
||
Mat[] channels = Cv2.Split(hsv); // 2. 拆通道
|
||
Mat h = channels[0]; // Hue 0-180
|
||
Mat s = channels[1]; // Saturation 0-255
|
||
Mat v = channels[2]; // Value 0-255
|
||
|
||
OCRTextResult hResult = null;
|
||
OCRTextResult sResult = null;
|
||
OCRTextResult vResult = null;
|
||
|
||
bool matchOK = false;
|
||
PointF[] pointsTotal = null;
|
||
sResult = OCRBytes(s.ImEncode(".png"));
|
||
if (sResult == null)
|
||
{
|
||
log.Error("s通道,OCR字符识别失败");
|
||
NoticePLCCompleteOCR();
|
||
return;
|
||
}
|
||
txt_readOcrResultShow.Text = sResult.text;
|
||
log.Info("s通道字符读取结果:" + sResult.text);
|
||
matchOK = sResult.match;
|
||
pointsTotal = sResult.points;
|
||
|
||
if (!matchOK)
|
||
{
|
||
hResult = OCRBytes(h.ImEncode(".png"));
|
||
if (hResult == null)
|
||
{
|
||
log.Error("h通道,OCR字符识别失败");
|
||
NoticePLCCompleteOCR();
|
||
return;
|
||
}
|
||
txt_readOcrResultShow.Text += "\n" + hResult.text;
|
||
log.Info("h通道字符读取结果:" + hResult.text);
|
||
matchOK = hResult.match;
|
||
if (hResult.points != null && hResult.points.Length > 0)
|
||
{
|
||
List<PointF> pp1 = hResult.points.ToList();
|
||
List<PointF> pp = pointsTotal.ToList();
|
||
pp.AddRange(pp1);
|
||
pointsTotal = pp.Distinct().ToArray();
|
||
}
|
||
}
|
||
if (!matchOK)
|
||
{
|
||
vResult = OCRBytes(v.ImEncode(".png"));
|
||
if (vResult == null)
|
||
{
|
||
log.Error("v通道,OCR字符识别失败");
|
||
NoticePLCCompleteOCR();
|
||
return;
|
||
}
|
||
txt_readOcrResultShow.Text += "\n" + vResult.text;
|
||
log.Info("v通道字符读取结果:" + vResult.text);
|
||
matchOK = vResult.match;
|
||
if (vResult.points != null && vResult.points.Length > 0)
|
||
{
|
||
List<PointF> pp1 = vResult.points.ToList();
|
||
List<PointF> pp = pointsTotal.ToList();
|
||
pp.AddRange(pp1);
|
||
pointsTotal = pp.Distinct().ToArray();
|
||
}
|
||
}
|
||
|
||
if (pointsTotal != null && pointsTotal.Length > 0)
|
||
{
|
||
byte[] ocrimagebyte = File.ReadAllBytes(file.FileName);
|
||
Bitmap Bmp = new Bitmap(new MemoryStream(ocrimagebyte));
|
||
using (Graphics g = Graphics.FromImage(Bmp))
|
||
{
|
||
g.DrawPolygon(new Pen(Brushes.Red, 2), pointsTotal.Select(x => new PointF() { X = x.X, Y = x.Y }).ToArray());
|
||
}
|
||
Ocr_picBox.BackgroundImage = null;
|
||
Ocr_picBox.BackgroundImage = Bmp;
|
||
int m1 = ocrTextResult.Count(x => x.Value);
|
||
log.Info($"OCR识别完成,匹配成功{m1}个字符,匹配失败{ocrTextResult.Count - m1}个字符");
|
||
ShowTheLansRs(mMatchingStr, (float)m1 / (float)ocrTextResult.Count);
|
||
}
|
||
|
||
NoticePLCCompleteOCR();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
log.Error(ex.Message + "未检测到字符");
|
||
NoticePLCCompleteOCR();
|
||
}
|
||
}
|
||
private void NoticePLCCompleteOCR()
|
||
{
|
||
if (autorunFlag == false)
|
||
{
|
||
byte[] datax = DataConverter.FloatToByte(0.0f, true);
|
||
cc24?.NotifyCamInspectionComplete(1, datax);
|
||
cc24?.NotifyCamAcqComplete(1);
|
||
}
|
||
}
|
||
private void NoticePLCCompleteDet(byte[] datax)
|
||
{
|
||
if (autorunFlag == false)
|
||
{
|
||
cc24?.NotifyCamInspectionComplete(0, datax);
|
||
cc24?.NotifyCamAcqComplete(0);
|
||
}
|
||
}
|
||
private OCRTextResult OCRBytes(byte[] ocrimagebyte)
|
||
{
|
||
try
|
||
{
|
||
OCRTextResult result = new OCRTextResult();
|
||
List<string> lastocr = new List<string>();
|
||
OCRResult ocrResult = Engine.DetectText(ocrimagebyte);
|
||
List<Point> pointsList = new List<Point>();
|
||
|
||
foreach (var item in ocrResult.TextBlocks)
|
||
{
|
||
if (item.Text.Contains(ocrTextDesign[mMatchingStr]))
|
||
{
|
||
result.points = item.BoxPoints.Select(x => new PointF() { X = x.X, Y = x.Y }).ToArray();
|
||
pointsList.Add(new Point(item.BoxPoints[0].X, item.BoxPoints[0].Y, item.Text));
|
||
}
|
||
}
|
||
|
||
List<Point> paixujeguo = paixu(pointsList);
|
||
foreach (var it in paixujeguo)
|
||
{
|
||
lastocr.Add(it.txt);
|
||
}
|
||
result.text = GETOCR(lastocr, ocrTextDesign[mMatchingStr]);
|
||
|
||
var keysToUpdate = new List<string>();
|
||
foreach (var item in ocrTextResult)
|
||
{
|
||
if (result.text.Contains(item.Key))
|
||
keysToUpdate.Add(item.Key);
|
||
}
|
||
|
||
foreach (var item in keysToUpdate)
|
||
{
|
||
ocrTextResult[item] = true;
|
||
}
|
||
|
||
result.match = true;
|
||
foreach (var item in ocrTextResult)
|
||
{
|
||
if (!item.Value)
|
||
result.match = false;
|
||
}
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
log.Error(ex.Message + ex.StackTrace);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
#region 图片裁剪
|
||
private void CutPicture(String picPath, int x, int y, int width, int height)
|
||
{
|
||
//图片路径
|
||
String oldPath = picPath;
|
||
//新图片路径
|
||
String newPath = System.IO.Path.GetExtension(oldPath);
|
||
//计算新的文件名,在新文件名后加_new
|
||
newPath = oldPath.Substring(0, oldPath.Length - newPath.Length) + "_new" + mMatchingStr + newPath;
|
||
//定义截取矩形
|
||
System.Drawing.Rectangle cropArea = new System.Drawing.Rectangle(x, y, width, height);
|
||
//要截取的区域大小
|
||
//加载图片
|
||
System.Drawing.Image img = System.Drawing.Image.FromStream(new System.IO.MemoryStream(System.IO.File.ReadAllBytes(oldPath)));
|
||
//判断超出的位置否
|
||
if ((img.Width < x + width) || img.Height < y + height)
|
||
{
|
||
MessageBox.Show("裁剪尺寸超出原有尺寸!");
|
||
img.Dispose();
|
||
return;
|
||
}
|
||
//定义Bitmap对象
|
||
System.Drawing.Bitmap bmpImage = new System.Drawing.Bitmap(img);
|
||
//进行裁剪
|
||
System.Drawing.Bitmap bmpCrop = bmpImage.Clone(cropArea, bmpImage.PixelFormat);
|
||
//保存成新文件
|
||
bmpCrop.Save(newPath);
|
||
//释放对象
|
||
img.Dispose();
|
||
bmpCrop.Dispose();
|
||
}
|
||
#endregion
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 使用正则表达式提取结果
|
||
/// </summary>
|
||
/// <param name="readOCR">读到的所有字符</param>
|
||
/// <param name="design">设计</param>
|
||
/// <param name="colours"></param>
|
||
/// <returns></returns>
|
||
private string GETOCR(List<string> readOCR, string design)
|
||
{
|
||
string ocrresult = "";
|
||
string pattern = @"" + design + "[A-Z0-9]{8}";
|
||
for (int i = 0; i < readOCR.Count; i++)
|
||
{
|
||
readOCR[i] = readOCR[i].Replace("_", "");
|
||
readOCR[i] = readOCR[i].Replace(" ", "");
|
||
}
|
||
MatchCollection matchResults;
|
||
|
||
try
|
||
{
|
||
foreach (var item in readOCR)
|
||
{
|
||
matchResults = Regex.Matches(item, pattern);
|
||
for (int i = 0; i < matchResults.Count; i++)
|
||
{
|
||
ocrresult = ocrresult + matchResults[i];
|
||
}
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
ocrresult = null;
|
||
}
|
||
if (ocrresult != null)
|
||
{
|
||
return ocrresult;
|
||
}
|
||
else
|
||
{
|
||
return "未能匹配到对应字符请查看产品是否超标,或订单号是否正确";
|
||
}
|
||
}
|
||
private void button1_Click(object sender, EventArgs e)
|
||
{
|
||
btn_StarDet_manual.Enabled = true;
|
||
button1.Enabled = false;
|
||
btn_StarDet_manual.BackColor = Color.LimeGreen;
|
||
button1.BackColor = Color.LightGray;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将结果显示在对应状态栏
|
||
/// </summary>
|
||
/// <param name="mM">PLC给的当前在第几道拍照</param>
|
||
/// <param name="s">OCR字符相似度结果</param>
|
||
void ShowTheLansRs(float mM, float s)
|
||
{
|
||
int mMnum = Convert.ToInt32(mM);
|
||
switch (mMnum)
|
||
{
|
||
case 1:
|
||
lbl_L1_verOcrRs.BackColor = Color.Lime;
|
||
if (s < 0.9)
|
||
{
|
||
lbl_L1_verOcrRs.BackColor = Color.Red;
|
||
}
|
||
else if (s > 0.9 & s < 1)
|
||
{
|
||
lbl_L1_verOcrRs.BackColor = Color.Lime;
|
||
s = 1;
|
||
}
|
||
ocrAcc.Add(s);
|
||
lbl_L1_verOcrRs.Text = s * 100 + "%";
|
||
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
|
||
break;
|
||
case 2:
|
||
lbl_L2_verOcrRs.BackColor = Color.Lime;
|
||
if (s < 0.9)
|
||
{
|
||
lbl_L2_verOcrRs.BackColor = Color.Red;
|
||
}
|
||
else if (s > 0.9 & s < 1)
|
||
{
|
||
lbl_L2_verOcrRs.BackColor = Color.Lime;
|
||
s = 1;
|
||
}
|
||
ocrAcc.Add(s);
|
||
lbl_L2_verOcrRs.Text = s * 100 + "%";
|
||
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
|
||
break;
|
||
case 3:
|
||
lbl_L3_verOcrRs.BackColor = Color.Lime;
|
||
if (s < 0.9)
|
||
{
|
||
lbl_L3_verOcrRs.BackColor = Color.Red;
|
||
}
|
||
else if (s > 0.9 & s < 1)
|
||
{
|
||
lbl_L3_verOcrRs.BackColor = Color.Lime;
|
||
s = 1;
|
||
}
|
||
ocrAcc.Add(s);
|
||
lbl_L3_verOcrRs.Text = s * 100 + "%";
|
||
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
|
||
break;
|
||
case 4:
|
||
lbl_L4_verOcrRs.BackColor = Color.Lime;
|
||
if (s < 0.9)
|
||
{
|
||
lbl_L4_verOcrRs.BackColor = Color.Red;
|
||
}
|
||
else if (s > 0.9 & s < 1)
|
||
{
|
||
lbl_L4_verOcrRs.BackColor = Color.Lime;
|
||
s = 1;
|
||
}
|
||
ocrAcc.Add(s);
|
||
lbl_L4_verOcrRs.Text = s * 100 + "%";
|
||
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
|
||
break;
|
||
case 5:
|
||
lbl_L5_verOcrRs.BackColor = Color.Lime;
|
||
if (s < 0.9)
|
||
{
|
||
lbl_L5_verOcrRs.BackColor = Color.Red;
|
||
}
|
||
else if (s > 0.9 & s < 1)
|
||
{
|
||
lbl_L5_verOcrRs.BackColor = Color.Lime;
|
||
s = 1;
|
||
}
|
||
ocrAcc.Add(s);
|
||
lbl_L5_verOcrRs.Text = s * 100 + "%";
|
||
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
|
||
break;
|
||
case 6:
|
||
lbl_L6_verOcrRs.BackColor = Color.Lime;
|
||
if (s < 0.9)
|
||
{
|
||
lbl_L6_verOcrRs.BackColor = Color.Red;
|
||
}
|
||
else if (s > 0.9 & s < 1)
|
||
{
|
||
lbl_L6_verOcrRs.BackColor = Color.Lime;
|
||
s = 1;
|
||
}
|
||
ocrAcc.Add(s);
|
||
lbl_L6_verOcrRs.Text = s * 100 + "%";
|
||
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
|
||
break;
|
||
case 7:
|
||
lbl_L7_verOcrRs.BackColor = Color.Lime;
|
||
if (s < 0.9)
|
||
{
|
||
lbl_L7_verOcrRs.BackColor = Color.Red;
|
||
}
|
||
else if (s > 0.9 & s < 1)
|
||
{
|
||
lbl_L7_verOcrRs.BackColor = Color.Lime;
|
||
s = 1;
|
||
}
|
||
ocrAcc.Add(s);
|
||
lbl_L7_verOcrRs.Text = s * 100 + "%";
|
||
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
|
||
break;
|
||
case 8:
|
||
lbl_L8_verOcrRs.BackColor = Color.Lime;
|
||
if (s < 0.9)
|
||
{
|
||
lbl_L8_verOcrRs.BackColor = Color.Red;
|
||
}
|
||
else if (s > 0.9 & s < 1)
|
||
{
|
||
lbl_L8_verOcrRs.BackColor = Color.Lime;
|
||
s = 1;
|
||
}
|
||
ocrAcc.Add(s);
|
||
lbl_L8_verOcrRs.Text = s * 100 + "%";
|
||
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
|
||
break;
|
||
case 9:
|
||
lbl_L9_verOcrRs.BackColor = Color.Lime;
|
||
if (s < 0.9)
|
||
{
|
||
lbl_L9_verOcrRs.BackColor = Color.Red;
|
||
}
|
||
else if (s > 0.9 & s < 1)
|
||
{
|
||
lbl_L9_verOcrRs.BackColor = Color.Lime;
|
||
s = 1;
|
||
}
|
||
ocrAcc.Add(s);
|
||
lbl_L9_verOcrRs.Text = s * 100 + "%";
|
||
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
|
||
break;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#endregion
|
||
|
||
#region 通讯相关
|
||
|
||
#region 通讯初始化
|
||
void InitializeCC24()
|
||
{
|
||
try
|
||
{
|
||
cc24 = new CC24();
|
||
|
||
cc24.VisionReceivedNewUserData += CC24_NewUserDataReceived;
|
||
cc24.PlcConnectionStatusChanged += CC24_PlcConnectionStatusChanged;
|
||
cc24.PlcTriggerCamAcqStart += CC24_PlcTriggerCamAcqStart;
|
||
cc24.PlcTriggerCamAcqStop += CC24_PlcTriggerCamAcqStop;
|
||
cc24.NotifyCamAcqEnabled += CC24_NotifyCamAcqEnabled;
|
||
cc24.NotifyCamAcqDisabled += CC24_NotifyCamAcqDisabled;
|
||
|
||
|
||
|
||
cc24.Initialize();
|
||
cc24.NotifyCamAcqEnable(0);
|
||
cc24.NotifyCamAcqEnable(1);
|
||
|
||
Invoke(new Action(() =>
|
||
{
|
||
if (cc24.SignalState.PlcConnectionStatus)
|
||
{
|
||
ttls_PCLStatusShow.Visible = true;
|
||
}
|
||
else
|
||
{
|
||
ttls_PCLStatusShow.Visible = false;
|
||
|
||
}
|
||
}));
|
||
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
log.Error($"CommCard Initialize Error: {ex.Message}");
|
||
}
|
||
|
||
}
|
||
#endregion
|
||
|
||
#region 相机采集使能状态
|
||
private void CC24_NotifyCamAcqEnabled(int cameraIndex, bool isEnabled)
|
||
{
|
||
|
||
Invoke(new Action(() =>
|
||
{
|
||
if (isEnabled)
|
||
{
|
||
ttls_AcqEnableShow.Visible = true;
|
||
}
|
||
else
|
||
{
|
||
ttls_AcqEnableShow.Visible = false;
|
||
}
|
||
}));
|
||
}
|
||
|
||
private void CC24_NotifyCamAcqDisabled(int cameraIndex, bool isEnabled)
|
||
{
|
||
Invoke(new Action(() =>
|
||
{
|
||
if (isEnabled)
|
||
{
|
||
ttls_AcqEnableShow.Visible = true;
|
||
}
|
||
else
|
||
{
|
||
ttls_AcqEnableShow.Visible = false;
|
||
}
|
||
}));
|
||
|
||
}
|
||
#endregion
|
||
|
||
#region 接收PLC数据
|
||
void CC24_NewUserDataReceived(object sender, CogNdmNewUserDataEventArgs e)
|
||
{
|
||
if (InvokeRequired)
|
||
{
|
||
Invoke(new CogNdmNewUserDataEventHandler(CC24_NewUserDataReceived), new object[] { sender, e });
|
||
return;
|
||
}
|
||
|
||
byte[] data = cc24.ReadBytesFromPLC(0, 4);
|
||
float mMatchingStrf = DataConverter.ByteToFloat(data, true);
|
||
mMatchingStr = Convert.ToInt32(mMatchingStrf);
|
||
|
||
log.Info("PC接收PLC数据:数据内容:" + mMatchingStr);
|
||
if (NumberOfLanes + 1 == mMatchingStr)
|
||
{
|
||
EnableStartDetect();
|
||
if (ocrAcc.Count == 0)
|
||
return;
|
||
if (ocrAcc.Min() < 0.95)
|
||
{
|
||
MessageBox.Show("当前检测中出现严重错误请注意!", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
else if (ocrAcc.Min() > 0.95 & ocrAcc.Min() < 1)
|
||
{
|
||
MessageBox.Show("当前检测中出现可允许误差请注意!", Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 接收触发相机信号
|
||
void CC24_PlcTriggerCamAcqStart(object sender, CogNdmTriggerAcquisitionEventArgs e)
|
||
{
|
||
if (InvokeRequired)
|
||
{
|
||
Invoke(new CogNdmTriggerAcquisitionEventHandler(CC24_PlcTriggerCamAcqStart), new object[] { sender, e });
|
||
return;
|
||
}
|
||
try
|
||
{
|
||
if (e.CameraIndex == 1)
|
||
{
|
||
Thread.Sleep(1000);
|
||
OcrCamTriger();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
log.Error($"Trigger AcqStart Error: {ex.Message}");
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 相机停止
|
||
private void CC24_PlcTriggerCamAcqStop(object sender, CogNdmTriggerAcquisitionStopEventArgs e)
|
||
{
|
||
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 通讯状态发生改变
|
||
private void CC24_PlcConnectionStatusChanged(object sender, CogNdmProtocolStatusChangedEventArgs e)
|
||
{
|
||
if (InvokeRequired)
|
||
{
|
||
Invoke(new CogNdmProtocolStatusChangedEventHandler(CC24_PlcConnectionStatusChanged), new object[] { sender, e });
|
||
return;
|
||
}
|
||
if (e.ProtocolStatus == CogNdmConnectionStatusConstants.Connected)
|
||
{
|
||
PlcContinueFlag = true;
|
||
log.Info("PLC已连接PC,可以进行相关操作");
|
||
ttls_PCLStatusShow.Visible = true;
|
||
}
|
||
else if (e.ProtocolStatus != CogNdmConnectionStatusConstants.Connecting)
|
||
{
|
||
PlcContinueFlag = false;
|
||
log.Info("PLC已断开PC,请查看相关设备是否连接");
|
||
ttls_PCLStatusShow.Visible = false;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 通讯发送坐标
|
||
private void sendToPLC(double x, double y, double r)
|
||
{
|
||
try
|
||
{
|
||
float xx = (float)x;
|
||
float yy = (float)y;
|
||
float rr = (float)r;
|
||
List<float> ocrxx = new List<float>();
|
||
List<float> ocryy = new List<float>();
|
||
|
||
switch (m_ProductStandard)
|
||
{
|
||
case "TBA1000Slim":
|
||
switch (ocrTextRequest[1].Count)
|
||
{
|
||
case 1:
|
||
xx = (float)x - 9.5f;
|
||
break;
|
||
case 2:
|
||
xx = (float)x - 19f;
|
||
break;
|
||
case 3:
|
||
xx = (float)x - 28.5f;
|
||
break;
|
||
case 4:
|
||
xx = (float)x - 38f;
|
||
break;
|
||
case 5:
|
||
xx = (float)x - 47.5f;
|
||
break;
|
||
case 6:
|
||
xx = (float)x - 57f;
|
||
break;
|
||
}
|
||
break;
|
||
case "TBA250B":
|
||
switch (ocrTextRequest[1].Count)
|
||
{
|
||
case 1:
|
||
xx = (float)x - 9.5f;
|
||
break;
|
||
case 2:
|
||
xx = (float)x - 19f;
|
||
break;
|
||
case 3:
|
||
xx = (float)x - 28.5f;
|
||
break;
|
||
case 4:
|
||
xx = (float)x - 38f;
|
||
break;
|
||
case 5:
|
||
xx = (float)x - 38f;
|
||
break;
|
||
case 6:
|
||
xx = (float)x - 38f;
|
||
break;
|
||
}
|
||
break;
|
||
case "TBA125Slim":
|
||
switch (ocrTextRequest[1].Count)
|
||
{
|
||
case 1:
|
||
xx = (float)x - 9.5f;
|
||
break;
|
||
case 2:
|
||
xx = (float)x - 19f;
|
||
break;
|
||
case 3:
|
||
xx = (float)x - 28.5f;
|
||
break;
|
||
case 4:
|
||
xx = (float)x - 28.5f;
|
||
break;
|
||
case 5:
|
||
xx = (float)x - 28.5f;
|
||
break;
|
||
case 6:
|
||
xx = (float)x - 28.5f;
|
||
break;
|
||
}
|
||
break;
|
||
case "TPA250SQ":
|
||
switch (ocrTextRequest[1].Count)
|
||
{
|
||
case 1:
|
||
xx = (float)x - 9.5f;
|
||
break;
|
||
case 2:
|
||
xx = (float)x - 19f;
|
||
break;
|
||
case 3:
|
||
xx = (float)x - 19f;
|
||
break;
|
||
case 4:
|
||
xx = (float)x - 19f;
|
||
break;
|
||
case 5:
|
||
xx = (float)x - 19f;
|
||
break;
|
||
case 6:
|
||
xx = (float)x - 19f;
|
||
break;
|
||
}
|
||
break;
|
||
case "TPA200SQ":
|
||
switch (ocrTextRequest[1].Count)
|
||
{
|
||
case 1:
|
||
xx = (float)x - 9.5f;
|
||
break;
|
||
case 2:
|
||
xx = (float)x - 9f;
|
||
break;
|
||
case 3:
|
||
xx = (float)x - 9f;
|
||
break;
|
||
case 4:
|
||
xx = (float)x - 9f;
|
||
break;
|
||
case 5:
|
||
xx = (float)x - 9f;
|
||
break;
|
||
case 6:
|
||
xx = (float)x - 9f;
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
|
||
float ocrx = 0, ocry = 0;
|
||
List<float> l = new List<float>();
|
||
l.Add((float)NumberOfLanes);
|
||
int nol = Convert.ToInt32(NumberOfLanes);
|
||
log.Info("当前订单OCR区域共" + nol + "组:");
|
||
for (int item = 0; item < nol; item++)
|
||
{
|
||
if (item == 0)
|
||
{
|
||
ocrx = xx - ((float)m_DistX) * ((float)Math.Cos((rr * Math.PI) / 180)) - ((float)m_DistY) * ((float)Math.Sin((rr * Math.PI) / 180));
|
||
l.Add(ocrx);
|
||
ocry = yy + ((float)m_DistY) * ((float)Math.Cos((rr * Math.PI) / 180)) - ((float)m_DistX) * ((float)Math.Sin((rr * Math.PI) / 180));
|
||
l.Add(ocry);
|
||
ocrxx.Add(ocrx);
|
||
ocryy.Add(ocry);
|
||
}
|
||
else
|
||
{
|
||
ocrx = ocrx + ((float)m_width * ((float)Math.Cos((rr * Math.PI) / 180))) + ((float)m_Gradient * ((float)Math.Sin((rr * Math.PI) / 180)));
|
||
l.Add(ocrx);
|
||
ocry = ocry - ((float)m_Gradient * ((float)Math.Cos((rr * Math.PI) / 180))) + ((float)m_width * ((float)Math.Sin((rr * Math.PI) / 180)));
|
||
l.Add(ocry);
|
||
ocrxx.Add(ocrx);
|
||
ocryy.Add(ocry);
|
||
}
|
||
|
||
log.Info("第" + (item + 1) + "组坐标为:X:" + ocrxx[item] + ",Y:" + ocryy[item] + "。");
|
||
if (ocrxx[item] < 0 || ocrxx[item] > 1600)
|
||
{
|
||
EnableStartDetect();
|
||
log.Error("x范围 0,1600!");
|
||
NoticePLCCompleteDet(DataConverter.FloatToByte(0.0f, true));
|
||
return;
|
||
}
|
||
if (ocryy[item] < -50 || ocryy[item] > 400)
|
||
{
|
||
EnableStartDetect();
|
||
log.Error("y范围 -50,400!");
|
||
NoticePLCCompleteDet(DataConverter.FloatToByte(0.0f, true));
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (check_Autorun.Checked == false && !debugFlag)
|
||
{
|
||
List<float> d = new List<float>();
|
||
for (int i = 0; i < l.Count; i++)
|
||
{
|
||
if (i == 0)
|
||
{
|
||
d.Add(l[i]);
|
||
}
|
||
else if (i % 2 == 1)
|
||
{
|
||
d.Add(l[l.Count - i - 1]);
|
||
d.Add(l[l.Count - i]);
|
||
}
|
||
}
|
||
NoticePLCCompleteDet(DataConverter.FloatToByte(d, true));
|
||
log.Info("坐标已发送完成。");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
EnableStartDetect();
|
||
log.Error(ex.Message + "未检测到K标志");
|
||
NoticePLCCompleteDet(DataConverter.FloatToByte(0.0f, true));
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 通讯关闭
|
||
private void CloseCC24()
|
||
{
|
||
try
|
||
{
|
||
cc24.VisionReceivedNewUserData -= CC24_NewUserDataReceived;
|
||
cc24.PlcConnectionStatusChanged -= CC24_PlcConnectionStatusChanged;
|
||
cc24.PlcTriggerCamAcqStart -= CC24_PlcTriggerCamAcqStart;
|
||
cc24.PlcTriggerCamAcqStop -= CC24_PlcTriggerCamAcqStop;
|
||
cc24.NotifyCamAcqEnabled -= CC24_NotifyCamAcqEnabled;
|
||
cc24.NotifyCamAcqDisabled -= CC24_NotifyCamAcqDisabled;
|
||
cc24.Shutdown();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
log.Error($"CommCard Closing Error: {ex.Message}");
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#endregion
|
||
}
|
||
}
|