介绍+
winform与halcon结合标准化工具实例
软件架构
软件架构说明 基于NET6 WINFORM+HALCON
实现标准化视觉检测工具
集成相机通讯
集成PLC通讯
TCP等常见通讯
支持常见halcon算子
- 图形采集
- blob分析
- 高精度匹配
- 颜色提取
- 找几何体
- 二维码提取
- OCR识别
- 等等
。。。
安装教程
https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0
使用说明
安装 NET6 SDK,编译即可运行
对入门的同学应该有较好的学习意义
本项目涵盖了标准化视觉检测工具的大部分功能,有兴趣的小伙伴可以请我吃一顿肯德基,获取源码进行学习。
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using HalconDotNet;
using MT_OCR5._0;
using PaddleOCRSharp;
namespace Vision.Winform.Algorithm
{ //识别各种二维码,一维码, 字符识别
namespace MT_code
{
public class QR
{
public ToolPar toolPar = new ToolPar();
public bool status = true;
internal HObject image = null;
//二维码识别句柄
internal HTuple modelID = null;
public string CodeType = "QR Code";
public string ParamName = "default_parameters";
public string ParamValue = "standard_recognition";
private void creathandle()
{
try
{
switch (toolPar.RunPar.QrMode)
{
case QrMode.QR:
CodeType = "QR Code";
break;
case QrMode.DM:
CodeType = "Data Matrix ECC 200";
break;
}
switch (toolPar.RunPar.QrRecognition)
{
case QRRecognition.standard_recognition:
ParamValue = "standard_recognition";
break;
case QRRecognition.enhanced_recognition:
ParamValue = "enhanced_recognition";
break;
case QRRecognition.maximum_recognition:
ParamValue = "maximum_recognition";
break;
}
if(modelID == null)
{
HOperatorSet.CreateDataCode2dModel((HTuple)CodeType, (HTuple)ParamName, (HTuple)ParamValue, out modelID);
}
}
catch (Exception)
{
status = false;
}
//return 0;
}
private void clearhandle()
{
HOperatorSet.ClearDataCode2dModel(modelID);
}
public void run()
{
creathandle();
try
{
toolPar.ResultPar.CodeResult = new List<BarcodeResult>();
if (modelID == null)
{
status = false;
return;
}
if (toolPar.InputPar.图像 != null)
{
if (toolPar.InputPar.ROI != null)
{
HOperatorSet.ReduceDomain(toolPar.InputPar.图像, toolPar.InputPar.ROI, out image);
}
else
{
image = toolPar.InputPar.图像;
}
//设置极性
string codePolarity= "dark_on_light";
switch (toolPar.RunPar.CodePolarity)
{
case CodePolarity.any: codePolarity = "any"; break;
case CodePolarity.positive: codePolarity = "dark_on_light"; break;
case CodePolarity.negative: codePolarity = "light_on_dark"; break;
}
HOperatorSet.SetDataCode2dParam(modelID, "polarity", codePolarity);
HOperatorSet.SetDataCode2dParam(modelID, "timeout", toolPar.RunPar.TimeOut);
HObject xlds;
HTuple strtmp, resultHandles;
HOperatorSet.FindDataCode2d(image,
out xlds,
modelID,
"stop_after_result_num", toolPar.RunPar.CodeNum,
out resultHandles,
out strtmp);
//把结果塞进去
for (int i = 0; i < strtmp.Length; i++)
{
BarcodeResult tmp;
HObject region;
HOperatorSet.GenRegionContourXld(xlds, out region, "filled");
tmp.region = region;
tmp.code = strtmp[i].S;
toolPar.ResultPar.CodeResult.Add(tmp);
}
toolPar.ResultPar.CodeNum = strtmp.Length;
//HOperatorSet.clear
}
else
{
status = false;
return;
}
}
catch (Exception)
{
clearhandle();
status = false;
}
clearhandle();
}
[Serializable]
public class ToolPar : ToolParBase
{
private InputPar _inputPar = new InputPar();
public InputPar InputPar
{
get { return _inputPar; }
set { _inputPar = value; }
}
private RunPar _runPar = new RunPar();
public RunPar RunPar
{
get { return _runPar; }
set { _runPar = value; }
}
private ResultPar _resultPar = new ResultPar();
public ResultPar ResultPar
{
get { return _resultPar; }
set { _resultPar = value; }
}
}
[Serializable]
public class InputPar
{
private HObject _图像;
public HObject 图像
{
get { return _图像; }
set { _图像 = value; }
}
private HObject _ROI;
public HObject ROI
{
get { return _ROI; }
set { _ROI = value; }
}
private HObject _屏蔽区域;
public HObject 屏蔽区域
{
get { return _屏蔽区域; }
set { _屏蔽区域 = value; }
}
public int FindCodeNum { set; get; } = 1;
}
[Serializable]
public class RunPar
{
public QRRecognition QrRecognition { get; set; }
public QrMode QrMode { get; set; }
public CodePolarity CodePolarity { get; set; }
public int TimeOut { get; set; }
public int CodeNum { get; set; }
}
[Serializable]
public class ResultPar
{
private List<BarcodeResult> _CodeResult;
public List<BarcodeResult> CodeResult
{
get { return _CodeResult; }
set { _CodeResult = value; }
}
private int _CodeNum;
public int CodeNum
{
get { return _CodeNum; }
set { _CodeNum = value; }
}
}
}
public class One_dimension
{
public ToolPar toolPar = new ToolPar();
public bool status = true;
internal HObject image = null;
//条形码识别句柄
internal HTuple modelID = null;
internal HTuple codetype = "auto";
private void creathandle()
{
try
{
HOperatorSet.CreateBarCodeModel(new HTuple(), new HTuple(), out modelID);
}
catch (Exception)
{
status = false;
}
//return 0;
}
private void clearhandle()
{
HOperatorSet.ClearBarCodeModel(modelID);
}
public void run()
{
creathandle();
toolPar.ResultPar.CodeResult = new List<BarcodeResult>();
try
{
if (modelID == null)
{
status = false;
return;
}
if (toolPar.InputPar.图像 != null)
{
if (toolPar.InputPar.ROI != null)
{
HOperatorSet.ReduceDomain(toolPar.InputPar.图像, toolPar.InputPar.ROI, out image);
}
else
{
image = toolPar.InputPar.图像;
}
HObject region;
HTuple strtmp;
HOperatorSet.SetBarCodeParam(modelID, "timeout", toolPar.RunPar.TimeOut);
HOperatorSet.SetBarCodeParam(modelID, "stop_after_result_num", toolPar.RunPar.CodeNum);
设置极性
//string codePolarity = "dark_on_light";
//switch (toolPar.RunPar.CodePolarity)
//{
// case CodePolarity.any: codePolarity = "any"; break;
// case CodePolarity.positive: codePolarity = "dark_on_light"; break;
// case CodePolarity.negative: codePolarity = "light_on_dark"; break;
//}
//HOperatorSet.SetBarCodeParam(modelID, "polarity", codePolarity);
HOperatorSet.FindBarCode(image, out region, modelID, codetype, out strtmp);
//把结果塞进去
for (int i = 0; i < strtmp.Length; i++)
{
BarcodeResult tmp;
tmp.region = region;
tmp.code = strtmp[i].S;
toolPar.ResultPar.CodeResult.Add(tmp);
}
toolPar.ResultPar.CodeNum = strtmp.Length;
//HOperatorSet.clear
}
else
{
status = false;
return;
}
}
catch (Exception)
{
clearhandle();
status = false;
}
clearhandle();
}
[Serializable]
public class ToolPar : ToolParBase
{
private InputPar _inputPar = new InputPar();
public InputPar InputPar
{
get { return _inputPar; }
set { _inputPar = value; }
}
private RunPar _runPar = new RunPar();
public RunPar RunPar
{
get { return _runPar; }
set { _runPar = value; }
}
private ResultPar _resultPar = new ResultPar();
public ResultPar ResultPar
{
get { return _resultPar; }
set { _resultPar = value; }
}
}
[Serializable]
public class InputPar
{
private HObject _图像;
public HObject 图像
{
get { return _图像; }
set { _图像 = value; }
}
private HObject _ROI;
public HObject ROI
{
get { return _ROI; }
set { _ROI = value; }
}
private HObject _屏蔽区域;
public HObject 屏蔽区域
{
get { return _屏蔽区域; }
set { _屏蔽区域 = value; }
}
}
[Serializable]
public class RunPar
{
//public BarRecognition BarRecognition { get; set; }
public BarMode BarMode { get; set; }
public CodePolarity CodePolarity { get; set; }
public int TimeOut { get; set; }
public int CodeNum { get; set; }
}
[Serializable]
public class ResultPar
{
private List<BarcodeResult> _CodeResult;
public List<BarcodeResult> CodeResult
{
get { return _CodeResult; }
set { _CodeResult = value; }
}
private int _CodeNum;
public int CodeNum
{
get { return _CodeNum; }
set { _CodeNum = value; }
}
}
}
public class OCR
{
public ToolPar toolPar = new ToolPar();
public bool status = true;
internal HObject image = null;
RunPar runPar=new RunPar ();
public void run()
{
try
{
if (toolPar.InputPar.图像 != null)
{
if (toolPar.InputPar.ROI != null && toolPar.InputPar.屏蔽区域 != null)
{
HObject reduce_region = new HObject();
reduce_region.Dispose();
HOperatorSet.Difference(toolPar.InputPar.ROI, toolPar.InputPar.屏蔽区域, out reduce_region);
//image.Dispose();
HOperatorSet.ReduceDomain(toolPar.InputPar.图像, reduce_region, out image);
HOperatorSet.CropDomain(image, out image);
reduce_region.Dispose();
}
else if (toolPar.InputPar.ROI != null && toolPar.InputPar.屏蔽区域 == null)
{
HOperatorSet.GenEmptyObj(out image);
HOperatorSet.ReduceDomain(toolPar.InputPar.图像, toolPar.InputPar.ROI, out image);
HOperatorSet.CropDomain(image, out image);
}
else if (toolPar.InputPar.ROI == null && toolPar.InputPar.屏蔽区域 != null)
{
HObject reduce_region = new HObject();
reduce_region.Dispose();
HOperatorSet.Difference(toolPar.InputPar.图像, toolPar.InputPar.屏蔽区域, out reduce_region);
//image.Dispose();
HOperatorSet.ReduceDomain(toolPar.InputPar.图像, reduce_region, out image);
HOperatorSet.CropDomain(image, out image);
reduce_region.Dispose();
}
else
{
if (image != null)
image.Dispose();
image = toolPar.InputPar.图像;
}
}
else
{
status = false;
return;
}
//初始化
//ocr_engine.OCR_INIT();
//HObject img;
//HOperatorSet.GenEmptyObj(out img);
//img = image;
检测
//string ocr_result = ocr_engine.OCR_Dect(img);
//ocr_engine.engine.Dispose();
//toolPar.ResultPar.OCRResult = ocr_result;
//ocr_result = String.Empty;
HOperatorSet.CountChannels(image, out var channels);
Bitmap img;
HObject multiChannelImage;
HOperatorSet.GenEmptyObj(out multiChannelImage);
if (channels == 3)
{
img=runPar.Honject2Bitmap24(image);
}
else
{
HOperatorSet.Compose3(image, image, image, out multiChannelImage);
img = runPar.Honject2Bitmap24(multiChannelImage);
}
runPar.ocrResult= runPar.engine.DetectText(img);
toolPar.ResultPar.OCRResult = runPar.ocrResult.Text;
}
catch (Exception)
{
status = false;
}
}
[Serializable]
public class ToolPar : ToolParBase
{
private InputPar _inputPar = new InputPar();
public InputPar InputPar
{
get { return _inputPar; }
set { _inputPar = value; }
}
private RunPar _runPar = new RunPar();
public RunPar RunPar
{
get { return _runPar; }
set { _runPar = value; }
}
private ResultPar _resultPar = new ResultPar();
public ResultPar ResultPar
{
get { return _resultPar; }
set { _resultPar = value; }
}
}
[Serializable]
public class InputPar
{
private HObject _图像;
public HObject 图像
{
get { return _图像; }
set { _图像 = value; }
}
private HObject _ROI;
public HObject ROI
{
get { return _ROI; }
set { _ROI = value; }
}
private HObject _屏蔽区域;
public HObject 屏蔽区域
{
get { return _屏蔽区域; }
set { _屏蔽区域 = value; }
}
}
[Serializable]
public class RunPar
{
public OCRModelConfig config = null;
public OCRParameter oCRParameter = new OCRParameter();
public OCRResult ocrResult = new OCRResult();
public PaddleOCREngine engine;
public RunPar()
{
engine = new PaddleOCREngine(config, oCRParameter);
}
[DllImport("kernel32.dll")]
public static extern void CopyMemory(int Destination, int add, int Length);
public Bitmap Honject2Bitmap24(HObject hObject)
{
HTuple width = new HTuple();
HTuple height = new HTuple();
HTuple pointer = new HTuple();
HTuple type = new HTuple();
HTuple width2 = new HTuple();
HTuple height2 = new HTuple();
HObject interleavedImage = new HObject();
HOperatorSet.GetImageSize(hObject, out width, out height);
HOperatorSet.InterleaveChannels(hObject, out interleavedImage, "rgb", 4 * width, 0);
HOperatorSet.GetImagePointer1(interleavedImage, out pointer, out type, out width2, out height2);
IntPtr scan = pointer;
return new Bitmap(width2 / 4, height2, width2, PixelFormat.Format24bppRgb, scan);
}
public void HObject2Bitmap8(HObject image, out Bitmap res)
{
HOperatorSet.GetImagePointer1(image, out var pointer, out var _, out var width, out var height);
res = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
ColorPalette palette = res.Palette;
for (int i = 0; i <= 255; i++)
{
palette.Entries[i] = Color.FromArgb(255, i, i, i);
}
res.Palette = palette;
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, width, height);
BitmapData bitmapData = res.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
int num = Image.GetPixelFormatSize(bitmapData.PixelFormat) / 8;
IntPtr scan = bitmapData.Scan0;
IntPtr source = pointer;
int num2 = width * height;
byte[] array = new byte[num2];
Marshal.Copy(source, array, 0, num2);
Marshal.Copy(array, 0, scan, num2);
res.UnlockBits(bitmapData);
}
}
[Serializable]
public class ResultPar
{
private string _OCRResult { get; set; }
public string OCRResult { get { return _OCRResult; } set { _OCRResult = value; } }
}
}
}
}