Bootstrap

Halcon之二维码

1,简介。

        Halcon提供读取二维码格式类型为PDF417,数据矩阵ECC200、QR码,MicroQR码以及Aztec码。与条形码相似,均是对字符和数字进行编码,这些符号由暗条和亮条或成为模块的点组成。条形码使用黑色条和空格作为模块,由于单个暗条和亮条沿其高度具有恒定的宽度,因此可以沿符号的宽度在单个扫描线中读取条形码。与条形码相反,对于二维码符号,改变沿两个方向发生。因此相同的信息可以被编码到更小的符号中。符号的大小,由两个方向上的模块数量确定,以及编码信息的长度或者所读取信息所需要的纠错级别。后者需要可以完全解码的符号,即使符号具有小缺陷,比如,二维码中一些模块不可见模糊等。常见的两种不同类型的二维码为堆叠码与矩形码。

        在堆叠码中,Halcon支持PDF417,其符号由几个条形码组成,这些条形码按照行和列进行排列,每一个条形码对单个“码字”进行编码。根据符号类型的名称,每个码字由四个暗条和四个光条(空格)构成的17个模块组合而成。它总是从黑暗开始,以光条结束。PDF417符号的行数和列数在3到90行、1到30列的范围内变化。开始和停止模式框定左右边框上的符号。码字的第一和最后列被称为左和右行指示符。在符号边界周围,放置均匀帧,这称为静区。对于小符号,存在PDF417的变体,其中没有右行指示符,停止模式减少为一个模块宽的条。它被称为紧凑或截断PDF417。

        矩阵码使用的式图形模式,它主要由三部分组成:前景模块、背景模块和取景器。取景器用于查找符号在图像中的取向。Halcon支持的矩阵码为ECC200、QR、MicroQR、Aztec,如下图所示

        对于矩阵码其前景和背景模块通常是正方形或矩形,但也出现圆形前景模块。模块按照行和列排序,行和列的数量定义符号的大小,对于QR码可以直接连接到其版本号,版本号越高,符号越大。ECC200的取景器为L型,以及在对应的边界上由暗和亮模块交替组成。QR码的取景器由三个“正方形”组成,称为“位置检测图形”。较小的MicroQR码只有1个取景器图形 ,也是正方形位于这个“位置检测图形”位于符号的左上角。Aztec码的取景器元素有嵌套在位于代码中间的方块组成。

        尽管堆叠码也可以通过条形码读取器逐行读取,但是矩阵码只能通过检测图像来解码,即需要通过相机获取图像。每个二维码都可以使用不同格式的符号类型,只有在读取过程分配合适的参数,才能较好的实现对二维码符号内容的查找,解码。

2,参数解析。

2.1参数: 'default_parameters':

参数定义

        用于配置二维码识别性能模式,默认值为 standard_recognition,需在 create_data_code_2d_model 首位声明。


