/************************
* 作者: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));
///
/// 声明一个cc24通讯对象
///
CC24 cc24;
///
/// 声明一个PaddleOCR对象
///
PaddleOCREngine Engine;
///
///对应表格"P2生成数据"这一页
///
ExcelWorksheet sheet1;
///
/// 对应表格"QSV对应产品规格和梯度"这一页
///
ExcelWorksheet sheet2;
///
/// 对应"产品规格对应排布方式"这一页
///
ExcelWorksheet sheet3;
///
/// 表格路径
///
string execlFileName = AppDomain.CurrentDomain.BaseDirectory + "Data\\Excle\\OCR文件0602.xlsx";
///
/// 共印依据 QSV Design, Layers, Colours,产品规格
///
string Sequence, QSV, Design, Layers, Colours, ProductStandard, ord;
///
/// 幅数 包材宽 梯度 X距离 Y距离
///
double NumberOfLanes, width, Gradient, DistX, DistY;
///
/// 定位Vpp文件
///
string vppdetFile = AppDomain.CurrentDomain.BaseDirectory + "Data\\VPPFile\\liledet.vpp";
///
/// OCRVpp文件
///
string vppocrFile = AppDomain.CurrentDomain.BaseDirectory + "Data\\VPPFile\\lileOCR.vpp";
///
/// 存图路径
///
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 ocrAcc = new List();
///
/// 相机对象 1和2
///
IDevice m_dev_cam0, m_dev_cam1;
List 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);
//}
///
/// 窗体加载
///
///
///
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 tsk = new List();
//将上面的加载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);
}
}
///
/// 窗体关闭
///
///
///
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相机启动码流");
}
///
/// 拍照完成后触发
///
///
///
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("定位相机启动码流");
}
///
/// 拍照完成后触发
///
///
///
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 按钮事件
///
/// 自动运行状态改变按钮
///
///
///
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;
}
}
///
/// 此按钮事件主要是获取excel表格内的数据
/// 包括定位偏移量,需要验证的字符
///
///
///
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;
}
}
///
/// 手动ocr
///
///
///
private void btn_manualOcr_Click(object sender, EventArgs e)
{
m_dev_cam0.ExecuteSoftwareTrigger();//相机1触发 = OCR拍照
log.Info("手动触发OCR");
}
///
/// 手动定位
///
///
///
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("手动触发开始");
}
///
/// 字符排序
///
/// 设计
///
///
///
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;
}
///
/// 清空上次订单数据
///
void ClearData()
{
QSV = null; Design = null; Layers = null; Colours = null; ProductStandard = null; ord = null;
NumberOfLanes = 0; width = 0; Gradient = 0; DistX = 0; DistY = 0;
}
///
/// 清空上次订单显示区
///
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 定位相机拍照触发处理函数
///
/// 定位相机拍照信号过来程序需要进行的操作
///
///
///
///
private void DetCamTriger()
{
log.Info("PLC触发定位相机,正在拍照计算...");
try
{
m_dev_cam1.ExecuteSoftwareTrigger();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
#endregion
#region OCR相机拍照触发处理函数
///
/// OCR相机拍照信号过来需要进行的操作
///
///
///
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);
}
}
}
///
/// 获取右下角定位标志坐标
///
/// PatMAX结果
///
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 paixu(List points)
{
int rowDistance = 50;
List> rows = new List>();
for (int i = 0; i < points.Count; i++)
{
List row = new List();
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 sortedPoints = new List();
foreach (List 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 paixu(List points)
//{
// const int rowDistance = 50;
// if (points.Count == 0) return new List();
// // 1. 先按纵坐标排序
// var src = points.OrderBy(p => p.y).ThenBy(p => p.x).ToList();
// var rows = new List>();
// List curRow = new List { 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 { 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();
// 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 temps = new List();
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 lastocr = new List();
OCRResult ocrResult = Engine.DetectText(ocrimagebyte);
// log.Debug("读取原始数据1:" + ocrResult.JsonText);
List pointsList = new List();
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 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
///
/// 使用正则表达式提取结果
///
/// 读到的所有字符
/// 设计
///
///
private string GETOCR(List 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 "未能匹配到对应字符请查看产品是否超标,或订单号是否正确";
}
}
///
/// 使用Levenshtein Distance计算字符串相似度
///
/// excel取到的验证字符
/// 读取到的字符
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];
}
///
/// 将结果显示在对应状态栏
///
/// PLC给的当前在第几道拍照
/// OCR字符相似度结果
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 ocrxx = new List();
List ocryy = new List();
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 l = new List();
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 d = new List();
for (int i=0;i