Files
TetraParkOCR/TetraParkOCR/Form1.cs
2025-11-05 15:08:47 +08:00

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