参数值解码速度识别精度硬件资源占用适用场景
standard_recognition极快‌ (≤50ms)基础容错(破损率≤10%)CPU < 30%常规印刷标签、流水线扫码
enhanced_recognition中等‌ (≤120ms)高精度(破损率≤25%)CPU 50%-70%反光金属表面、轻微畸变
maximum_recognition‌ (≤300ms)极限容错(破损率≤40%)GPU ≥80%强反光曲面、严重污损标签
* Initialize visual settings
dev_update_off ()
dev_close_window ()
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
dev_set_color ('green')
dev_set_line_width (3)
Message := 'This program demonstrates how to read 2d data'
Message[1] := 'codes with the following default settings:'
Message[2] := ' \'standard recognition\''
Message[3] := ' \'enhanced recognition\''
Message[4] := ' \'maximum recognition\''
Message[5] := ' '
Message[6] := 'Note that you can choose the desired symbol'
Message[7] := 'types by (un)commenting the corresponding'
Message[8] := 'lines in the code.'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Step 1: Choose the symbol type
* -------------------------------------------------------
* Choose the symbol types by (un)commenting the corresponding
* lines. Note that you can choose more than one symbol type.
SymbolType := []
SymbolType := [SymbolType,'QR Code']
SymbolType := [SymbolType,'Micro QR Code']
SymbolType := [SymbolType,'PDF417']
SymbolType := [SymbolType,'Aztec Code']
SymbolType := [SymbolType,'Data Matrix ECC 200']
* 
* Loop over all chosen symbol types
* -------------------------------------------------------
* Get images of the chosen symbol types, create the
* corresponding data code model with each default setting,
* read the data codes with each model and display the results
for Index := 0 to |SymbolType| - 1 by 1
    * 
    * Step 2 : Get image names for the current symbol type
    * ----------------------------------------------------
    * Ecc 200
    if (SymbolType[Index] == 'Data Matrix ECC 200')
        list_image_files ('datacode/ecc200', 'default', [], ImageFiles)
        ImageFiles := regexp_select(ImageFiles,'(ecc200_cpu_)|(ecc200_disturbed_0)')
        * QR Code
    elseif (SymbolType[Index] == 'QR Code')
        list_image_files ('datacode/qrcode', 'default', [], ImageFiles)
        ImageFiles := regexp_select(ImageFiles,'qr_workpiece')
        * Micro QR Code
    elseif (SymbolType[Index] == 'Micro QR Code')
        list_image_files ('datacode/micro_qr', 'default', [], ImageFiles)
        ImageFiles := regexp_select(ImageFiles,'micro_qr')
        * PDF417
    elseif (SymbolType[Index] == 'PDF417')
        list_image_files ('datacode/pdf417', 'default', [], ImageFiles)
        ImageFiles := regexp_select(ImageFiles,'(pdf417_hd)|(pdf417_misc)')
        * Aztec
    elseif (SymbolType[Index] == 'Aztec Code')
        list_image_files ('datacode/aztec', 'default', [], ImageFiles)
        ImageFiles := regexp_select(ImageFiles,'aztec')
    endif
    * 
    * Step 3: Create data code models
    * ---------------------------------------------------
    * Create a model of the current symbol type for each
    * default setting standard, enhanced, and maximum.
    create_data_code_2d_model (SymbolType[Index], 'default_parameters', 'standard_recognition', DataCodeHandleStandard)
    create_data_code_2d_model (SymbolType[Index], 'default_parameters', 'enhanced_recognition', DataCodeHandleEnhanced)
    create_data_code_2d_model (SymbolType[Index], 'default_parameters', 'maximum_recognition', DataCodeHandleMaximum)
    set_data_code_2d_param (DataCodeHandleMaximum, 'polarity', 'light_on_dark')
    * 
    * Loop over all images
    * ----------------------------------------------------
    * Search and read the data codes in each image and
    * display the decoded string for each found data code
    NLoops := 20
    for I := 0 to |ImageFiles| - 1 by 1
        read_image (Image, ImageFiles[I])
        dev_resize_window_fit_image (Image, 0, 0, -1, -1)
        dev_display (Image)
        * 
        * Step 4: Read the data codes
        * -------------------------------------------
        * Find and decode the data codes with each
        * data code model and measure the runtime
        * 
        * Standard mode
        find_data_code_2d (Image, SymbolXLDs, DataCodeHandleStandard, [], [], ResultHandles, DecodedDataStrings)
        count_seconds (T1)
        for N := 1 to NLoops by 1
            find_data_code_2d (Image, SymbolXLDs, DataCodeHandleStandard, [], [], ResultHandles, DecodedDataStrings)
        endfor
        count_seconds (T2)
        FoundStandard := |DecodedDataStrings|
        TimeStandard := 1000 * (T2 - T1) / real(NLoops)
        * 
        * Enhanced mode
        find_data_code_2d (Image, SymbolXLDs, DataCodeHandleEnhanced, [], [], ResultHandles, DecodedDataStrings)
        count_seconds (T1)
        for N := 1 to NLoops by 1
            find_data_code_2d (Image, SymbolXLDs, DataCodeHandleEnhanced, [], [], ResultHandles, DecodedDataStrings)
        endfor
        count_seconds (T2)
        FoundEnhanced := |DecodedDataStrings|
        TimeEnhanced := 1000 * (T2 - T1) / real(NLoops)
        * 
        * Maximum mode
        find_data_code_2d (Image, SymbolXLDs, DataCodeHandleMaximum, [], [], ResultHandles, DecodedDataStrings)
        count_seconds (T1)
        for N := 1 to NLoops by 1
            find_data_code_2d (Image, SymbolXLDs, DataCodeHandleMaximum, [], [], ResultHandles, DecodedDataStrings)
        endfor
        count_seconds (T2)
        FoundMaximum := |DecodedDataStrings|
        TimeMaximum := 1000 * (T2 - T1) / real(NLoops)
        * 
        * Generate the message for the runtimes
        * ---------------------------------------
        ResultMessage := 'Runtime of recognition modes:'
        Color := gen_tuple_const(4,'black')
        * Standard
        ResultMessage[1] := ' standard mode:' + TimeStandard$'7.2f' + ' ms'
        if (FoundStandard == 0)
            ResultMessage[1] := ResultMessage[1] + ' (no symbol found)'
            Color[1] := 'red'
        endif
        * Enhanced
        ResultMessage[2] := ' enhanced mode:' + TimeEnhanced$'7.2f' + ' ms'
        if (FoundEnhanced == 0)
            ResultMessage[2] := ResultMessage[2] + ' (no symbol found)'
            Color[2] := 'red'
        endif
        * Maximum
        ResultMessage[3] := ' maximum mode: ' + TimeMaximum$'7.2f' + ' ms'
        if (FoundMaximum == 0)
            ResultMessage[3] := ResultMessage[3] + ' (no symbol found)'
            Color[3] := 'red'
        endif
        * 
        * Step 5: Display the results
        * --------------------------------------------
        TitleMessage := SymbolType[Index] + ': Image ' + (I + 1) + ' of ' + |ImageFiles|
        display_found_data_codes (SymbolXLDs, WindowHandle, DecodedDataStrings, TitleMessage, ResultMessage, 'forest green', Color)
        * 
        * Deacivate the following lines to run the program without breaks
        if (I < |ImageFiles| - 1 or Index < |SymbolType| - 1)
            disp_continue_message (WindowHandle, 'black', 'true')
            stop ()
        endif
    endfor
    * 
    * Clear the 2d data code models
    clear_data_code_2d_model (DataCodeHandleStandard)
    clear_data_code_2d_model (DataCodeHandleEnhanced)
    clear_data_code_2d_model (DataCodeHandleMaximum)
