using HalconDotNet;
|
using LB_VisionControls;
|
using System;
|
using System.Collections.Generic;
|
using System.Drawing;
|
using System.Drawing.Imaging;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
|
namespace LB_VisionProcesses.Alogrithms.Halcon
|
{
|
public class HFindCode2dTool : TAlgorithm
|
{
|
public enum Code2dType { None, QRCode, BarCode };
|
|
HTuple hv_QRCodeHandle = new HTuple();//二维码模板
|
HTuple hv_BarCodeHandle = new HTuple();//条码模板
|
public HFindCode2dTool()
|
{
|
strProcessClass = "LB_VisionProcesses.Alogrithms.Halcon.HFindCode2dTool";
|
strProcessName = "Halcon2D_读码工具";
|
|
//创建一个条码模型
|
hv_BarCodeHandle = CreateCodeMode();
|
hv_QRCodeHandle = CreateQRCodeMode();
|
|
Params.Inputs.Add("Code2dType", "BarCode");
|
Params.Inputs.Add("CodeHead", "");
|
Params.Inputs.Add("CodeLength", 0);
|
Params.Inputs.Add("MinThreshold", 80);
|
Params.Inputs.Add("MaxThreshold", 180);
|
|
Params.Inputs.Add("MinCount", 0);
|
Params.Inputs.Add("MaxCount", 9999);
|
|
Params.Outputs.Add("Count", 0);
|
Params.Outputs.Add("CodeStrings", new List<string>());
|
}
|
|
private static readonly object lockObj = new object();
|
|
public override bool Run()
|
{
|
DateTime StartTime = DateTime.Now;
|
|
InitRunParams();
|
HOperatorSet.GenEmptyObj(out HObject EmptyObj);
|
OutputImage = EmptyObj;
|
|
// 创建并启动任务
|
TAlgorithmMain();
|
RunTime = (DateTime.Now - StartTime).TotalMilliseconds;
|
return Result;
|
}
|
/// <summary>
|
/// 算子逻辑
|
/// </summary>
|
public override void TAlgorithmMain()
|
{
|
lock (lockObj)
|
{
|
#region 初始化变量
|
HOperatorSet.GenEmptyObj(out HObject ho_SymbolXLDs);
|
HOperatorSet.GenEmptyObj(out HObject ho_SymbolRegions);
|
HTuple hv_DecodedDataStrings = new HTuple();
|
HTuple hv_DecodedDataTypes = new HTuple();
|
|
//创建一个条码模型
|
hv_BarCodeHandle = CreateCodeMode();
|
hv_QRCodeHandle = CreateQRCodeMode();
|
#endregion
|
|
try
|
{
|
if (InputImage == null || !(InputImage is HObject))
|
{
|
Msg = "输入图片为空";
|
Result = false;
|
return;
|
}
|
//if (InputImage is Bitmap)
|
//{
|
// try
|
// {
|
// using (HImage hImage = new HImage())
|
// {
|
// Rectangle rect = new Rectangle(0, 0, ((Bitmap)InputImage).Width, ((Bitmap)InputImage).Height);
|
// BitmapData srcBmpData = ((Bitmap)InputImage).LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
|
// hImage.GenImageInterleaved(srcBmpData.Scan0, "rgbx", ((Bitmap)InputImage).Width, ((Bitmap)InputImage).Height, 0, "byte", ((Bitmap)InputImage).Width, ((Bitmap)InputImage).Height, 0, 0, -1, 0);
|
// ((Bitmap)InputImage).UnlockBits(srcBmpData);
|
// //((Bitmap)InputImage).Dispose();
|
// InputImage = null;
|
// InputImage = hImage.Clone();
|
// }
|
// }
|
// catch (Exception ex)
|
// {
|
// }
|
//}
|
if (!(InputImage is HObject))
|
{
|
Msg = "输入图片格式不为HObject";
|
Result = false;
|
return;
|
}
|
|
object DomainImage = null;
|
|
#region 裁剪区域
|
if (!ReduceDomainImage(InputImage, ref DomainImage))
|
{
|
Msg = "裁剪区域失败";
|
Result = false;
|
return;
|
}
|
this.Record = new MsgRecord();
|
#endregion
|
|
#region 算子逻辑
|
HObject hoDomainImage = DomainImage as HObject;
|
HTuple hv_Channels = new HTuple();
|
//判断是否为灰度图
|
using (HDevDisposeHelper dh = new HDevDisposeHelper())
|
{
|
try
|
{
|
HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
|
if (hv_Channels.TupleInt() != 1)
|
HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
|
|
//转换后再次检查是否为灰度图
|
HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
|
if (hv_Channels.TupleInt() != 1)
|
{
|
HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
|
Msg = "输入图片不为灰度图";
|
Result = false;
|
return;
|
}
|
}
|
catch
|
{
|
Msg = "输入图片不为灰度图且转换失败";
|
Result = false;
|
return;
|
}
|
}
|
|
Code2dType eCode2dType = Code2dType.None;
|
string CodeHead = (ProcessParams.ConvertToString(Params.Inputs["CodeHead"])).TrimEnd();
|
int CodeLength = ProcessParams.ConvertToInt32(Params.Inputs["CodeLength"]);
|
int MinThreshold = ProcessParams.ConvertToInt32(Params.Inputs["MinThreshold"]);
|
int MaxThreshold = ProcessParams.ConvertToInt32(Params.Inputs["MaxThreshold"]);
|
|
// 尝试转换字符串为枚举类型
|
if (!Enum.TryParse(ProcessParams.ConvertToString(Params.Inputs["Code2dType"]), out eCode2dType))
|
eCode2dType = Code2dType.None;
|
|
if (string.IsNullOrEmpty(CodeHead) || CodeHead.Trim() == "")
|
{
|
switch (eCode2dType)
|
{
|
case Code2dType.None:
|
break;
|
case Code2dType.QRCode:
|
HOperatorSet.FindDataCode2d(hoDomainImage, out ho_SymbolXLDs, hv_QRCodeHandle, new HTuple(), new HTuple(), out hv_BarCodeHandle, out hv_DecodedDataStrings);
|
break;
|
case Code2dType.BarCode:
|
HOperatorSet.FindBarCode(hoDomainImage, out ho_SymbolRegions, hv_BarCodeHandle, "auto", out hv_DecodedDataStrings);
|
HOperatorSet.GetBarCodeResult(hv_BarCodeHandle, "all", "decoded_types", out hv_DecodedDataTypes);
|
break;
|
}
|
}
|
else
|
{
|
//使用图像增强算法找到想要的条码
|
for (int i = 0; i <= ProcessParams.ConvertToInt32(Params.Inputs["MinThreshold"]); i = i + 20)
|
{
|
for (int j = 255; j >= ProcessParams.ConvertToInt32(Params.Inputs["MaxThreshold"]); j = j - 40)
|
{
|
//色阶映射,增强图像对比度
|
scale_gray_map(hoDomainImage, out HObject ho_Image2, i, j);
|
switch (eCode2dType)
|
{
|
case Code2dType.None:
|
break;
|
case Code2dType.QRCode:
|
HOperatorSet.FindDataCode2d(ho_Image2, out ho_SymbolXLDs, hv_QRCodeHandle, new HTuple(), new HTuple(), out hv_BarCodeHandle, out hv_DecodedDataStrings);
|
hv_DecodedDataTypes = null;
|
break;
|
case Code2dType.BarCode:
|
HOperatorSet.FindBarCode(ho_Image2, out ho_SymbolRegions, hv_BarCodeHandle, "auto", out hv_DecodedDataStrings);
|
HOperatorSet.GetBarCodeResult(hv_BarCodeHandle, "all", "decoded_types", out hv_DecodedDataTypes);
|
break;
|
}
|
|
if ((int)(new HTuple(((hv_DecodedDataStrings.TupleStrlen())).TupleGreater(0))) != 0)
|
{
|
HTuple row = new HTuple();
|
HTuple col = new HTuple();
|
HTuple phi = new HTuple();
|
HTuple length1 = new HTuple();
|
HTuple length2 = new HTuple();
|
|
List<string> listCodeStrings = new List<string>();
|
|
for (int k = 0; k < hv_DecodedDataStrings.Length; k++)
|
{
|
string strBarCode = (string)hv_DecodedDataStrings[k];
|
if (strBarCode.StartsWith(CodeHead))
|
{
|
//CodeLength大于0时开启长度校验
|
if (CodeLength > 0 && strBarCode.Length != CodeLength)
|
continue;
|
|
switch (eCode2dType)
|
{
|
case Code2dType.None:
|
break;
|
case Code2dType.QRCode:
|
HOperatorSet.SelectObj(ho_SymbolXLDs, out HObject ho_SymbolXLD, k + 1);
|
HOperatorSet.SmallestRectangle2Xld(ho_SymbolXLD, out row, out col, out phi, out length1, out length2);
|
HOperatorSet.GenRectangle2(out HObject ho_SymbolXLDRegion, row, col, phi, length1, length2);
|
((MsgRecord)Record).AddRecord(strBarCode, row, col, ho_SymbolXLDRegion);
|
break;
|
case Code2dType.BarCode:
|
HOperatorSet.SelectObj(ho_SymbolRegions, out HObject ho_SymbolRegion, k + 1);
|
HOperatorSet.SmallestRectangle2(ho_SymbolRegion, out row, out col, out phi, out length1, out length2);
|
((MsgRecord)Record).AddRecord(strBarCode, row, col, ho_SymbolRegion);
|
break;
|
}
|
OutputImage = hoDomainImage;
|
listCodeStrings.Add(strBarCode);
|
Params.Outputs["CodeStrings"] = listCodeStrings;
|
Params.Outputs["Count"] = 1;
|
Msg = "运行成功";
|
Result = true;
|
return;
|
}
|
}
|
}
|
}
|
}
|
|
OutputImage = null;
|
Params.Outputs["CodeStrings"] = null;
|
Params.Outputs["Count"] = 0;
|
if (CodeLength > 0)
|
Msg = string.Format("没有找到指定头为\"{0}\"且长度为\"{1}\"的码", CodeHead, CodeLength);
|
else
|
Msg = string.Format("没有找到指定头为\"{0}\"码", CodeHead);
|
Result = false;
|
return;
|
}
|
#endregion
|
|
#region 结果处理
|
this.Record = new ObjectRecord();
|
List<string> CodeStrings = new List<string>();
|
if ((int)(new HTuple(((hv_DecodedDataStrings.TupleStrlen())).TupleGreater(0))) != 0)
|
{
|
for (int k = 0; k < hv_DecodedDataStrings.Length; k++)
|
CodeStrings.Add((string)hv_DecodedDataStrings[k]);
|
|
switch (eCode2dType)
|
{
|
case Code2dType.None:
|
break;
|
case Code2dType.QRCode:
|
HOperatorSet.SmallestRectangle2Xld(ho_SymbolXLDs, out HTuple row, out HTuple col, out HTuple phi, out HTuple length1, out HTuple length2);
|
HOperatorSet.GenRectangle2(out HObject ho_SymbolXLDRegion, row, col, phi, length1, length2);
|
((ObjectRecord)Record).AddRecord(ho_SymbolXLDRegion);
|
break;
|
case Code2dType.BarCode:
|
HOperatorSet.DilationRectangle1(ho_SymbolRegions, out HObject Regiondilation, 9, 9);
|
((ObjectRecord)Record).AddRecord(Regiondilation);
|
break;
|
}
|
}
|
|
Params.Outputs["CodeStrings"] = CodeStrings;
|
Params.Outputs["Count"] = CodeStrings.Count;
|
#endregion
|
|
#region 生成OutputImage给后续处理
|
try
|
{
|
OutputImage = hoDomainImage;
|
}
|
catch (Exception ex)
|
{
|
Msg = "生成OutputImage失败,原因是:" + ex.ToString();
|
Result = false;
|
return;
|
}
|
#endregion
|
|
if (Msg == "运行超时")
|
{
|
Result = false;
|
return;
|
}
|
|
int MinCount = ProcessParams.ConvertToInt32(Params.Inputs["MinCount"]);
|
int MaxCount = ProcessParams.ConvertToInt32(Params.Inputs["MaxCount"]);
|
|
if (CodeStrings.Count < MinCount || CodeStrings.Count > MaxCount)
|
{
|
Msg = string.Format("结果个数超出范围({0},{1})", MinCount, MaxCount);
|
Result = false;
|
return;
|
}
|
|
Msg = "运行成功";
|
Result = true;
|
return;
|
}
|
catch (Exception ex)
|
{
|
Msg = "运行失败,原因是:" + ex.ToString().TrimEnd();
|
Params.Outputs.Add("Count", 0);
|
Params.Outputs.Add("CodeStrings", new List<string>());
|
OutputImage = null;
|
Result = false;
|
return;
|
}
|
finally
|
{
|
bCompleted = true;
|
|
#region 内存释放
|
ho_SymbolXLDs.Dispose();
|
ho_SymbolRegions.Dispose();
|
#endregion
|
}
|
}
|
}
|
|
/// <summary>
|
/// 创建条码类型
|
/// </summary>
|
public HTuple CreateCodeMode()
|
{
|
//条码模型句柄
|
HTuple hv_BarCodeHandle = null;
|
|
//创建条码模型
|
HOperatorSet.CreateBarCodeModel(new HTuple(), new HTuple(), out hv_BarCodeHandle);
|
HOperatorSet.SetBarCodeParam(hv_BarCodeHandle, "orientation", 0);
|
HOperatorSet.SetBarCodeParam(hv_BarCodeHandle, "orientation_tol", 90);
|
return hv_BarCodeHandle;
|
}
|
|
public HTuple CreateQRCodeMode()
|
{
|
//条码模型句柄
|
HTuple hv_QRCodeHandle = null;
|
HOperatorSet.CreateDataCode2dModel("QR Code", new HTuple(), new HTuple(), out hv_QRCodeHandle);
|
return hv_QRCodeHandle;
|
}
|
}
|
}
|