在做项目时,之前使用的是某康的智能读码器,综合考虑成本,可通过相机拍照来读取图片的二维码,我这边用Halcon来实现。
Halcon代码如下:
*创建模型
create_data_code_2d_model('Data Matrix ECC 200', [], [], DataCodeHandle)
*设置条码极性
set_data_code_2d_param(DataCodeHandle, 'polarity', 'any')
*解码时长的设置,超时直接将条码丢弃
set_data_code_2d_param(DataCodeHandle, 'timeout', 200)
*开始二维码识别
read_image (Image, 'C:/Users/Administrator/Desktop/AirPods/Image_20220815110012088.bmp')
*开始计时
count_seconds(Seconds)
*解析二维码
find_data_code_2d(Image, SymbolXLDs, DataCodeHandle, [], [], ResultHandles, DecodedDataStrings)
*结束计时
count_seconds(Seconds1)
*累计耗时
time:=Seconds1-Seconds
*判断解码结果是否有结果
tuple_length(DecodedDataStrings, Length)
if (Length>0)
*//获取区域
concat_obj(SymbolXLDs, SymbolXLDs, ObjectsConcat)
dev_clear_window ()
dev_display (Image)
*绘制区域
dev_display(ObjectsConcat)
*显示二维码
dev_disp_text(DecodedDataStrings, 'window', 'top', 'left', 'black', [], [])
endif
显示效果:
可以看出几十毫秒可以解读条码,如要识别其他类型的二维码,可更改create_data_code_2d_model算子的参数。
那么如何将Halcon代码转化为C#可调用的方法?
1 先将Halcon代码导出,得到cs文件
2 在VS中添加Halcon的引用,并将方法调整,我这里是结合OpencvSHarp
调整后的方法:
/// <summary>
/// 识别 Data Matrix ECC 200
/// </summary>
/// <param name="ho_InputImage">图片对象</param>
/// <returns></returns>
private string ReadDataMatrix(HObject ho_InputImage)
{
string result = string.Empty;
// Local iconic variables
HObject ho_SymbolXLDs;
HObject ho_ObjectsConcat = null;
// Local control variables
HTuple hv_DataCodeHandle = new HTuple(), hv_Seconds = new HTuple();
HTuple hv_ResultHandles = new HTuple(), hv_DecodedDataStrings = new HTuple();
HTuple hv_Seconds1 = new HTuple(), hv_time = new HTuple();
HTuple hv_Length = new HTuple();
// Initialize local and output iconic variables
HOperatorSet.GenEmptyObj(out ho_SymbolXLDs);
HOperatorSet.GenEmptyObj(out ho_ObjectsConcat);
try
{
//创建模型
hv_DataCodeHandle.Dispose();
//QR Code
HOperatorSet.CreateDataCode2dModel("QR Code", new HTuple(), new HTuple(), out hv_DataCodeHandle);
//HOperatorSet.CreateDataCode2dModel("QR Code", new HTuple(), new HTuple(), out hv_DataCodeHandle);
//设置条码极性
HOperatorSet.SetDataCode2dParam(hv_DataCodeHandle, "polarity", "any");
//解码时长的设置,超时直接将条码丢弃
HOperatorSet.SetDataCode2dParam(hv_DataCodeHandle, "timeout", 300);
//**********开始二维码识别****************
//开始计时
hv_Seconds.Dispose();
HOperatorSet.CountSeconds(out hv_Seconds);
//解析二维码
ho_SymbolXLDs.Dispose(); hv_ResultHandles.Dispose(); hv_DecodedDataStrings.Dispose();
HOperatorSet.FindDataCode2d(ho_InputImage, out ho_SymbolXLDs, hv_DataCodeHandle,
new HTuple(), new HTuple(), out hv_ResultHandles, out hv_DecodedDataStrings);
//结束计时
hv_Seconds1.Dispose();
HOperatorSet.CountSeconds(out hv_Seconds1);
//累计耗时
hv_time.Dispose();
using (HDevDisposeHelper dh = new HDevDisposeHelper())
{
hv_time = hv_Seconds1 - hv_Seconds;
}
//MessageBox.Show(hv_time);
//判断解码结果是否有结果
hv_Length.Dispose();
HOperatorSet.TupleLength(hv_DecodedDataStrings, out hv_Length);
if ((int)(new HTuple(hv_Length.TupleGreater(0))) != 0)
{
result = hv_DecodedDataStrings;
}
}
catch (Exception ex)
{
return result;
}
finally
{
ho_InputImage.Dispose();
ho_SymbolXLDs.Dispose();
ho_ObjectsConcat.Dispose();
hv_DataCodeHandle.Dispose();
hv_Seconds.Dispose();
hv_ResultHandles.Dispose();
hv_DecodedDataStrings.Dispose();
hv_Seconds1.Dispose();
hv_time.Dispose();
hv_Length.Dispose();
}
return result;
}
此处还涉及Mat对象转换为HObject
/// <summary>
/// Mat转换为HObject
/// </summary>
/// <param name="mat"></param>
/// <returns></returns>
public HImage Mat2HObject(Mat mat)
{
HImage hImage = new HImage();
try
{
if (mat.Type() == MatType.CV_8UC1)
{
hImage.GenImage1("byte", mat.Width, mat.Height, mat.Data);
}
else
{
hImage.GenImageInterleaved(mat.Data, "rgb", mat.Width, mat.Height, 0, "byte", mat.Width, mat.Height, 0, 0, -1, 0);
}
}
catch (Exception)
{
}
finally
{
mat.Dispose();
}
return hImage;
}