endfor

2.2参数 ‘contrast_tolerance

参数定义
        控制算法对局部对比度变化的容忍度(如强光/反光场景),通过不同算法组合实现性能与精度的平衡,改善光照不均场景下的读取成功率。

🔢 ‌取值对比表

取值算法策略性能表现适用场景推荐指数
low单一快速算法⚡️ 最快速度常规对比度环境★★★★☆
high强化抗干扰算法⏳ 较高耗时强反光/极端对比变化环境★★☆☆☆
any双算法并行验证🐢 最低速度对精度要求极高的关键场景★☆☆☆☆

⚙️ ‌默认设置
Default: 'low'
Enhanced Mode: 'low'
Maximum Tolerance: 'any'

💡 ‌使用建议

  1. 优先使用默认值 low 满足大多数场景
  2. 仅在出现明显反光干扰时尝试 high
  3. 对精度要求>速度时启用 any
  4. 可通过性能表现列图标快速识别速度差异
* This example demonstrates the impact of the parameter
* 'contrast_tolerance' parameter of the ECC200 reader.
* 
* If 'contrast_tolerance' is set to 'high', the ECC200 reader is
* more tolerant towards local contrast variation within a symbol.
* This is achieved due to internal preprocessing.
* If 'contrast_tolerance' is set to 'low', this preprocessing step
* is omitted.
* If 'contrast_tolerance' is set to 'any', the reader tries both
* modes.
* 
* Note that 'contrast_tolerance' is also included in the training
* mode of the ECC200 reader.
* 
dev_update_off ()
dev_close_window ()
* 
* Initialize image path and window size
list_image_files ('datacode/ecc200', 'default', [], ImageFiles)
tuple_regexp_select (ImageFiles, 'contrast_variations', ImageFiles)
read_image (Image, ImageFiles[0])
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_color ('green')
dev_set_line_width (3)
* 
* Display short description
Message := 'This example program demonstrates how the parameter'
Message[1] := '\'contrast_tolerance\' influences the search with a'
Message[2] := 'ECC200 reader for 2d data code symbols with local'
Message[3] := 'contrast variations.'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Create ECC200 data code model with 'contrast_tolerance' set to 'low'
create_data_code_2d_model ('Data Matrix ECC 200', 'default_parameters', 'enhanced_recognition', DataCodeHandleLow)
set_data_code_2d_param (DataCodeHandleLow, 'contrast_tolerance', 'low')
* 
* Create ECC200 data code model with 'contrast_tolerance' set to 'high'
create_data_code_2d_model ('Data Matrix ECC 200', 'default_parameters', 'enhanced_recognition', DataCodeHandleHigh)
set_data_code_2d_param (DataCodeHandleHigh, 'contrast_tolerance', 'high')
* 
for Index := 0 to 5 by 1
    read_image (Image, ImageFiles[Index])
    Loops := 2
    * 
    * Try to find the data code symbol with 'contrast_tolerance' set to 'low'
    count_seconds (T1)
    for Loop := 1 to Loops by 1
        find_data_code_2d (Image, SymbolXLDs, DataCodeHandleLow, [], [], ResultHandles, DecodedDataStrings)
    endfor
    count_seconds (T2)
    FoundLow := |DecodedDataStrings|
    TimeLow := 1000 * (T2 - T1) / Loops
    * 
    * Try to find the data code symbol with 'contrast_tolerance' set to 'high'
    count_seconds (T1)
    for Loop := 1 to Loops by 1
        find_data_code_2d (Image, SymbolXLDs, DataCodeHandleHigh, [], [], ResultHandles, DecodedDataStrings)
    endfor
    count_seconds (T2)
    FoundHigh := |DecodedDataStrings|
    TimeHigh := 1000 * (T2 - T1) / Loops
    * 
    * Create message about the search
    Color := gen_tuple_const(4,'black')
    Message := 'Runtime:'
    Message[1] := '\'contrast_tolerance\' = \'low\': ' + TimeLow$'8.2f' + ' ms'
    if (FoundLow == 0)
        Message[1] := Message[1] + '  (no symbol found)'
        Color[1] := 'red'
    endif
    Message[2] := '\'contrast_tolerance\' = \'high\':' + TimeHigh$'8.2f' + ' ms'
    if (FoundHigh == 0)
        Message[2] := Message[2] + '  (no symbol found)'
        Color[2] := 'red'
    endif
    * 
    * Display the data code symbol and information about runtime
    dev_display (Image)
    dev_display (SymbolXLDs)
    disp_message (WindowHandle, 'Image ' + (Index + 1) + ' of 6', 'window', 12, 12, 'black', 'true')
    disp_message (WindowHandle, Message, 'window', 40, 12, Color, 'true')
    * 
    * Display continue message
    if (Index < 5)
        disp_continue_message (WindowHandle, 'black', 'true')
        stop ()
    endif
