Files
TetraParkOCR/利乐包装OCR/Form1.cs
2025-10-27 09:30:49 +08:00

2236 lines
88 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.
/************************
* 作者CVE-安翀岚
*
* Vision:1.0.23.1007 (发布使用)
* Windows10 X64(PaddleOCR不能部署在32位操作系统上)
* PaddleOCR 3.10
* Vpro: 9.5 SR2
*
***********************/
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
using OfficeOpenXml;
using Cognex.VisionPro;
using Cognex.VisionPro.Comm;
using Cognex.VisionPro.QuickBuild;
using Cognex.VisionPro.ToolBlock;
using Cognex.VisionPro.PMAlign;
using Cognex.VisionPro.ToolGroup;
using Cognex.VisionPro.ImageProcessing;
using PaddleOCRSharp;
using AVP.CRobot;
using log4net;
using LogShowLib;
using System.Text.RegularExpressions;
using TetraParkOCR;
using Bjcve.Comm.FFP;
using ThridLibray;
using CLIDelegate;
namespace TetraPackOCR
{
public partial class Form1 : Form
{
public Form1()
{
double a = CogMisc.RadToDeg(0.0273672);
double r1 = Math.Cos((a * Math.PI) / 180);
double r2 = Math.Sin((a * Math.PI) / 180);
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 Sequence, QSV, Design, Layers, Colours, ProductStandard, ord;
/// <summary>
/// 幅数 包材宽 梯度 X距离 Y距离
/// </summary>
double NumberOfLanes, width, Gradient, DistX, DistY;
/// <summary>
/// 定位Vpp文件
/// </summary>
string vppdetFile = AppDomain.CurrentDomain.BaseDirectory + "Data\\VPPFile\\liledet.vpp";
/// <summary>
/// OCRVpp文件
/// </summary>
string vppocrFile = AppDomain.CurrentDomain.BaseDirectory + "Data\\VPPFile\\lileOCR.vpp";
/// <summary>
/// 存图路径
/// </summary>
string SaveImageFileOCR = AppDomain.CurrentDomain.BaseDirectory + "SaveImage\\OCR";//ocr存图
string SaveImageFileDET = AppDomain.CurrentDomain.BaseDirectory + "SaveImage\\Det";//ocr存图
private CogJobManager myJobManager1, myJobManager2;
private CogJob myJob1, myJob2;
private string[] verocr = new string[20];
bool Coprinted_ordeFlag = false; //是否为共印订单旗帜
bool PlcContinueFlag = false; //PLC状态旗帜
int mMatchingStr = 0;//接收当前OCR拍照位置
List<float> ocrAcc = new List<float>();
/// <summary>
/// 相机对象 1和2
/// </summary>
IDevice m_dev_cam0, m_dev_cam1;
List<IDeviceInfo> DeviceList;
public string ImagePixelFormat = ""; //图像格式设置
delegate void DetResultDelegate(Object Sender, CogJobManagerActionEventArgs e);
delegate void OcrResultDelegate(Bitmap bmp);
#endregion
#region
//private void MainPage_SizeChanged(object sender, EventArgs e)
//{
// asf.controlAutoSize(this);
//}
/// <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;
//asf.controllInitializeSize(this);
log.Info("软件正在加载...");
Action action = (() =>
{
//InitializeCamer1();
//InitializeCamer2();
InitializePaddleOCR();
myJobManager1 = CogSerializer.LoadObjectFromFile(vppdetFile) as CogJobManager;
myJobManager2 = CogSerializer.LoadObjectFromFile(vppocrFile) as CogJobManager;
InitializeCC24();
log.Info("模型文件加载完成");
this.check_Autorun.BackgroundImage = Image.FromFile(Application.StartupPath + "\\logo_image\\ON.png");
this.ttls_SystemStatusShow.Visible = true;
this.ttls_CamStatusShow.Visible = true;
this.Invoke(new Action(() =>
{
this.btn_manualOcr.Enabled = true;
this.btn_manualDet.Enabled = true;
check_Autorun.Enabled = true;
btn_StarDet_manual.Enabled = true;
}));
});
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 =>
{
myJob1 = myJobManager1.Job(0);
myJob2 = myJobManager2.Job(0);
// 注册结果队列事件
myJobManager1.UserResultAvailable += new CogJobManager.CogUserResultAvailableEventHandler(DetResult);
// myJobManager2.UserResultAvailable += new CogJobManager.CogUserResultAvailableEventHandler(OCRResult);
});
}
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
{
if (myJob1.AcqFifo.FrameGrabber != null)
{
myJob1.AcqFifo.FrameGrabber.Disconnect(true);
}
if (myJob2.AcqFifo.FrameGrabber != null)
{
myJob2.AcqFifo.FrameGrabber.Disconnect(true);
}
ClossCam();
// 注销结果队列事件
myJobManager1.UserResultAvailable -= new CogJobManager.CogUserResultAvailableEventHandler(DetResult);
//myJobManager2.UserResultAvailable -= new CogJobManager.CogUserResultAvailableEventHandler(OCRResult);
myJobManager1.Shutdown();
//myJobManager2.Shutdown();
CloseCC24();
Application.DoEvents();
System.Environment.Exit(0);
}
catch
{
ClossCam();
// 注销结果队列事件
myJobManager1.UserResultAvailable -= new CogJobManager.CogUserResultAvailableEventHandler(DetResult);
//myJobManager2.UserResultAvailable -= new CogJobManager.CogUserResultAvailableEventHandler(OCRResult);
myJobManager1.Shutdown();
//myJobManager2.Shutdown();
CloseCC24();
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 InitializeCamer1()
{
DeviceList = Enumerator.EnumerateDevices(); //发现设备,搜索所有大华相机
// m_dev_cam0 = Enumerator.GetDeviceByIndex(0);//通过索引获取
m_dev_cam0 = Enumerator.GetDeviceByKey("Machine Vision:CK21686DAK00001");//通过"设备厂商名:设备序列号"获取
//m_dev_cam0 = Enumerator.GetDeviceByGigeIP("192.168.20.2");//通过IP地址获取
m_dev_cam0.CameraOpened += m_dev0_CameraOpened;
m_dev_cam0.CameraClosed += m_dev0_CameraClosed;
m_dev_cam0.ConnectionLost += m_dev0_ConnectionLost;
if(!m_dev_cam0.Open())
{
MessageBox.Show("OCR相机打开失败");
}
// 设置图像格式
// set PixelFormat
using (IEnumParameter p = m_dev_cam0.ParameterCollection[ParametrizeNameSet.ImagePixelFormat])
{
ImagePixelFormat = "BayerRG8";
//ImagePixelFormat = "Mono8";
p.SetValue(ImagePixelFormat);
}
// 设置曝光
using (IFloatParameter p = m_dev_cam0.ParameterCollection[ParametrizeNameSet.ExposureTime])
{
p.SetValue(80000);
}
// 设置增益
using (IFloatParameter p = m_dev_cam0.ParameterCollection[ParametrizeNameSet.GainRaw])
{
p.SetValue(2.5);
}
using (IEnumParameter p = m_dev_cam0.ParameterCollection[ParametrizeNameSet.AcquisitionMode])
{
p.SetValue("Continuous");
}
using (IEnumParameter p = m_dev_cam0.ParameterCollection[ParametrizeNameSet.TriggerMode])
{
p.SetValue("On");
}
//if (!m_dev_cam0.Open())
//{
// MessageBox.Show(@"OCR相机连接失败");
// return;
//}
m_dev_cam0.StreamGrabber.ImageGrabbed += StreamGrabber_ImageGrabbed_0;
m_dev_cam0.StreamGrabber.GrabStarted += StreamGrabber_GrabStarted_0;
// 打开Software Trigger
// Set Software Trigger
m_dev_cam0.TriggerSet.Open(TriggerSourceEnum.Software);
if (!m_dev_cam0.GrabUsingGrabLoopThread())
{
// 开启采集失败
log.Error("开启采集失败");
}
log.Info("OCR相机加载完毕");
}
#endregion
#region 1
void m_dev0_ConnectionLost(object sender, EventArgs e)
{
MessageBox.Show(m_dev_cam0.DeviceInfo.Key + "OCR相机断线");
}
void m_dev0_CameraClosed(object sender, EventArgs e)
{
MessageBox.Show(m_dev_cam0.DeviceInfo.Key + "OCR相机关闭");
}
void m_dev0_CameraOpened(object sender, EventArgs e)
{
// MessageBox.Show(m_dev_cam0.DeviceInfo.Key + "启动");
}
void StreamGrabber_GrabStarted_0(object sender, EventArgs e)
{
log.Info("OCR相机启动码流");
}
/// <summary>
/// 拍照完成后触发
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void StreamGrabber_ImageGrabbed_0(object sender, GrabbedEventArgs e)
{
try
{
Bitmap bmp = null;
bmp = e.GrabResult.ToBitmap(true);
OCRResult(bmp);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
#endregion
#region 2
private void InitializeCamer2()
{
DeviceList = Enumerator.EnumerateDevices(); //发现设备,搜索所有大华相机
//m_dev_cam1 = Enumerator.GetDeviceByIndex(1);//通过索引获取
m_dev_cam1 = Enumerator.GetDeviceByKey("Machine Vision:BK27185BAK00038");//通过"设备厂商名:设备序列号"获取
//m_dev_cam1 = Enumerator.GetDeviceByGigeIP("192.168.10.1");//通过IP地址获取
m_dev_cam1.CameraOpened += m_dev1_CameraOpened;
m_dev_cam1.CameraClosed += m_dev1_CameraClosed;
m_dev_cam1.ConnectionLost += m_dev1_ConnectionLost;
if (!m_dev_cam1.Open())
{
MessageBox.Show("定位相机打开失败");
}
// 设置图像格式
// set PixelFormat
using (IEnumParameter p = m_dev_cam1.ParameterCollection[ParametrizeNameSet.ImagePixelFormat])
{
ImagePixelFormat = "Mono";
p.SetValue(ImagePixelFormat);
}
// 设置曝光
using (IFloatParameter p = m_dev_cam1.ParameterCollection[ParametrizeNameSet.ExposureTime])
{
p.SetValue(80000);
}
// 设置增益
using (IFloatParameter p = m_dev_cam1.ParameterCollection[ParametrizeNameSet.GainRaw])
{
p.SetValue(1.0);
}
using (IEnumParameter p = m_dev_cam1.ParameterCollection[ParametrizeNameSet.AcquisitionMode])
{
p.SetValue("Continuous");
}
using (IEnumParameter p = m_dev_cam1.ParameterCollection[ParametrizeNameSet.TriggerMode])
{
p.SetValue("On");
}
//if (!m_dev_cam1.Open())
//{
// MessageBox.Show(@"定位相机连接失败");
// return;
//}
m_dev_cam1.StreamGrabber.ImageGrabbed += StreamGrabber_ImageGrabbed_1;
m_dev_cam1.StreamGrabber.GrabStarted += StreamGrabber_GrabStarted_1;
// 打开Software Trigger
// Set Software Trigger
m_dev_cam1.TriggerSet.Open(TriggerSourceEnum.Software);
if (!m_dev_cam1.GrabUsingGrabLoopThread())
{
// 开启采集失败
log.Error("开启采集失败");
}
log.Info("定位相机加载完毕");
}
#endregion
#region 2
void m_dev1_ConnectionLost(object sender, EventArgs e)
{
MessageBox.Show(m_dev_cam1.DeviceInfo.Key + "定位相机断线");
}
void m_dev1_CameraClosed(object sender, EventArgs e)
{
MessageBox.Show(m_dev_cam1.DeviceInfo.Key + "定位相机关闭");
}
void m_dev1_CameraOpened(object sender, EventArgs e)
{
// MessageBox.Show(m_dev_cam0.DeviceInfo.Key + "启动");
}
void StreamGrabber_GrabStarted_1(object sender, EventArgs e)
{
log.Info("定位相机启动码流");
}
/// <summary>
/// 拍照完成后触发
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void StreamGrabber_ImageGrabbed_1(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 = myJob1.VisionTool as CogToolGroup;
CogToolBlock myTB = myTG.Tools["CogToolBlock1"] as CogToolBlock;
CogImageConvertTool cogImageConvert = myTB.Tools["CogImageConvertTool1"] as CogImageConvertTool;
cogImageConvert.InputImage = cogimage;
//运行jobmanager
myJobManager1.Run();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
#endregion
#region
void ClossCam()
{
//注销相机事件
m_dev_cam0.CameraOpened -= m_dev0_CameraOpened;
m_dev_cam0.CameraClosed -= m_dev0_CameraClosed;
m_dev_cam0.ConnectionLost -= m_dev0_ConnectionLost;
m_dev_cam1.CameraOpened -= m_dev1_CameraOpened;
m_dev_cam1.CameraClosed -= m_dev1_CameraClosed;
m_dev_cam1.ConnectionLost -= m_dev1_ConnectionLost;
m_dev_cam0.ShutdownGrab();
m_dev_cam0.Dispose();
m_dev_cam0 = null;
m_dev_cam1.ShutdownGrab();
m_dev_cam1.Dispose();
m_dev_cam1 = null;
}
#endregion
#endregion
#region OCR模型参数初始化
private void InitializePaddleOCR()
{
//模型初始化
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.5f;
OcrParameter.max_side_len = 1280;
//初始化OCR
Engine = new PaddleOCREngine(config, OcrParameter);
}
#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)
{
//CloseCC24();
log.Info("PC断开PLC连接,只可进行本地操作。");
this.check_Autorun.BackgroundImage = Image.FromFile(Application.StartupPath + "\\logo_image\\OFF.png");
this.panel_Manual.Visible = true;
this.btn_StarDet_manual.Enabled = false;
this.ttls_PCLStatusShow.Visible = false;
}
else if (!check_Autorun.Checked)
{
//InitializeCC24();
log.Info("PC加载PLC已完成");
this.check_Autorun.BackgroundImage = Image.FromFile(Application.StartupPath + "\\logo_image\\ON.png");
this.panel_Manual.Visible = false;
this.btn_StarDet_manual.Enabled = true;
this.ttls_PCLStatusShow.Visible = true;
}
}
/// <summary>
/// 此按钮事件主要是获取excel表格内的数据
/// 包括定位偏移量,需要验证的字符
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_OrderNum_Click(object sender, EventArgs e)
{
try
{
ClearData();
ClearDataShow();
this.Invoke(new Action(() =>
{
this.lbl_L1_verOcrRs.Text = "未启用";
this.lbl_L1_verOcrRs.BackColor = Color.Gray;
this.lbl_L2_verOcrRs.Text = "未启用";
this.lbl_L2_verOcrRs.BackColor = Color.Gray;
this.lbl_L3_verOcrRs.Text = "未启用";
this.lbl_L3_verOcrRs.BackColor = Color.Gray;
this.lbl_L4_verOcrRs.Text = "未启用";
this.lbl_L4_verOcrRs.BackColor = Color.Gray;
this.lbl_L5_verOcrRs.Text = "未启用";
this.lbl_L5_verOcrRs.BackColor = Color.Gray;
this.lbl_L6_verOcrRs.Text = "未启用";
this.lbl_L6_verOcrRs.BackColor = Color.Gray;
this.lbl_L7_verOcrRs.Text = "未启用";
this.lbl_L7_verOcrRs.BackColor = Color.Gray;
this.lbl_L8_verOcrRs.Text = "未启用";
this.lbl_L8_verOcrRs.BackColor = Color.Gray;
this.lbl_L9_verOcrRs.Text = "未启用";
this.lbl_L9_verOcrRs.BackColor = Color.Gray;
}));
this.btn_OrderNum.Enabled = false;
//通过订单号获取表格中需要的值
string order = txt_OrderNum.Text;
string laststr = order.Substring(order.Length - 1);
if (laststr == "C")
{
Coprinted_ordeFlag = true;
if (order == null)
{
log.Warn("订单号为空,请输入订单号。");
//MessageBox.Show("请输入订单号");
}
else
{
log.Info("当前订单号为:" + order);
//读取表格内容
ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
using (ExcelPackage package = new ExcelPackage(execlFileName))
{
sheet1 = package.Workbook.Worksheets["P2生成数据"];
sheet2 = package.Workbook.Worksheets["QSV对应产品规格和梯度"];
sheet3 = package.Workbook.Worksheets["产品规格对应排布方式"];
//根据订单遍历sheet1 找Sequence QSV NumOFLanes 字符
for (int i = 1; i < sheet1.Dimension.Rows; i++)
{
if (sheet1.GetValue(i, 3) != null)
{
ord = sheet1.Cells[i, 3].Value.ToString();
}
else
{
ord = null;
}
if (ord == order)
{
Sequence = sheet1.Cells[i, 2].Value.ToString();
QSV = sheet1.Cells[i, 4].Value.ToString();
this.lbl_QSVShow.Text = QSV;
log.Info("当前订单QSV:" + QSV);
NumberOfLanes = Convert.ToInt32(sheet1.Cells[i, 5].Value.ToString());
log.Info("当前订单Number Of Lanes:" + NumberOfLanes);
this.lbl_NOFShow.Text = sheet1.Cells[i, 5].Value.ToString();
////获取字符 并显示在界面还需处理先预留在这 共印订单不在这取字符
//Design = sheet1.Cells[i, 7].Value.ToString();
//Layers = sheet1.Cells[i, 8].Value.ToString();
//Colours = sheet1.Cells[i, 9].Value.ToString();
//lbl_verOcrShow.Text = ExecelGetOcrDealWithForShow(Design, Layers, Colours);
break;
}
}
if (Sequence != null)
{
for (int i = 1; i < sheet1.Dimension.Rows; i++)
{
string seq;
if (sheet1.GetValue(i, 2) != null)
{
seq = sheet1.Cells[i, 2].Value.ToString();
}
else
{
seq = null;
}
if (seq == Sequence)
{
Design = sheet1.Cells[i, 7].Value.ToString();
Layers = sheet1.Cells[i, 8].Value.ToString();
Colours = sheet1.Cells[i, 9].Value.ToString();
string Lane = sheet1.Cells[i, 6].Value.ToString();
Lane = Lane.Replace("[", ""); Lane = Lane.Replace("]", "");
string[] lans = Lane.Split(',');
for (int j = 0; j < lans.Length; j++)
{
verocr[Convert.ToInt32(lans[j])] = ExecelGetOcrDealWithForShow(Design, Layers);
}
}
}
}
if (QSV != null)
{
string qsv;
//根据得到的QSV遍历sheet2 找产品规格和宽度梯度
for (int j = 1; j <= sheet2.Dimension.Rows; j++)
{
qsv = sheet2.Cells[j, 1].Value.ToString();
if (qsv == QSV)
{
ProductStandard = sheet2.Cells[j, 2].Value.ToString();
this.lbl_ProductStandardShow.Text = ProductStandard;
log.Info("当前订单产品编号:" + ProductStandard);
width = Convert.ToDouble(sheet2.Cells[j, 3].Value.ToString());
this.lbl_widthShow.Text = sheet2.Cells[j, 3].Value.ToString();
log.Info("当前订单幅宽:" + width);
Gradient = Convert.ToDouble(sheet2.Cells[j, 4].Value.ToString());
this.lbl_GradientShow.Text = sheet2.Cells[j, 4].Value.ToString();
log.Info("当前订单梯度:" + Gradient);
}
}
string str, ps;
//根据产品规格获取距离坐标
for (int n = 1; n < sheet3.Dimension.Rows; n++)
{
if (sheet3.GetValue(n, 1) != null)
{
ps = sheet3.Cells[n, 1].Value.ToString();
}
else
{
ps = null;
}
if (ps == null)
{
continue;
}
else if (ps == ProductStandard)//应该有另一个条件一同决定
{
str = sheet3.Cells[n, 4].Value.ToString();
string[] x_y = str.Split(',');
string[] X = x_y[0].Split(':');
string[] Y = x_y[1].Split(':');
DistX = Convert.ToDouble(X[1].Replace("mm", ""));
this.lbl_DistXShow.Text = X[1].Replace("mm", "");
log.Info("当前订单X偏移:" + DistX);
DistY = Convert.ToDouble(Y[1].Replace("mm", ""));
this.lbl_DistYShow.Text = Y[1].Replace("mm", "");
log.Info("当前订单Y偏移:" + DistY);
}
}
log.Info("相关数据已获取完成,且已显示在界面中,请查看。");
}
else
{
log.Debug("请检查订单号是否正确");
}
}
}
}
else
{
Coprinted_ordeFlag = false;
if (order == null)
{
log.Warn("订单号为空,请输入订单号。");
//MessageBox.Show("请输入订单号");
}
else
{
log.Info("当前订单号为:" + order);
//读取表格内容
ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
using (ExcelPackage package = new ExcelPackage(execlFileName))
{
sheet1 = package.Workbook.Worksheets["P2生成数据"];
sheet2 = package.Workbook.Worksheets["QSV对应产品规格和梯度"];
sheet3 = package.Workbook.Worksheets["产品规格对应排布方式"];
//根据订单遍历sheet1 找QSV NumOFLanes 字符
for (int i = 1; i < sheet1.Dimension.Rows; i++)
{
if (sheet1.GetValue(i, 3) != null)
{
ord = sheet1.Cells[i, 3].Value.ToString();
}
else
{
ord = null;
}
if (ord == order)
{
QSV = sheet1.Cells[i, 4].Value.ToString();
this.lbl_QSVShow.Text = QSV;
log.Info("当前订单QSV:" + QSV);
NumberOfLanes = Convert.ToInt32(sheet1.Cells[i, 5].Value.ToString());
log.Info("当前订单Number Of Lanes:" + NumberOfLanes);
this.lbl_NOFShow.Text = sheet1.Cells[i, 5].Value.ToString();
//获取字符 并显示在界面还需处理先预留在这
Design = sheet1.Cells[i, 7].Value.ToString();
Layers = sheet1.Cells[i, 8].Value.ToString();
Colours = sheet1.Cells[i, 9].Value.ToString();
lbl_verOcrShow.Text = ExecelGetOcrDealWithForShow(Design, Layers);
}
}
if (QSV != null)
{
string qsv;
//根据得到的QSV遍历sheet2 找产品规格和宽度梯度
for (int j = 1; j <= sheet2.Dimension.Rows; j++)
{
qsv = sheet2.Cells[j, 1].Value.ToString();
if (qsv == QSV)
{
ProductStandard = sheet2.Cells[j, 2].Value.ToString();
this.lbl_ProductStandardShow.Text = ProductStandard;
log.Info("当前订单产品编号:" + ProductStandard);
width = Convert.ToDouble(sheet2.Cells[j, 3].Value.ToString());
this.lbl_widthShow.Text = sheet2.Cells[j, 3].Value.ToString();
log.Info("当前订单幅宽:" + width);
Gradient = Convert.ToDouble(sheet2.Cells[j, 4].Value.ToString());
this.lbl_GradientShow.Text = sheet2.Cells[j, 4].Value.ToString();
log.Info("当前订单梯度:" + Gradient);
}
}
string str, ps;
//根据产品规格获取距离坐标
for (int n = 1; n < sheet3.Dimension.Rows; n++)
{
if (sheet3.GetValue(n, 1) != null)
{
ps = sheet3.Cells[n, 1].Value.ToString();
}
else
{
ps = null;
}
if (ps == null)
{
continue;
}
else if (ps == ProductStandard)//应该有另一个条件一同决定
{
str = sheet3.Cells[n, 4].Value.ToString();
string[] x_y = str.Split(',');
string[] X = x_y[0].Split(':');
string[] Y = x_y[1].Split(':');
DistX = Convert.ToDouble(X[1].Replace("mm", ""));
this.lbl_DistXShow.Text = X[1].Replace("mm", "");
log.Info("当前订单X偏移:" + DistX);
DistY = Convert.ToDouble(Y[1].Replace("mm", ""));
this.lbl_DistYShow.Text = Y[1].Replace("mm", "");
log.Info("当前订单Y偏移:" + DistY);
}
}
log.Info("相关数据已获取完成,且已显示在界面中,请查看。");
}
else
{
log.Debug("请检查订单号是否正确");
}
}
}
}
///判断当前Lans决定结果显示数量
switch (NumberOfLanes)
{
case 1:
this.Invoke(new Action(() =>
{
this.lbl_L1_verOcrRs.Text = "启用";
this.lbl_L1_verOcrRs.BackColor = Color.Yellow;
}));
break;
case 2:
this.Invoke(new Action(() =>
{
this.lbl_L1_verOcrRs.Text = "启用";
this.lbl_L1_verOcrRs.BackColor = Color.Yellow;
this.lbl_L2_verOcrRs.Text = "启用";
this.lbl_L2_verOcrRs.BackColor = Color.Yellow;
}));
break;
case 3:
this.Invoke(new Action(() =>
{
this.lbl_L1_verOcrRs.Text = "启用";
this.lbl_L1_verOcrRs.BackColor = Color.Yellow;
this.lbl_L2_verOcrRs.Text = "启用";
this.lbl_L2_verOcrRs.BackColor = Color.Yellow;
this.lbl_L3_verOcrRs.Text = "启用";
this.lbl_L3_verOcrRs.BackColor = Color.Yellow;
}));
break;
case 4:
this.Invoke(new Action(() =>
{
this.lbl_L1_verOcrRs.Text = "启用";
this.lbl_L1_verOcrRs.BackColor = Color.Yellow;
this.lbl_L2_verOcrRs.Text = "启用";
this.lbl_L2_verOcrRs.BackColor = Color.Yellow;
this.lbl_L3_verOcrRs.Text = "启用";
this.lbl_L3_verOcrRs.BackColor = Color.Yellow;
this.lbl_L4_verOcrRs.Text = "启用";
this.lbl_L4_verOcrRs.BackColor = Color.Yellow;
}));
break;
case 5:
this.Invoke(new Action(() =>
{
this.lbl_L1_verOcrRs.Text = "启用";
this.lbl_L1_verOcrRs.BackColor = Color.Yellow;
this.lbl_L2_verOcrRs.Text = "启用";
this.lbl_L2_verOcrRs.BackColor = Color.Yellow;
this.lbl_L3_verOcrRs.Text = "启用";
this.lbl_L3_verOcrRs.BackColor = Color.Yellow;
this.lbl_L4_verOcrRs.Text = "启用";
this.lbl_L4_verOcrRs.BackColor = Color.Yellow;
this.lbl_L5_verOcrRs.Text = "启用";
this.lbl_L5_verOcrRs.BackColor = Color.Yellow;
}));
break;
case 6:
this.Invoke(new Action(() =>
{
this.lbl_L1_verOcrRs.Text = "启用";
this.lbl_L1_verOcrRs.BackColor = Color.Yellow;
this.lbl_L2_verOcrRs.Text = "启用";
this.lbl_L2_verOcrRs.BackColor = Color.Yellow;
this.lbl_L3_verOcrRs.Text = "启用";
this.lbl_L3_verOcrRs.BackColor = Color.Yellow;
this.lbl_L4_verOcrRs.Text = "启用";
this.lbl_L4_verOcrRs.BackColor = Color.Yellow;
this.lbl_L5_verOcrRs.Text = "启用";
this.lbl_L5_verOcrRs.BackColor = Color.Yellow;
this.lbl_L6_verOcrRs.Text = "启用";
this.lbl_L6_verOcrRs.BackColor = Color.Yellow;
}));
break;
case 7:
this.Invoke(new Action(() =>
{
this.lbl_L1_verOcrRs.Text = "启用";
this.lbl_L1_verOcrRs.BackColor = Color.Yellow;
this.lbl_L2_verOcrRs.Text = "启用";
this.lbl_L2_verOcrRs.BackColor = Color.Yellow;
this.lbl_L3_verOcrRs.Text = "启用";
this.lbl_L3_verOcrRs.BackColor = Color.Yellow;
this.lbl_L4_verOcrRs.Text = "启用";
this.lbl_L4_verOcrRs.BackColor = Color.Yellow;
this.lbl_L5_verOcrRs.Text = "启用";
this.lbl_L5_verOcrRs.BackColor = Color.Yellow;
this.lbl_L6_verOcrRs.Text = "启用";
this.lbl_L6_verOcrRs.BackColor = Color.Yellow;
this.lbl_L7_verOcrRs.Text = "启用";
this.lbl_L7_verOcrRs.BackColor = Color.Yellow;
}));
break;
case 8:
this.Invoke(new Action(() =>
{
this.lbl_L1_verOcrRs.Text = "启用";
this.lbl_L1_verOcrRs.BackColor = Color.Yellow;
this.lbl_L2_verOcrRs.Text = "启用";
this.lbl_L2_verOcrRs.BackColor = Color.Yellow;
this.lbl_L3_verOcrRs.Text = "启用";
this.lbl_L3_verOcrRs.BackColor = Color.Yellow;
this.lbl_L4_verOcrRs.Text = "启用";
this.lbl_L4_verOcrRs.BackColor = Color.Yellow;
this.lbl_L5_verOcrRs.Text = "启用";
this.lbl_L5_verOcrRs.BackColor = Color.Yellow;
this.lbl_L6_verOcrRs.Text = "启用";
this.lbl_L6_verOcrRs.BackColor = Color.Yellow;
this.lbl_L7_verOcrRs.Text = "启用";
this.lbl_L7_verOcrRs.BackColor = Color.Yellow;
this.lbl_L8_verOcrRs.Text = "启用";
this.lbl_L8_verOcrRs.BackColor = Color.Yellow;
}));
break;
case 9:
this.Invoke(new Action(() =>
{
this.lbl_L1_verOcrRs.Text = "启用";
this.lbl_L1_verOcrRs.BackColor = Color.Yellow;
this.lbl_L2_verOcrRs.Text = "启用";
this.lbl_L2_verOcrRs.BackColor = Color.Yellow;
this.lbl_L3_verOcrRs.Text = "启用";
this.lbl_L3_verOcrRs.BackColor = Color.Yellow;
this.lbl_L4_verOcrRs.Text = "启用";
this.lbl_L4_verOcrRs.BackColor = Color.Yellow;
this.lbl_L5_verOcrRs.Text = "启用";
this.lbl_L5_verOcrRs.BackColor = Color.Yellow;
this.lbl_L6_verOcrRs.Text = "启用";
this.lbl_L6_verOcrRs.BackColor = Color.Yellow;
this.lbl_L7_verOcrRs.Text = "启用";
this.lbl_L7_verOcrRs.BackColor = Color.Yellow;
this.lbl_L8_verOcrRs.Text = "启用";
this.lbl_L8_verOcrRs.BackColor = Color.Yellow;
this.lbl_L9_verOcrRs.Text = "启用";
this.lbl_L9_verOcrRs.BackColor = Color.Yellow;
}));
break;
}
this.btn_OrderNum.Enabled = true;
}
catch (Exception ex)
{
log.Error(ex.Message + "请检查订单号是否正确,数据表中并无此订单号");
this.btn_OrderNum.Enabled = true;
}
}
/// <summary>
/// 手动ocr
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_manualOcr_Click(object sender, EventArgs e)
{
m_dev_cam0.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_cam1.ExecuteSoftwareTrigger();
log.Info("手动触发定位");
}
private void btn_StarDet_manual_Click(object sender, EventArgs e)
{
m_dev_cam1.ExecuteSoftwareTrigger();
log.Info("手动触发开始");
}
/// <summary>
/// 字符排序
/// </summary>
/// <param name="d">设计</param>
/// <param name="l"></param>
/// <param name="c"></param>
/// <returns></returns>
private string ExecelGetOcrDealWithForShow(string d, string l)
{
string rescult = "";
string[] dd = d.Split('-');
//for (int i = 0; i < dd.Length-1; i++)
//{
// rescult = rescult + dd[0];
//}
//rescult = dd[0].Remove(0, 1);
string[] ll = l.Split(',');
for (int i = 0; i < ll.Length; i++)
{
ll[i] = ll[i].Replace(" ", ""); ll[i] = ll[i].Replace("[", ""); ll[i] = ll[i].Replace("]", "");
string[] str = ll[i].Split('-');
rescult = rescult + dd[1]+ str[1] + str[0];
}
return rescult;
}
/// <summary>
/// 清空上次订单数据
/// </summary>
void ClearData()
{
QSV = null; Design = null; Layers = null; Colours = null; ProductStandard = null; ord = null;
NumberOfLanes = 0; width = 0; Gradient = 0; DistX = 0; DistY = 0;
}
/// <summary>
/// 清空上次订单显示区
/// </summary>
void ClearDataShow()
{
lbl_QSVShow.Text = "";
lbl_NOFShow.Text = "";
lbl_ProductStandardShow.Text = "";
lbl_widthShow.Text = "";
lbl_GradientShow.Text = "";
lbl_DistXShow.Text = "";
lbl_DistYShow.Text = "";
lbl_verOcrShow.Text = "";
}
private void txt_OrderNum_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
this.btn_OrderNum_Click(sender, e);
}
}
#endregion
#region PLC触发相机
#region
/// <summary>
/// 定位相机拍照信号过来程序需要进行的操作
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DetCamTriger()
{
log.Info("PLC触发定位相机正在拍照计算...");
try
{
m_dev_cam1.ExecuteSoftwareTrigger();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
#endregion
#region OCR相机拍照触发处理函数
/// <summary>
/// OCR相机拍照信号过来需要进行的操作
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OcrCamTriger()
{
log.Info("PLC触发OCR相机正在拍照计算...");
try
{
m_dev_cam0.ExecuteSoftwareTrigger();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
#endregion
#endregion
#region
#region
public void DetResult(object sender, CogJobManagerActionEventArgs e)
{
try
{
if (InvokeRequired)
{
Invoke(new DetResultDelegate(DetResult), new object[] { sender, e });
return;
}
//清除上次的结果显示
this.lbl_XShow.Text = "";
this.lbl_YShow.Text = "";
this.lbl_RShow.Text = "";
CogToolGroup myTG = myJob1.VisionTool as CogToolGroup;
CogToolBlock myTB = myTG.Tools["CogToolBlock1"] as CogToolBlock;
CogPMAlignTool myPMA = myTB.Tools["CogPMAlignTool2"] as CogPMAlignTool;
CogImageConvertTool myImage = myTB.Tools["CogImageConvertTool1"] as CogImageConvertTool;
////把vpro图像转为bitmap
//ICogImage cogimg = myImage.OutputImage;
//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("定位存图已完成");
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);
this.lbl_XShow.Text = xx.ToString();
this.lbl_YShow.Text = yy.ToString();
this.lbl_RShow.Text = rr.ToString();
//画模型轮廓
CogCompositeShape shape = myPMA.Results[i].CreateResultGraphics(CogPMAlignResultGraphicConstants.MatchFeatures);
CogCompositeShape shape1 = myPMA.Results[i].CreateResultGraphics(CogPMAlignResultGraphicConstants.CoordinateAxes);
this.Location_Display.InteractiveGraphics.Add(shape, "", false);
this.Location_Display.InteractiveGraphics.Add(shape1, "", false);
//画定位的十字点
CPMARunStatus.DrawPointMarker(xx, yy, CogMisc.DegToRad(rr), CogColorConstants.Orange, Location_Display, ".");
log.Info("定位计算已完成。");
sendToPLC(xx, yy, rr);
}
else
{
log.Info("没有定位到K标志,请查看图像或相机是否正常");
}
}
catch (Exception ex)
{
log.Error(ex.Message + "未检测到K标志");
if (this.check_Autorun.Checked == false)
{
byte[] datax = DataConverter.FloatToByte(0.0f, true);
cc24?.NotifyCamInspectionComplete(0, datax);
cc24?.NotifyCamAcqComplete(0);
}
}
}
/// <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;
}
//ai suggest① 先按 y 排序 → ② 一次扫描把相邻且 Δy<50 的点归并成同一行 → ③ 每行内部按 x 排序 → ④ 按行收集。
//List<Point> paixu(List<Point> points)
//{
// const int rowDistance = 50;
// if (points.Count == 0) return new List<Point>();
// // 1. 先按纵坐标排序
// var src = points.OrderBy(p => p.y).ThenBy(p => p.x).ToList();
// var rows = new List<List<Point>>();
// List<Point> curRow = new List<Point> { src[0] };
// float baseY = src[0].y;
// // 2. 一次扫描分好行
// for (int i = 1; i < src.Count; i++)
// {
// if (Math.Abs(src[i].y - baseY) < rowDistance)
// {
// curRow.Add(src[i]);
// }
// else
// {
// rows.Add(curRow);
// curRow = new List<Point> { src[i] };
// baseY = src[i].y;
// }
// }
// rows.Add(curRow); // 别忘了最后一行
// // 3. 行内再按 x 排一次(虽然 OrderBy 已做过,保险)
// foreach (var row in rows)
// row.Sort((a, b) => a.x.CompareTo(b.x));
// // 4. 按行先后汇总
// var sorted = new List<Point>();
// foreach (var row in rows)
// sorted.AddRange(row);
// return sorted;
//}
#endregion
#region OCR结果处理
private void OCRResult(Bitmap bmp)
{
try
{
if (InvokeRequired)
{
Invoke(new OcrResultDelegate(OCRResult), new object[] { bmp });
return;
}
//CogToolGroup myTG = myJob2.VisionTool as CogToolGroup;
//CogAcqFifoTool myImage = myTG.Tools["CogAcqFifoTool1"] as CogAcqFifoTool;
//把vpro图像先转为bitmap
//ICogImage cogimg = myImage.OutputImage;
//Bitmap bmp = new Bitmap(cogimg.ToBitmap()); //有时会丢图cogimg为空改为SDK取图
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");
//string strtimef = DateTime.Now.ToString("yyyy-MM-dd");
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", 200, 1400, 5052, 1600);
//List<PointD> temps = new List<PointD>();
GetOCRImage getOCRImage = new GetOCRImage();
GetOCRImage.FileTimeInfo file = getOCRImage.GetLatesFileImageName(SaveImageFileOCR + '\\' + strtimef, ".bmp");
if (file != null)
{
byte[] ocrimagebyte = File.ReadAllBytes(file.FileName);
Bitmap Bmp = new Bitmap(new MemoryStream(ocrimagebyte));
List<string> lastocr = new List<string>();
OCRResult ocrResult = Engine.DetectText(ocrimagebyte);
// log.Debug("读取原始数据1" + ocrResult.JsonText);
List<Point> pointsList = new List<Point>();
string[] sd = Design.Split('-');
foreach (var item in ocrResult.TextBlocks) //将检测框绘制在图片上
{
if (item.Text.Contains(sd[1]))
{
using (Graphics g = Graphics.FromImage(Bmp))
{
g.DrawPolygon(new Pen(Brushes.Red, 2), item.BoxPoints.Select(x => new PointF() { X = x.X, Y = x.Y }).ToArray());
}
//lastocr.Add(item.Text);
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);
}
//对图像显示区更新
Ocr_picBox.BackgroundImage = null;
Ocr_picBox.BackgroundImage = Bmp;
txt_readOcrResultShow.Clear();
if (!Coprinted_ordeFlag) //判断是否为共印订单
{
txt_readOcrResultShow.Text = GETOCR(lastocr, Design);
log.Info("字符读取结果:" + GETOCR(lastocr, Design));
int distance = CalculateAcc(ExecelGetOcrDealWithForShow(Design, Layers), GETOCR(lastocr, Design));
float maxLength = Math.Max(ExecelGetOcrDealWithForShow(Design, Layers).Length, GETOCR(lastocr, Design).Length);
float strSimilarity = (maxLength - distance) / maxLength;
ShowTheLansRs(mMatchingStr, strSimilarity);
}
else
{
txt_readOcrResultShow.Text = GETOCR(lastocr, Design);
log.Info("字符读取结果:" + GETOCR(lastocr, Design));
int distance = CalculateAcc(verocr[mMatchingStr], GETOCR(lastocr, Design));
float maxLength = Math.Max(verocr[mMatchingStr].Length, GETOCR(lastocr, Design).Length);
float strSimilarity = (maxLength - distance) / maxLength;
ShowTheLansRs(mMatchingStr, strSimilarity);
}
if (this.check_Autorun.Checked == false)
{
byte[] datas = DataConverter.FloatToByte(0.0f);
cc24?.NotifyCamAcqComplete(1); //通知PLC OCR相机已完成采集
cc24?.NotifyCamInspectionComplete(1, datas);
}
}
}
catch (Exception ex)
{
log.Error(ex.Message + "未检测到字符");
if (this.check_Autorun.Checked == false)
{
byte[] datax = DataConverter.FloatToByte(0.0f, true);
cc24?.NotifyCamInspectionComplete(1, datax);
cc24?.NotifyCamAcqComplete(1);
}
}
}
#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[] d = design.Split('-');
string pattern = @""+d[1]+"[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 "未能匹配到对应字符请查看产品是否超标,或订单号是否正确";
}
}
/// <summary>
/// 使用Levenshtein Distance计算字符串相似度
/// </summary>
/// <param name="readocr">excel取到的验证字符</param>
/// <param name="getocr">读取到的字符</param>
int CalculateAcc(string readocr, string getocr)
{
int columnSize = getocr.Length;
int rowSize = readocr.Length;
if (columnSize == 0)
{
return rowSize;
}
if (rowSize == 0)
{
return columnSize;
}
int[,] matrix = new int[rowSize + 1, columnSize + 1];
for (int i = 0; i <= columnSize; i++)
{
matrix[0, 1] = i;//ai提示此处应为matrix[0,i]=i;
}
for (int j = 1; j <= rowSize; j++)//ai提示此处应为j=0
{
matrix[j, 0] = j;
}
for (int i = 0; i < rowSize; i++)
{
for (int j = 0; j < columnSize; j++)
{
int sign;
if (getocr[j].Equals(readocr[i]))
sign = 0;
else
sign = 1;
matrix[i + 1, j + 1] = Math.Min(Math.Min(matrix[i, j] + sign, matrix[i + 1, j] + 1), matrix[i, j + 1] + 1);
}
}
return matrix[rowSize, columnSize];
}
/// <summary>
/// 将结果显示在对应状态栏
/// </summary>
/// <param name="mM">PLC给的当前在第几道拍照</param>
/// <param name="s">OCR字符相似度结果</param>
void ShowTheLansRs(float mM, float s)
{
int mMnum = Convert.ToInt32(mM);
//s = 1;//**************************************************************************************************注意
switch (mMnum)
{
case 1:
this.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);
this.lbl_L1_verOcrRs.Text = s * 100 + "%";
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
break;
case 2:
this.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);
this.lbl_L2_verOcrRs.Text = s * 100 + "%";
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
break;
case 3:
this.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);
this.lbl_L3_verOcrRs.Text = s * 100 + "%";
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
break;
case 4:
this.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);
this.lbl_L4_verOcrRs.Text = s * 100 + "%";
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
break;
case 5:
this.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);
this.lbl_L5_verOcrRs.Text = s * 100 + "%";
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
break;
case 6:
this.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);
this.lbl_L6_verOcrRs.Text = s * 100 + "%";
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
break;
case 7:
this.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);
this.lbl_L7_verOcrRs.Text = s * 100 + "%";
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
break;
case 8:
this.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);
this.lbl_L8_verOcrRs.Text = s * 100 + "%";
log.Info("字符对比结果:当前第" + mMnum + "道的读取字符与验证字符相似度为" + s * 100 + "%");
break;
case 9:
this.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);
this.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);
this.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)
{
this.Invoke(new Action(() =>
{
if (isEnabled)
{
this.ttls_AcqEnableShow.Visible = true;
}
else
{
this.ttls_AcqEnableShow.Visible = false;
}
}));
}
private void CC24_NotifyCamAcqDisabled(int cameraIndex, bool isEnabled)
{
this.Invoke(new Action(() =>
{
if (isEnabled)
{
this.ttls_AcqEnableShow.Visible = true;
}
else
{
this.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)
{
if(ocrAcc.Min()<0.95)
{
MessageBox.Show("当前检测中出现严重错误请注意!",this.Text, MessageBoxButtons.OK,MessageBoxIcon.Error);
}
else if(ocrAcc.Min()>0.95 & ocrAcc.Min()<1)
{
MessageBox.Show("当前检测中出现可允许误差请注意!", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
ocrAcc.Clear();
}
}
#endregion
#region
void CC24_PlcTriggerCamAcqStart(object sender, CogNdmTriggerAcquisitionEventArgs e)
{
if (InvokeRequired)
{
Invoke(new CogNdmTriggerAcquisitionEventHandler(CC24_PlcTriggerCamAcqStart), new object[] { sender, e });
return;
}
try
{
#region
if (e.CameraIndex == 0)
{
DetCamTriger();
}
#endregion
#region OCR拍照信号
if (e.CameraIndex == 1)
{
Thread.Sleep(100);
OcrCamTriger();
}
#endregion
}
catch (Exception ex)
{
log.Error($"Trigger AcqStart Error: {ex.Message}");
}
}
#endregion
#region
private void CC24_PlcTriggerCamAcqStop(object sender, CogNdmTriggerAcquisitionStopEventArgs e)
{
if (InvokeRequired)
{
Invoke(new CogNdmTriggerAcquisitionStopEventHandler(CC24_PlcTriggerCamAcqStop), new object[] { sender, e });
return;
}
if (e.CameraIndex == 0)
{
log.Info("PLC中断定位相机拍照。");
}
if (e.CameraIndex == 1)
{
log.Info("PLC中断OCR相机拍照。");
}
}
#endregion
#region
private void CC24_PlcConnectionStatusChanged(object sender, CogNdmProtocolStatusChangedEventArgs e)
{
// The event is raised from a non-GUI thread.
// Invoke this function on the GUI thread.
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
{
string[] col = Colours.Split(',');
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 (ProductStandard)
{
case "TBA1000Slim":
switch (col.Length)
{
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 (col.Length)
{
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 (col.Length)
{
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 (col.Length)
{
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;
}
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)DistX) * ((float)Math.Cos((rr * Math.PI) / 180));
l.Add(ocrx);
ocry = yy - ((float)DistY) * ((float)Math.Sin((rr * Math.PI) / 180));
l.Add(ocry);
ocrxx.Add(ocrx);
ocryy.Add(ocry);
}
else
{
ocrx = ocrx + ((float)width * ((float)Math.Cos((rr * Math.PI) / 180)));
l.Add(ocrx);
ocry = ocry - ((float)Gradient * ((float)Math.Cos((rr * Math.PI) / 180)));
l.Add(ocry);
ocrxx.Add(ocrx);
ocryy.Add(ocry);
}
log.Info("第" + (item + 1) + "组坐标为X" + ocrxx[item] + ",Y:" + ocryy[item] + "。");
}
if (this.check_Autorun.Checked == false)
{
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]);
}
}
byte[] datax = DataConverter.FloatToByte(d, true);
cc24?.NotifyCamInspectionComplete(0, datax);
cc24?.NotifyCamAcqComplete(0);
log.Info("坐标已发送完成。");
}
}
catch (Exception ex)
{
log.Error(ex.Message + "未检测到K标志");
if (check_Autorun.Checked == false)
{
byte[] datax = DataConverter.FloatToByte(0.0f, true);
cc24?.NotifyCamInspectionComplete(0, datax);
cc24?.NotifyCamAcqComplete(0);
}
}
}
#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
}
}