using HalconDotNet; 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 { [Process("Halcon2D读码工具", Category = "Halcon2D工具", Description = "创建读码工具")] 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("CodeStrings", new List()); } private static readonly object lockObj = new object(); /// /// 算子逻辑 /// 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 = hImage.Clone(); } } catch (Exception ex) { Msg = "转图出错:" + ex.Message; Result = false; return; } } if (!(InputImage is HObject)) { Msg = "输入图片格式不为Mat"; 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 listCodeStrings = new List(); 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 CodeStrings = new List(); 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: ((ObjectRecord)Record).AddXld(ho_SymbolXLDs); 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(); OutputImage = null; Result = false; return; } finally { if (!Result) { Params.Outputs["CodeStrings"] = ""; Params.Outputs["Count"] = 0; } bCompleted = true; #region 内存释放 ho_SymbolXLDs.Dispose(); ho_SymbolRegions.Dispose(); #endregion } } } /// /// 创建条码类型 /// 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; } } }