endfor
* 
* Clear the 2d data code models
clear_data_code_2d_model (DataCodeHandleLow)
clear_data_code_2d_model (DataCodeHandleHigh)

 2.3参数:‘train’

参数定义

        使用样本二维码图形进行训练,获取参数,以便对有噪声,模糊的二维码进行识别。

*训练保存二维码模型文件
*读取保存的二维码模型文件并应用于二维码的读取
dev_update_off ()
dev_close_window ()
ImageFiles := 'datacode/ecc200/ecc200_cpu_0'
ImageNum := 16
read_image (Image, ImageFiles + '07')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
dev_set_line_width (3)
dev_set_color ('green')
* 
* Display short description
* This program demonstrates the training of a 2d data code model
* and how to write the trained model into a file and also how to
* read the saved model from the file. The model is then used
* to find data codes in a sequence of images.
Message := 'This program demonstrates the training of a 2d data code'
Message[1] := 'model, how to write the trained model into a file, and'
Message[2] := 'also how to read the saved model from the file. The'
Message[3] := 'model is then used to find data codes in a sequence of'
Message[4] := 'images.'
Message[5] := 'Furthermore it is shown how to obtain the values of the'
Message[6] := 'model parameters before and after the training.'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Step 1: Create a 2d data code model
* -------------------------------------------------------
* Create a 2d data code model of the 2d data code class
* 'Data Matrix ECC 200'. The operator returns a handle to
* the 2d data code model which can be used for all further
* operations on the data code.
create_data_code_2d_model ('Data Matrix ECC 200', [], [], DataCodeHandle)
* 
* Get model parameters before the training
* -------------------------------------------------------
query_data_code_2d_params (DataCodeHandle, 'get_model_params', GenParamNames)
get_data_code_2d_param (DataCodeHandle, GenParamNames, ModelBeforeTraining)
* 
* Step 2: Train the model
* -------------------------------------------------------
* Train the model on a dark and a bright image
* 
* 暗图片
read_image (Image, 'datacode/ecc200/ecc200_cpu_007')
find_data_code_2d (Image, SymbolXLDs, DataCodeHandle, 'train', 'all', ResultHandles, DecodedDataStrings)
dev_display (Image)
dev_display (SymbolXLDs)
TitleMessage := 'Train on a dark image'
display_found_data_codes (SymbolXLDs, WindowHandle, DecodedDataStrings, TitleMessage, [], 'forest green', 'black')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* 亮图片
read_image (Image, 'datacode/ecc200/ecc200_cpu_008')
find_data_code_2d (Image, SymbolXLDs, DataCodeHandle, 'train', 'all', ResultHandles, DecodedDataStrings)
dev_display (Image)
dev_display (SymbolXLDs)
TitleMessage := 'Train on a bright image'
display_found_data_codes (SymbolXLDs, WindowHandle, DecodedDataStrings, TitleMessage, [], 'forest green', 'black')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Get model parameters after the training
* -------------------------------------------------------
get_data_code_2d_param (DataCodeHandle, GenParamNames, ModelAfterTraining)
* 
* Display the model parameters
dev_clear_window ()
ModelAdaption := (GenParamNames + ':')$'-25' + ModelBeforeTraining$'15' + ' -> ' + ModelAfterTraining
disp_message (WindowHandle, 'Model parameters before and after the training:', 'window', 12, 12, 'white', 'false')
disp_message (WindowHandle, ModelAdaption, 'window', 60, 12, 'white', 'false')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Step 3: Write the model into a file
* --------------------------------------------------------
* Save the model in a file so that it can be used later
write_data_code_2d_model (DataCodeHandle, '2d_data_code_model.dcm')
* 
* Clear the 2d data code model
clear_data_code_2d_model (DataCodeHandle)
* 
* Display message about saved file and next step
dev_clear_window ()
Message := 'The data code model is saved in \'2d_data_code_model.dcm\'.'
Message[1] := ' '
Message[2] := 'In the next step the saved model is read and used to'
Message[3] := 'find data codes in a sequenz of images.'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Step 4: Read an existing 2d data code model
* ----------------------------------------------------------
* Read the previously saved data code model
read_data_code_2d_model ('2d_data_code_model.dcm', DataCodeHandle)
* 
* Step 5: Read the data codes
* -------------------------------------------------------
* Search and read the data codes in each image and
* display the decoded string for each found data code
for Index := 7 to 16 by 1
    read_image (Image, ImageFiles + Index$'.2d')
    dev_display (Image)
    * 
    * Find and decode the data codes and measure the runtime
    count_seconds (T1)
    find_data_code_2d (Image, SymbolXLDs, DataCodeHandle, [], [], ResultHandles, DecodedDataStrings)
    count_seconds (T2)
    Time := 1000 * (T2 - T1)
    * 
    * Display the results
    TitleMessage := 'Image ' + (Index - 6) + ' of ' + (ImageNum - 6)
    ResultMessage := 'Data code found in ' + Time$'.1f' + ' ms'
    display_found_data_codes (SymbolXLDs, WindowHandle, DecodedDataStrings, TitleMessage, ResultMessage, 'forest green', 'black')
    * 
    * Deactivate the following lines to run the program without breaks
    if (Index < ImageNum)
        disp_continue_message (WindowHandle, 'black', 'true')
        stop ()
    endif
endfor
* 
* Clear the 2d data code model
clear_data_code_2d_model (DataCodeHandle)
*对于查找有噪声且模糊的二维码需要对样本进行训练然后再进行读取识别
* Initialize image path and visual settings
dev_update_off ()
dev_close_window ()
ImageFiles := 'datacode/ecc200/ecc200_damaged_finder_pattern_'
ImageFilesTrain := 'datacode/ecc200/ecc200_damaged_finder_pattern_training_'
ImageNum := 19
ImageTrainNum := 5
read_image (Image, ImageFiles + '01')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_line_width (3)
dev_set_color ('green')
* 
* Display short description
Message := 'This program demonstrates how to find and decode'
Message[1] := 'ECC200 symbols that have a heavily disturbed finder pattern.'
Message[2] := 'To read these symbols successfully, some example images'
Message[3] := 'that contain ECC200 symbols with similar disturbances'
Message[4] := 'are used to train the data code reader.'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Step 1: Create a 2d data code model
* ----------------------------------------------------
* Create a 2d data code model of the 2d data code class
* 'Data Matrix ECC 200'.
create_data_code_2d_model ('Data Matrix ECC 200', [], [], DataCodeHandle)
* 
* Step 2: 训练模型,获取参数
* -------------------------------------------------------
* Train the model on some images containing ECC 200 symbols
* with disturbed finder pattern
for Index := 1 to ImageTrainNum by 1
    read_image (Image, ImageFilesTrain + Index$'.2d')
    * 
    * Find and decode the data codes
    *'train', 'all':表示所有参数均需要进行训练
    find_data_code_2d (Image, SymbolXLDs, DataCodeHandle, 'train', 'all', ResultHandles, DecodedDataStrings)
   
    * Display results
    dev_display (Image)
    dev_display (SymbolXLDs)
    TitleMessage := 'Train on image ' + Index + ' of ' + ImageTrainNum
    display_found_data_codes (SymbolXLDs, WindowHandle, DecodedDataStrings, TitleMessage, [], 'forest green', 'black')
    disp_continue_message (WindowHandle, 'black', 'true')
    stop ()
endfor
* 
* Display message about the next step
dev_clear_window ()
Message := 'The trained data code model is now used to find the data codes'
Message[1] := 'in a sequence of images with similar disturbances.'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Step 3: 读取二维码
* -------------------------------------------------------
* 通过训练模型查找和读取二维码
* in each image and display the decoded string for each
* found data code
for Index := 1 to ImageNum by 1
    read_image (Image, ImageFiles + Index$'.2d')
    dev_display (Image)
    * 
    * Find and decode the data codes and measure the runtime
    count_seconds (T1)
    find_data_code_2d (Image, SymbolXLDs, DataCodeHandle, [], [], ResultHandles, DecodedDataStrings)
    count_seconds (T2)
    Time := (T2 - T1) * 1000.0
    * 
    * Display the results
    TitleMessage := 'Image ' + Index + ' of ' + ImageNum
    ResultMessage := 'Data code found in ' + Time$'.1f' + ' ms'
    display_found_data_codes (SymbolXLDs, WindowHandle, DecodedDataStrings, TitleMessage, ResultMessage, 'forest green', 'black')
    * 
    * If no data codes are found
    if (|ResultHandles| == 0)
        disp_message (WindowHandle, 'No Symbol found (in ' + Time$'.1f' + ' ms )', 'window', -1, -1, 'black', 'true')
    endif
    * 
    * Deactivate the following lines to run the program without breaks
    if (Index < ImageNum)
        disp_continue_message (WindowHandle, 'black', 'true')
        stop ()
    endif
endfor
* 
* Clear the data code model
clear_data_code_2d_model (DataCodeHandle)

训练图形

训练完成后才能成功识别读取二维码

2.4 参数 mall_modules_robustness

‌参数定义

        提升对小尺寸模块(黑白单元)的检测鲁棒性,适用于高密度、微型或低质量数据码的识别。实现对超小二维码的检测。


参数定义与取值
适用场景算法行为
low标准模块尺寸(清晰、高对比度)快速检测,但对微小模块或模糊边缘敏感,可能漏检。
medium中等密度或轻微噪声干扰的模块平衡检测精度与速度,允许一定程度的模块尺寸波动。
high微型模块、低分辨率或强噪声环境增强抗干扰能力,容忍模块变形和边缘模糊,但计算量显著增加。

场景适配与配置建议
场景类型参数值辅助参数搭配预处理建议
高密度Data Matrix(如电子元件标签)highmodule_size_min=3, module_size_max=8图像锐化 + 对比度拉伸
低光照模糊条码mediumcontrast_min=30, noise_tolerance=high自适应阈值分割 + 去噪
工业印刷标准条码(清晰)lowfinder_pattern_tolerance=low无需特殊处理

2.5 参数 module_size_min

1. 参数定义与核心作用

  • 功能‌:设定数据码中单个模块(Module,即黑白单元)的‌最小像素宽度‌,用于过滤噪声或无效区域。
  • 默认值‌:通常为 5(根据图像分辨率动态调整)。
  • 影响范围‌:直接决定检测算法的搜索空间,过小可能导致误检,过大导致漏检。

2. 场景适配与推荐值
场景类型推荐值配合参数预处理建议
高密度条码(如电子元件标签)3-4small_modules_robustness='high'图像锐化 + ROI 裁剪
低分辨率图像(远距离拍摄)2-3contrast_min=20超分辨率重建 + 对比度增强
标准印刷条码(清晰、无变形)5finder_pattern_tolerance='low'无需处理
强噪声环境(工业脏污、反光)6-8noise_tolerance='high'中值滤波 + 形态学去噪
*这个示例程序展示了如何查找和解码具有非常小模块大小的ECc200符号。
*要成功读取这些符号,默认设置为“低”的参数“小模块鲁棒性”必须设置为“高”。
*此外,参数“模块大小最小”必须设置为最小预期模块大小,在本例中为值1。
*为了显示参数“小模块鲁棒性”的影响在数据码读取器上,
*运算符查找数据码2d被调用两次使用不同的关于参数设置。
* 
dev_update_off ()
dev_close_window ()
read_image (Image, 'datacode/ecc200/ecc200_cpu_001')
ZoomFactorStart := 0.8
zoom_image_factor (Image, ImageZoomed, ZoomFactorStart, ZoomFactorStart, 'constant')
dev_open_window_fit_image (ImageZoomed, 0, 0, -1, -1, WindowHandle1)
* 
* Open a second window with in the same size as the first window
get_window_extents (WindowHandle1, Row, Column, WidthOriginal, HeightOriginal)
dev_open_window_fit_size (0, WidthOriginal + 10, WidthOriginal, HeightOriginal, -1, -1, WindowHandle2)
dev_set_line_width (2)
* 
* Create two ECC 200 data code models for 'small_modules_robustness' set to 'high'
* and 'small_modules_robustness' set to 'low', respectively (set 'module_size_min' to 1).
create_data_code_2d_model ('Data Matrix ECC 200', ['small_modules_robustness','module_size_min'], ['high',1], DataCodeHandle1)
create_data_code_2d_model ('Data Matrix ECC 200', ['small_modules_robustness','module_size_min'], ['low',1], DataCodeHandle2)
* 
* Within the loop:
* + In each iteration step, the image is scaled down again
* + Find the data code with 'small_modules_robustness' set to 'high'
* + Find data code with 'small_modules_robustness' set to 'low'
* + Display the results for each setting in different windows
Size := 16
for ZoomFactor := ZoomFactorStart to 0.3 by -0.1
    zoom_image_factor (Image, ImageZoomed, ZoomFactor, ZoomFactor, 'constant')
    set_display_font (WindowHandle1, Size, 'mono', 'true', 'false')
    set_display_font (WindowHandle2, Size, 'mono', 'true', 'false')
    Size := Size - 1
    * 
    * Find data code with 'small_modules_robustness' set to 'high'
    find_data_code_2d (ImageZoomed, SymbolXLDs1, DataCodeHandle1, [], [], ResultHandles1, DecodedDataStrings1)
    * 
    * Find data code with 'small_modules_robustness' set to 'low'
    find_data_code_2d (ImageZoomed, SymbolXLDs2, DataCodeHandle2, [], [], ResultHandles2, DecodedDataStrings2)
    * 
    * Display the results for both settings
    if (Size < 11)
        Message := 'Small modules robustness:\n'
    else
        Message := 'Small modules robustness: '
    endif
    * For 'small_modules_robustness: high'
    dev_set_window (WindowHandle1)
    dev_resize_window_fit_image (ImageZoomed, 0, 0, 1000, 1000)
    dev_set_line_width (2)
    dev_display (ImageZoomed)
    disp_message (WindowHandle1, Message + 'high', 'window', 4, 4, 'black', 'true')
    disp_results (SymbolXLDs1, WindowHandle1, DataCodeHandle1, ResultHandles1, DecodedDataStrings1)
    * For 'small_modules_robustness: low'
    dev_set_window (WindowHandle2)
    dev_resize_window_fit_image (ImageZoomed, 0, WidthOriginal + 10, 1000, 1000)
    dev_display (ImageZoomed)
    disp_message (WindowHandle2, Message + 'low', 'window', 4, 4, 'black', 'true')
    disp_results (SymbolXLDs2, WindowHandle2, DataCodeHandle2, ResultHandles2, DecodedDataStrings2)
    disp_continue_message (WindowHandle2, 'black', 'true')
    stop ()
endfor
* 
* Clear the data code model
clear_data_code_2d_model (DataCodeHandle1)
clear_data_code_2d_model (DataCodeHandle2)
dev_close_window ()

二维码符号较大时两种模式均可识别:

二维码符号较小时,Hight模式可是识别而Low模式无法识别:

 


2.6 参数 strict_quiet_zone

1. 参数定义与核心作用
静区(Quiet Zone)‌:

        数据码(如QR码、Data Matrix)周围必须存在的空白区域,用于隔离干扰信号,确保解码稳定性和准确性。

  • 标准规范‌:静区宽度需 ≥ 1倍模块尺寸(Module Size)。
  • 参数意义‌:strict_quiet_zone 控制是否严格遵循静区宽度标准。

2. 参数模式对比

模式检测行为适用场景
严格模式true静区宽度必须 ≥1倍模块尺寸,否则判定为无效。工业高精度场景(静区完整、无遮挡)
宽松模式false允许静区部分缺失或宽度接近0,依赖算法补偿。静区受损、标签边缘印刷、低质量图像环境

3. 场景配置与调优建议

典型场景适配
  • 场景1:精密工业标签(静区完整)

    • 参数值‌:true
    • 辅助参数‌:module_size_min=5, contrast_min=30
    • 预处理建议‌:背光均匀照明 + 高斯滤波降噪
  • 场景2:物流标签边缘印刷(静区缺失)

    • 参数值‌:false
    • 辅助参数‌:quiet_zone_min_factor=0.5
    • 预处理建议‌:ROI裁剪 + 边缘锐化
  • 场景3:高反射表面数据码(如金属)

    • 参数值‌:false
    • 辅助参数‌:noise_tolerance=high, polarity=light
    • 预处理建议‌:偏振光照明 + 动态阈值分割
性能与误检率权衡
  • 严格模式 (true)‌:

    • 优势‌:误检率降低 20%~40%(静区完整场景)。
    • 风险‌:静区不足时可能漏检。
  • 宽松模式 (false)‌:

    • 优势‌:支持复杂环境(如静区被遮挡)。
    • 代价‌:计算时间增加 10%~15%。
*静区检测参数应用样例 
dev_update_off ()
dev_close_window ()
read_image (Image, 'datacode/qrcode/qr_milk_carton')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
dev_display (Image)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_line_width (3)
* 
* Create data code model,设置为Micro QR Code
create_data_code_2d_model ('Micro QR Code', 'default_parameters', 'enhanced_recognition', DataCodeHandle)
* 
*使用默认参数进行搜索,在QRCode中查找到Micro QR Code
find_data_code_2d (Image, SymbolXLDs, DataCodeHandle, [], [], ResultHandles, DecodedDataStrings)
dev_set_color ('red')
dev_display (Image)
dev_display (SymbolXLDs)
Message := 'This program demonstrates how to suppress the detection of'
Message[1] := 'a false Micro QR Code inside larger codes while searching for'
Message[2] := 'Micro QR Codes.'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_message (WindowHandle, 'Search with default parameters:', 'window', 82, 12, 'black', 'true')
disp_message (WindowHandle, 'False Micro QR Code detected inside a QR Code.', 'window', 100, 12, 'red', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* 设置 'strict_quiet_zone' to 'yes' 执行严格的静区检查
set_data_code_2d_param (DataCodeHandle, 'strict_quiet_zone', 'yes')
* 
* Search with new setting
find_data_code_2d (Image, SymbolXLDs, DataCodeHandle, [], [], ResultHandles, DecodedDataStrings)
dev_set_color ('green')
dev_display (Image)
dev_display (SymbolXLDs)
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_message (WindowHandle, 'Search with \'strict_quiet_zone\' set to \'yes\':', 'window', 82, 12, 'black', 'true')
disp_message (WindowHandle, 'Detection of a false Micro QR Code was successfully suppressed.', 'window', 100, 12, 'forest green', 'true')
* 
* Clear the data code model
clear_data_code_2d_model (DataCodeHandle)

使用默认值时 即strict_quiet_zone=“no”,不检查静态区出现了误将QRCode的一部分作为Micro QR Code进行识别读取:

 设置strict_quiet_zone=“yes”,严格检查静态区避免了将QRCode的一部分作为Micro QR Code进行识别读取的情况:

 

;