Halcon一维码识别

文章目录

  • 参数连接
  • halcon 自带案例1(设置校验位识别条码)
  • Halcon 自带案例2(设置对比度识别条码)
  • Halcon 自带案例3(存在曲面变形)
  • Halcon 自带案例4(设置条码扫描线)
  • Halcon 自带案例5(一维码阈值)
  • Halcon Codabar编码案例
  • Halcon Code128编码案例
  • Halcon 符合编码案例
  • Halcon 当条码被遮挡的情况下
  • Halcon 检测条码绘制条码矩形 decode_bar_code_rectangle2
  • halcon 设置条码的高度和宽度案例

参数连接

一维码识别算子

halcon 自带案例1(设置校验位识别条码)

ctrl +e 选择 一维码的第一个案例, set_bar_code_param (BarCodeHandle, ‘check_char’, ‘present\absent’)设置条码是否检查校验位

在这里插入图片描述

*check_char    是否验证校验位(present是 absent 否)
*composite_code   附加一个二维条码构成"组合码"
*element_height_min 最小条码的高度
*element_size_max   条码最大尺寸(宽度和间距)
*element_size_min   条码最小尺寸(宽度和间距)
*max_diff_orient    相邻边缘方向的最大角度容差
*meas_thresh        用来识别条码边沿,一般取值[0.05,0.2]
*meas_thresh_abs
*min_identical_scanlines   认定成功解码所需的最少扫描线数,默认为1
*num_scanlines        条码扫描的最大数目
*orientation          条码方向()
*orientation_tol      条码方向容差()
*persistence          保存解码的中间结果
*start_stop_tolerance 当检测扫描线的起点和终点图案时,用该语句设置"容许误差"
*stop_after_result_num 设置要解码的条码条数
*upce_encodation       用以不同的输出格式(UPC-E码)
*timeout               检测超时
*train                 训练
*quiet_zone    
*slanted               对倾斜条码额外处理


* Read bar codes of type 2/5 Industrial
*这是创建一个空的条码模型,并将其存储在变量BarCodeHandle中。该模型可以用于设置和调整条码参数。
create_bar_code_model ([], [], BarCodeHandle)
* We expect to decode a single bar code per image
*此代码行设置读取图像时停止的结果数量。在本例中,我们只需要读取一个条码,因此此参数设置为1set_bar_code_param (BarCodeHandle, 'stop_after_result_num', 1)

* Some codes show a minimal code length of 1 digit. Hence, we need to decrease the
* default setting for this application.
*此代码行设置具体条码类型的参数。在本例中,‘2/5 Industrial’条码类型的最小长度被设置为1set_bar_code_param_specific (BarCodeHandle, '2/5 Industrial', 'min_code_length', 1)
* Note, that this is not recommended in real world applications due to the possibility
* of more false reads.

dev_close_window ()
dev_open_window (0, 0, 120, 300, 'black', WindowHandle)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
dev_set_draw ('margin')
dev_set_line_width (3)
for I := 1 to 4 by 1
    read_image (Image, 'barcode/25industrial/25industrial0' + I)
    get_image_size (Image, Width, Height)
    dev_set_window_extents (0, 0, Width - 1, Height - 1)
    dev_display (Image)
    dev_set_color ('green')

    * Read bar code, the resulting string includes the check character
 *不检查校验位的情况
    *设置条码参数,不检查校验位。
    set_bar_code_param (BarCodeHandle, 'check_char', 'absent')
    *寻找图像中的条码,并将解码结果存储在变量DecodedDataStrings中。此处使用了'2/5 Industrial'条码类型。
    find_bar_code (Image, SymbolRegions, BarCodeHandle, '2/5 Industrial', DecodedDataStrings)
    *在窗口中显示解码结果,颜色为黑色。
    disp_message (WindowHandle, DecodedDataStrings, 'window', 12, 12, 'black', 'false')
    *获取解码结果的长度,并将其存储在变量LastChar中。
    LastChar := strlen(DecodedDataStrings) - 1
    *在窗口中显示解码结果的最后一个字符,并将其颜色设置为森林绿。
    disp_message (WindowHandle, sum(gen_tuple_const(LastChar,' ')) + DecodedDataStrings{LastChar}, 'window', 12, 12, 'forest green', 'false')
    stop ()
    * Read bar code using the check character to check the result, i.e.,
    * the check character does not belong to the returned string anymore.
    * If the check character is not correct, the bar code reading fails
    dev_set_color ('green')
*检查校验位的情况
    *设置条码参数,检查校验位
    set_bar_code_param (BarCodeHandle, 'check_char', 'present')
    *再次寻找图像中的条码,并将解码结果存储在变量DecodedDataStrings中。此处同样使用了'2/5 Industrial'条码类型。
    find_bar_code (Image, SymbolRegions, BarCodeHandle, '2/5 Industrial', DecodedDataStrings)
    *在窗口中显示重新解码得到的结果,颜色为黑色。
    disp_message (WindowHandle, DecodedDataStrings, 'window', 36, 12, 'black', 'false')
    dev_set_color ('magenta')
    if (I < 4)
        stop ()
    endif
endfor

Halcon 自带案例2(设置对比度识别条码)

在这里插入图片描述

设置条码的对比度来减少运行的时间增加正确性,通过改变set_bar_code_param (BarCodeHandle, ‘contrast_min’, ContrastMinValue) 的值设置对比度计算时间,并且增加识别的正确率
在这里插入图片描述
ContrastMinValue :=0的的情况下识别到一维码的个数在这里插入图片描述
在这里插入图片描述

* Example program for the usage of the bar code parameter
* 'contrast_min'.
* 
* This parameter can be used to reduce the runtime of find_bar_code
* in the presence of a low contrast bar-like structures in an image.
* Moreover 'contrast_min' can also be used to reduce the number of
* false positives if the expected barcodes have high contrast.
* 
* Create bar code reader model
create_bar_code_model ([], [], BarCodeHandle)
* 
* Initialization
dev_update_off ()
dev_close_window ()
* 
* Read and display example images without any visible bar codes
read_image (Image, 'barcode/25interleaved/25interleaved_zeiss1')
* 
* Set display defaults
dev_open_window_fit_image (Image, 0, 0, 600, 500, WindowHandle)
dev_display (Image)
dev_set_draw ('margin')
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
get_window_extents (WindowHandle, Row, Column, Width, Height)
dev_open_window (0, Width + 5, 400, 300, 'white', WindowHandleText)
set_display_font (WindowHandleText, 14, 'mono', 'true', 'false')
* 
* Display information about the example
Message[0] := 'This example demonstrates the use of the bar code parameter \'contrast_min\'.'
Message[1] := ' '
Message[2] := 'The parameter \'contrast_min\' can be used to reduce the runtime of find_bar_code in the presence of low contrast bar-like structures in an image. Moreover \'contrast_min\' can also be used to reduce the number of false positives in applications where the expected barcodes have a high contrast.'
MessageWrapped := regexp_replace(Message + ' ',['(.{0,35})\\s','replace_all'],'$1\n')
disp_message (WindowHandleText, MessageWrapped, 'window', 12, 12, 'black', 'false')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
dev_set_window (WindowHandle)
dev_clear_window ()
dev_display (Image)


* 首先将'contrast_min'参数设置为默认值0,并执行find_bar_code函数,记录运行时间
* Number of repetitions for runtime measurements(运行时测量的次数)
NumRepeat := 100
* 
* First, set the minimum contrast of the bar code candidate regions
* to 0 (default)
ContrastMinValue := 0
*set_bar_code_param (条形码读取器模型的句柄, 要设置的参数名称, 参数的值)
set_bar_code_param (BarCodeHandle, 'contrast_min', ContrastMinValue)
* 
* The bar code reader finds many bar code candidate regions that have
* a low absolute contrast
Times := []
for I := 0 to NumRepeat by 1
    count_seconds (Start)
    *查找条形码
    find_bar_code (Image, SymbolRegions, BarCodeHandle, '2/5 Interleaved', DecodedDataStrings)
    count_seconds (End)
    Time := End - Start
    Times := [Times,Time]
endfor
RunTimeContrastMinLow := 1000 * median(Times)
* Get candidate regions and display results(选取区域并显示结果)
*访问在条码符号搜索或解码过程中创建的标志性对象。
get_bar_code_object (BarCodeObjects, BarCodeHandle, 'all', 'candidate_regions')
count_obj (BarCodeObjects, Number)
dev_set_color ('red')
dev_set_line_width (5)
dev_display (BarCodeObjects)
dev_set_window (WindowHandleText)
dev_clear_window ()
Message := ['\'contrast_min\' = ' + ContrastMinValue + ':','   Found ' + Number + ' candidate(s) in ' + (RunTimeContrastMinLow$'.4') + ' ms']
disp_message (WindowHandleText, Message, 'window', 12, 12, '', 'false')
* 
* Now, set the bar code reader parameter 'contrast_min' to a value
* greater than 0.0 to consider only candidates having an absolute
* contrast of at least that value.
*'contrast_min'参数设置为大于0的值,并再次执行find_bar_code函数,记录运行时间:
ContrastMinValue := 120
set_bar_code_param (BarCodeHandle, 'contrast_min', ContrastMinValue)
* 
* Search again for bar codes. Now, a significantly smaller number of
* candidates should be found, and the overall runtime should be reduced.
Times := []
for I := 0 to NumRepeat by 1
    count_seconds (Start)
    find_bar_code (Image, SymbolRegions, BarCodeHandle, '2/5 Interleaved', DecodedDataStrings)
    count_seconds (End)
    Time := End - Start
    Times := [Times,Time]
endfor
RunTimeContrastMinHigh := 1000 * median(Times)
* Get candidate regions and display results
dev_set_window (WindowHandle)
get_bar_code_object (BarCodeObjects, BarCodeHandle, 'all', 'candidate_regions')
count_obj (BarCodeObjects, Number)
dev_set_color ('forest green')
dev_set_line_width (3)
dev_display (BarCodeObjects)
smallest_rectangle1 (SymbolRegions, Row1, Column1, Row2, Column2)
get_bar_code_result (BarCodeHandle, 'all', 'decoded_types', DecodedTypes)
disp_message (WindowHandle, DecodedTypes + '\n' + DecodedDataStrings, 'image', Row1, Column2 + 20, 'black', 'true')
dev_set_window (WindowHandleText)
Message := ['\'contrast_min\' = ' + ContrastMinValue + ':','   Found ' + Number + ' candidate(s) in ' + (RunTimeContrastMinHigh$'.4') + ' ms']
disp_message (WindowHandleText, Message, 'window', 62, 12, 'forest green', 'false')
Message := 'Setting \'contrast_min\' to a higher value typically results in a faster execution and in fewer false positives.'
MessageWrapped := regexp_replace(Message + ' ',['(.{0,35})\\s','replace_all'],'$1\n')
disp_message (WindowHandleText, MessageWrapped, 'window', 122, 12, 'black', 'false')

Halcon 自带案例3(存在曲面变形)

在这里插入图片描述

分别设置set_bar_code_param (BarCodeHandle, ‘element_size_variable’, ‘false\true’)
对于条形码不变形的情况下element_size_variable的情况在这里插入图片描述
条形码扭曲变形的情况下在这里插入图片描述

* This example demonstrates how to use the bar code parameter
* 'element_size_variable' if surface deformations are present.
* 
* To illustrate the effect of the parameter, both decoding results
* are shown in contrast. It is shown that, under cylindrical
* surface deformation, setting the bar code parameter to 'true'
* will lead to successful decoding.
* ****************************************************************
* 
* Initialization
dev_update_off ()
dev_close_window ()
* 
* Create two bar code model with different element_size_variable values
create_bar_code_model ([], [], BarCodeHandle)
set_bar_code_param (BarCodeHandle, 'element_size_variable', 'false')
create_bar_code_model ([], [], BarCodeHandleVarSize)
set_bar_code_param (BarCodeHandleVarSize, 'element_size_variable', 'true')
CodeTypes := ['GS1 DataBar Limited','GS1 DataBar Expanded','GS1 DataBar Expanded Stacked']
* 
* Prepare graphics window
read_image (Image, 'barcode/gs1databar_limited/gs1databar_limited_no_deform')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
* 
* Define bar code region
DecodeRectRow := 315
DecodeRectColumn := 490
DecodeRectPhi := 0
DecodeRectLength1 := 410
DecodeRectLength2 := 200
* 
* Part 1
* Read bar code without distortions
* 
* Decode the bar code with default setting
decode_bar_code_rectangle2 (Image, BarCodeHandle, CodeTypes, DecodeRectRow, DecodeRectColumn, DecodeRectPhi, DecodeRectLength1, DecodeRectLength2, DecodedDataStrings)
get_bar_code_object (SymbolRegions, BarCodeHandle, 'all', 'symbol_regions')
* 
* Allow variable element sizes ('element_size_variable' = 'true')
decode_bar_code_rectangle2 (Image, BarCodeHandleVarSize, CodeTypes, DecodeRectRow, DecodeRectColumn, DecodeRectPhi, DecodeRectLength1, DecodeRectLength2, DecodedDataStringsVarSize)
get_bar_code_object (SymbolRegionsVarSize, BarCodeHandleVarSize, 'all', 'symbol_regions')
* 
* Display results
Message := 'If the bar code is not deformed, it is found with default settings.'
Message[1] := 'Setting \'element_size_variable\' to \'true\' is not necessary.'
display_results (Image, SymbolRegions, SymbolRegionsVarSize, WindowHandle, DecodedDataStrings, DecodedDataStringsVarSize, Message)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Part 2
* Read distorted bar code
* 
read_image (Image, 'barcode/gs1databar_limited/gs1databar_limited_cylinder')
* 
* Use default setting
decode_bar_code_rectangle2 (Image, BarCodeHandle, CodeTypes, DecodeRectRow, DecodeRectColumn, DecodeRectPhi, DecodeRectLength1, DecodeRectLength2, DecodedDataStrings)
get_bar_code_object (SymbolRegions, BarCodeHandle, 'all', 'symbol_regions')
* Use 'element_size_variable' = 'true'
decode_bar_code_rectangle2 (Image, BarCodeHandleVarSize, CodeTypes, DecodeRectRow, DecodeRectColumn, DecodeRectPhi, DecodeRectLength1, DecodeRectLength2, DecodedDataStringsVarSize)
get_bar_code_object (SymbolRegionsVarSize, BarCodeHandleVarSize, 'all', 'symbol_regions')
* 
* Display results
Message := 'If the bar code is bended, the code will only be read with'
Message[1] := '\'element_size_variable\' set to \'true\'.'
display_results (Image, SymbolRegions, SymbolRegionsVarSize, WindowHandle, DecodedDataStrings, DecodedDataStringsVarSize, Message)

Halcon 自带案例4(设置条码扫描线)

在这里插入图片描述

设置扫描线set_bar_code_param (BarCodeHandle, ‘majority_voting’, MajorityVotingSetting)
当MajorityVotingSetting为false的情况在这里插入图片描述
当MajorityVotingSetting为true的情况在这里插入图片描述

* This example program shows the effect of the bar code
* parameter 'majority_voting'.
* 
* The bar code reader analyses multiple scanlines and tries
* to decode them. By default, this process is terminated as soon
* as one scanline can be decoded successfully. In some cases,
* the result derived from this scanline may be wrong due to
* local printing errors.
* 
* If the parameter 'majority_voting' is set to 'true', all
* scanlines are analysed. The final reading result is then
* determined by a majority voting of all successful decoding
* results.
* 
* Prepare visualization settings and objects
dev_update_off ()
dev_close_window ()
read_image (Image, 'barcode/ean13/ean13_label')
get_image_size (Image, WidthI, HeightI)
dev_open_window_fit_image (Image, 0, 0, 600, 500, WindowHandle)
dev_display (Image)
dev_set_draw ('margin')
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
get_window_extents (WindowHandle, Row, Column, Width, Height)
WindowZoomFactor := real(WidthI) / Width
dev_open_window (0, Width + 5, 400, 300, 'white', WindowHandleText)
set_display_font (WindowHandleText, 14, 'mono', 'true', 'false')
* 
* Create bar code reader model
create_bar_code_model ([], [], BarCodeHandle)
* 
* PART I, read bar code without majority voting
MajorityVotingSetting := 'false'
set_bar_code_param (BarCodeHandle, 'majority_voting', MajorityVotingSetting)
* 持久性模型设置
set_bar_code_param (BarCodeHandle, 'persistence', 1)
* 定义条码阈值
set_bar_code_param (BarCodeHandle, 'meas_thresh', 0.1)
* 防止'meas_thresh'参数出现错误检测
set_bar_code_param (BarCodeHandle, 'meas_thresh_abs', 30)
* 
* Perform decoding and prepare results
dev_set_window (WindowHandle)
* 直接扫描所提供的区域以寻找条形码
decode_bar_code_rectangle2 (Image, BarCodeHandle, 'EAN-13', 280, 223, 3.14125 / 2.0, 200, 50, DecodedDataStrings)
*得到解码区域
get_bar_code_object (SymbolRegion, BarCodeHandle, 'all', 'symbol_regions')
*得到解码类型
get_bar_code_result (BarCodeHandle, 'all', 'decoded_types', DecodedTypes)
*得到解析条码的字符串结果
get_bar_code_result (BarCodeHandle, 'all', 'decoded_strings', DecodedData)
*访问在条码符号搜索或解码过程中创建的标志性对象
get_bar_code_object (ValidScanlines, BarCodeHandle, 'all', 'scanlines_valid')
get_majority_voting_example_symbols (SymbolRegion, ValidScanlines, DecodedData, BarCodeHandle, DecodedTypes, DecodedData)
* 选中某一个连通域
select_obj (ValidScanlines, FirstScanline, 5)
* 
* Display results and labels
disp_message (WindowHandle, ['Looking for bar codes','\'majority_voting\' = \'' + MajorityVotingSetting + '\''], 'window', 12, 12, 'black', 'true')
ColorsText := ['forest green','red']
dev_set_line_width (2)
smallest_rectangle1 (SymbolRegion, Row1, Column1, Row2, Column2)
dev_set_color ('red')
dev_display (SymbolRegion)
dev_display (FirstScanline)
* 
Message := ['Codetype: ','Data:     '] + [DecodedTypes,DecodedData]
disp_message (WindowHandle, Message, 'image', Row1 - 40 * WindowZoomFactor, Column2 - 100, ColorsText[1], 'true')
* 
* Display description
Message := 'By default \'majority_voting\' is set to \'false\'.'
Message[1] := ' '
Message[2] := 'If the parameter \'majority_voting\' is set to \'false\', the reading result is set to the decoding result of the first scanline that could be decoded.'
Message[3] := ' '
Message[4] := 'Here, an \'EAN-13\' code is detected wrongly inside of another \'EAN-13\' because of a printing error.'
MessageWrapped := regexp_replace(Message + ' ',['(.{0,35})\\s','replace_all'],'$1\n')
disp_message (WindowHandleText, MessageWrapped, 'window', 12, 12, 'black', 'false')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* PART II, enable majority voting
* 
MajorityVotingSetting := 'true'
set_bar_code_param (BarCodeHandle, 'majority_voting', MajorityVotingSetting)
* 
* Perform decoding and prepare results
decode_bar_code_rectangle2 (Image, BarCodeHandle, 'EAN-13', 280, 223, 3.14125 / 2.0, 200, 50, DecodedDataStrings)
get_bar_code_object (SymbolRegion, BarCodeHandle, 'all', 'symbol_regions')
get_bar_code_result (BarCodeHandle, 'all', 'decoded_types', DecodedTypes)
get_bar_code_result (BarCodeHandle, 'all', 'decoded_strings', DecodedData)
get_bar_code_object (ValidScanlines, BarCodeHandle, 'all', 'scanlines_valid')
* 选取 1-4,6,7根线
select_obj (ValidScanlines, MajorityScanlines, [[1:4],6,7])
* 
* Display results and labels
dev_display (Image)
disp_message (WindowHandle, ['Looking for bar codes','\'majority_voting\' = \'' + MajorityVotingSetting + '\''], 'window', 12, 12, 'black', 'true')
dev_set_draw ('margin')
dev_set_color ('green')
dev_set_line_width (2)
smallest_rectangle1 (SymbolRegion, Row1, Column1, Row2, Column2)
dev_display (SymbolRegion)
dev_display (MajorityScanlines)
Message := ['Codetype: ','Data:     '] + [DecodedTypes,DecodedData]
disp_message (WindowHandle, Message, 'image', Row1 - 40 * WindowZoomFactor, Column2 - 100, 'forest green', 'true')
* 
* Display description
dev_set_window (WindowHandleText)
Message := 'If majority voting is enabled, the bar code reader uses a majority voting scheme to determine the reading results. It returns the result that has been decoded from the majority of all scanlines.'
Message[1] := ' '
Message[2] := 'Here, the correct \'EAN-13\' code is found.'
MessageWrapped := regexp_replace(Message + ' ',['(.{0,35})\\s','replace_all'],'$1\n')
dev_clear_window ()
disp_message (WindowHandleText, MessageWrapped, 'window', 12, 12, 'black', 'false')

Halcon 自带案例5(一维码阈值)

在这里插入图片描述

通过改变set_bar_code_param (BarCodeHandle, ‘meas_thresh_abs’, MeasThreshAbsValue) 的阈值来提高识别的准确度

* Example program for the usage of the bar code parameter
* 'meas_thresh_abs'.
* This parameter can be used to reduce the number of false
* positives when finding bar code symbol regions which we expect
* to have a high contrast. To artificially demonstrate this we
* try to find the bar code type PharmaCode that has no check
* character and therefore is recognized very easily within
* noise. As 'noise' we use images that do not contain any bar
* codes at all.
* By using 'meas_thresh_abs' with a value greater than 0.0 we
* force the bar code reader to use only the parts of a scanline
* with an absolute contrast of at least that value and thus
* reduce the number of false positives.
* 
* Create bar code reader model
create_bar_code_model ([], [], BarCodeHandle)
* 
* Initialization
dev_update_var ('off')
dev_update_pc ('off')
dev_update_window ('off')
dev_close_window ()
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
dev_set_draw ('margin')
dev_set_line_width (3)
* 
* Read and display example images without any visible bar codes
ExampleImages := ['zeiss1','patras','fabrik']
for Index := 0 to |ExampleImages| - 1 by 1
    FileName := ExampleImages[Index]
    read_image (Image, FileName)
    rgb1_to_gray (Image, Image)
    * 
    * Set display defaults
    get_image_size (Image, Width, Height)
    dev_set_window_extents (-1, -1, Width, Height)
    dev_display (Image)
    * 
    * First, disable absolute thresholds by setting the value 0.0
    * for the parameter 'meas_thresh_abs'
    MeasThreshAbsValue := 0.0
    set_bar_code_param (BarCodeHandle, 'meas_thresh_abs', MeasThreshAbsValue)
    * 
    * The bar code reader finds many (wrong) potential bar codes using
    * scanlines that have a low absolute contrast
    find_bar_code (Image, SymbolRegions, BarCodeHandle, 'PharmaCode', DecodedDataStrings)
    dev_set_color ('red')
    dev_display (SymbolRegions)
    disp_message (WindowHandle, ['Found ' + |DecodedDataStrings| + ' potential bar codes','  with parameter meas_thresh_abs = ' + MeasThreshAbsValue], 'window', 12, 12, '', 'true')
    disp_continue_message (WindowHandle, 'black', 'true')
    stop ()
    * 
    * Now, set the bar code reader parameter 'meas_thresh_abs' to a value
    * greater than 0.0 to use only parts of a scanline having an absolute
    * contrast of at least that value.
    MeasThreshAbsValue := 10.0
    set_bar_code_param (BarCodeHandle, 'meas_thresh_abs', MeasThreshAbsValue)
    * 
    * Look again for a bar code. Now, significant less scanlines should be found.
    find_bar_code (Image, SymbolRegions, BarCodeHandle, 'PharmaCode', DecodedDataStrings)
    dev_set_color ('lime green')
    dev_display (SymbolRegions)
    disp_message (WindowHandle, ['Found ' + |DecodedDataStrings| + ' potential bar codes','  with parameter meas_thresh_abs = ' + MeasThreshAbsValue], 'window', 5 * 12, 12, '', 'true')
    disp_continue_message (WindowHandle, 'black', 'true')
    stop ()
endfor

阈值为0
在这里插入图片描述阈值为10
在这里插入图片描述

Halcon Codabar编码案例

在这里插入图片描述

find_bar_code (Image, SymbolRegions, BarCodeHandle, ‘Codabar’, DecodedDataStrings)

* Read bar codes of type Codabar
* 
create_bar_code_model ([], [], BarCodeHandle)
* We expect to decode a single bar code per image
set_bar_code_param (BarCodeHandle, 'stop_after_result_num', 1)
dev_close_window ()
dev_open_window (0, 0, 120, 300, 'black', WindowHandle)
dev_set_color ('green')
dev_set_draw ('margin')
dev_set_line_width (3)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
for I := 1 to 6 by 1
    read_image (Image, 'barcode/codabar/codabar' + (I$'.2'))
    get_image_size (Image, Width, Height)
    dev_set_window_extents (0, 0, Width - 1, Height - 1)
    dev_display (Image)
    set_bar_code_param (BarCodeHandle, 'check_char', 'present')
    find_bar_code (Image, SymbolRegions, BarCodeHandle, 'Codabar', DecodedDataStrings)
    disp_message (WindowHandle, DecodedDataStrings, 'window', 12, 12, 'black', 'false')
    LastChar := strlen(DecodedDataStrings) - 1
    disp_message (WindowHandle, DecodedDataStrings{0} + sum(gen_tuple_const(LastChar - 1,' ')) + DecodedDataStrings{LastChar}, 'window', 12, 12, 'forest green', 'false')
    if (I < 6)
        stop ()
    endif
endfor

Halcon Code128编码案例

在这里插入图片描述

find_bar_code (Image, SymbolRegions, BarCodeHandle, ‘Code 128’, DecodedDataStrings) 改变的参数

* Read bar codes of type Code 128
* 
create_bar_code_model ([], [], BarCodeHandle)
dev_close_window ()
dev_open_window (0, 0, 600, 600, 'black', WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_draw ('margin')
dev_set_color ('green')
dev_set_line_width (3)
for I := 1 to 3 by 1
    read_image (Image, 'barcode/code128/code128' + (I$'.2'))
    dev_resize_window_fit_image (Image, 0, 0, -1, -1)
    find_bar_code (Image, SymbolRegions, BarCodeHandle, 'Code 128', DecodedDataStrings)
    get_bar_code_result (BarCodeHandle, 0, 'decoded_reference', Reference)
    String := ''
    for J := 0 to strlen(DecodedDataStrings) - 1 by 1
        if (ord(DecodedDataStrings{J}) < 32)
            Char := '\\x' + ord(DecodedDataStrings{J})$'02x'
        else
            Char := DecodedDataStrings{J}
        endif
        String := String + Char
    endfor
    disp_message (WindowHandle, String, 'window', 12, 12, 'black', 'true')
    if (I < 3)
        disp_continue_message (WindowHandle, 'black', 'true')
        stop ()
    endif
endfor

Halcon 符合编码案例

在这里插入图片描述

set_bar_code_param (BarCodeHandle, ‘composite_code’, ‘CC-A/B’) 设置为复合码

* 
* This program demonstrates the decoding of GS1 DataBar bar
* codes with Composite component
* 
dev_close_window ()
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
* 
ScaleWindow := 1.0
* 
dev_set_draw ('margin')
dev_set_color ('green')
dev_set_line_width (3)
* 
create_bar_code_model ([], [], BarCodeHandle)
set_bar_code_param (BarCodeHandle, 'composite_code', 'CC-A/B')
* 
set_bar_code_param (BarCodeHandle, 'element_size_min', 1.5)
* 
TestParams := []
TestParams := [TestParams,'gs1databar_stacked_composite_01','GS1 DataBar Stacked']
TestParams := [TestParams,'gs1databar_limited_composite_01','GS1 DataBar Limited']
TestParams := [TestParams,'gs1databar_limited_composite_02','GS1 DataBar Limited']
TestParams := [TestParams,'gs1databar_expanded_composite_01','GS1 DataBar Expanded']
* 
* 
for I := 0 to |TestParams| - 2 by 2
    File := 'barcode/gs1databar_composite/' + TestParams[I]
    CodeType := TestParams[I + 1]
    * 
    read_image (Image, File)
    get_image_size (Image, Width, Height)
    dev_set_window_extents (0, 0, ScaleWindow * Width, ScaleWindow * Height)
    disp_message (WindowHandle, 'Barcode Type: ' + CodeType, 'window', 12, 12, 'black', 'true')
    * 
    find_bar_code (Image, SymbolRegions, BarCodeHandle, CodeType, DecodedDataStrings)
    * 
    get_bar_code_result (BarCodeHandle, 'all', 'decoded_strings', DecodedStrings)
    get_bar_code_result (BarCodeHandle, 'all', 'composite_strings', CompositeStrings)
    disp_message (WindowHandle, DecodedStrings + '\nComposite: ' + CompositeStrings, 'image', 36, 12, 'black', 'true')
    if (I < |TestParams| - 2)
        disp_continue_message (WindowHandle, 'black', 'true')
        stop ()
    endif
endfor

Halcon 当条码被遮挡的情况下

在这里插入图片描述在这里插入图片描述

* 
* This program demonstrates visualization of bar code scanlines.
* This visualization can be used to inspect the quality of images, where
* occlusions or print defects might prevent the bar code reader from
* successfully decoding the underlying bar code.
* 
* With 'scanlines_all' all scanlines that the bar code reader would
* eventually use to decode a  candidate bar code (here, colored in red).
* With 'scanlines_valid' are visualized all scanlines that can be decoded
* as well (here, colored in green)
* 
dev_update_off ()
dev_close_window ()
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_draw ('margin')
* 
Files := ['ean1314','ean1313','ean13_defect_05']
Color := ['magenta','red','green','yellow']
* 
create_bar_code_model ([], [], BarCodeHandle)
set_bar_code_param (BarCodeHandle, 'persistence', 1)
* 
for I := 0 to |Files| - 1 by 1
    Filename := 'barcode/ean13/' + Files[I]
    * 
    read_image (Image, Filename)
    get_image_size (Image, Width, Height)
    dev_set_window_extents (0, 0, Width, Height)
    dev_display (Image)
    * 
    find_bar_code (Image, SymbolRegions, BarCodeHandle, 'EAN-13', DecodedDataStrings)
    * Display only scanlines of the decoded candidate region.
    if (|DecodedDataStrings|)
        CandidateIds := [0:|DecodedDataStrings| - 1]
    else
        CandidateIds := 'all'
    endif
    * 
    get_bar_code_object (Candidates, BarCodeHandle, CandidateIds, 'candidate_regions')
    dev_set_line_width (4)
    dev_set_color (Color[0])
    dev_display (Candidates)
    * 获取所有扫描线对象(红色)
    get_bar_code_object (AllScanlines, BarCodeHandle, CandidateIds, 'scanlines_all')
    dev_set_color (Color[1])
    dev_display (AllScanlines)
    * 获取有效的扫描线对象(绿色)
    get_bar_code_object (ValidScanlines, BarCodeHandle, CandidateIds, 'scanlines_valid')
    dev_set_line_width (2)
    dev_set_color (Color[2])
    dev_display (ValidScanlines)
    * 获取边缘的扫描线对象(黄色)
    get_bar_code_object (MergedScanlines, BarCodeHandle, CandidateIds, 'scanlines_merged_edges')
    dev_set_color (Color[3])
    dev_display (MergedScanlines)
    * 
    disp_message (WindowHandle, 'Decoded data string: ' + DecodedDataStrings, 'window', 12, 12, 'black', 'true')
    disp_message (WindowHandle, ['Candidate region','Extracted scanlines','Valid scanlines','Edges used for merging'], 'window', 42, 12, Color, ['black','false'])
    if (I < |Files| - 1)
        disp_continue_message (WindowHandle, 'black', 'true')
        stop ()
    endif
endfor

在这里插入图片描述

主要代码

* 获取候选条形码区域的对象
    get_bar_code_object (Candidates, BarCodeHandle, CandidateIds, 'candidate_regions')
    dev_set_line_width (4)
    dev_set_color (Color[0])
    dev_display (Candidates)
    * 获取所有扫描线对象(红色)
    get_bar_code_object (AllScanlines, BarCodeHandle, CandidateIds, 'scanlines_all')
    dev_set_color (Color[1])
    dev_display (AllScanlines)
    * 获取有效的扫描线对象(绿色)
    get_bar_code_object (ValidScanlines, BarCodeHandle, CandidateIds, 'scanlines_valid')
    dev_set_line_width (2)
    dev_set_color (Color[2])
    dev_display (ValidScanlines)
    * 获取边缘的扫描线对象(黄色)
    get_bar_code_object (MergedScanlines, BarCodeHandle, CandidateIds, 'scanlines_merged_edges')
    dev_set_color (Color[3])
    dev_display (MergedScanlines) 

Halcon 检测条码绘制条码矩形 decode_bar_code_rectangle2

* This example demonstrates how to use the operator
* decode_bar_code_rectangle2.
* The bar code region is extracted by simple segmentation
* and the returned rectangle2 parameters are passed to
* the operator decode_bar_code_rectangle2.
* 
* Initialize variables
Directory := 'barcode/ean13/'
TeaBoxRegExp := '.*tea_box.*'
* 
* Initialize settings
dev_update_window ('off')
dev_set_draw ('margin')
* 
* Get list of tea_box*-image files
list_image_files (Directory, 'default', [], ImageFiles)
ImageFilesTea := regexp_select(ImageFiles,[TeaBoxRegExp,'ignore_case'])
read_image (Image, ImageFilesTea[0])
* 
* Prepare graphics window and bar code model
dev_close_window ()
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
dev_set_line_width (2)
create_bar_code_model ([], [], BarCodeHandle)
* 
* Decode tea_box*-images
for ImageIndex := 0 to |ImageFilesTea| - 1 by 1
    read_image (Image, ImageFilesTea[ImageIndex])
    dev_display (Image)
    * 
    * segment and determine the bar code region
    threshold (Image, RegionThresh, 56, 255)
    connection (RegionThresh, RegThreshConn)
    select_shape_std (RegThreshConn, RegionBC, 'max_area', 100)
    * 
    * create input parameters for decode_bar_code_rectangle2
    smallest_rectangle2 (RegionBC, Row, Column, Phi, Length1, Length2)
    gen_rectangle2 (Rectangle2BC, Row, Column, Phi, Length1, Length2)
    dev_set_color ('magenta')
    dev_display (Rectangle2BC)
    * 
    * decode_bar_code_rectangle2 directly uses the passed rectangle2 parameters as ROI
    decode_bar_code_rectangle2 (Image, BarCodeHandle, 'EAN-13', Row, Column, Phi, Length1, Length2, Decoded)
    get_bar_code_object (SymbolRegions, BarCodeHandle, 'all', 'symbol_regions')
    dev_set_color ('lime green')
    dev_display (SymbolRegions)
    disp_message (WindowHandle, 'Found bar code: ' + Decoded, 'window', 5, 5, 'black', 'true')
    if (ImageIndex < |ImageFilesTea| - 1)
        disp_continue_message (WindowHandle, 'black', 'true')
        stop ()
    endif
endfor

在这里插入图片描述

halcon 设置条码的高度和宽度案例

* This example demonstrates how to use the bar code parameters
* 'barcode_height_min' and 'barcode_width_min' to narrow the
* number of detected candidate regions in which possible bar
* codes are searched for.
* 
* This is especially recommended if some factors like the bar code
* type, the number of encoded characters etc. are constant
* throughout the application. Then, the manual adjustment of
* these parameters can lead to an increasing speed and robustness.
* 
* To illustrate the effect of the parameters, the detected
* candidate regions are displayed before and after setting
* each of the parameters. It is shown that the number of
* potential candidate region decreases when the parameters
* are manually adjusted.
* ****************************************************************
* 
* Initialization
dev_update_off ()
dev_close_window ()
read_image (Image, 'barcode/code39/code3906')
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_draw ('margin')
dev_set_color ('green')
* 
MinWidth := 280
MinHeight := 60
* 
* Display a description
Message := 'This example demonstrates how to use the bar code'
Message[1] := 'parameters \'barcode_height_min\' and \'barcode_width_min\''
Message[2] := 'to narrow the number of detected candidate regions in'
Message[3] := 'which the bar codes are searched for.'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Create a bar code model
create_bar_code_model ([], [], BarCodeHandle)
* 
* Adjust the minimal widths of the bar code elements
* and find the bar code
find_bar_code (Image, SymbolRegions, BarCodeHandle, 'Code 39', DecodedDataStrings)
* 
* Get all candidate regions
get_bar_code_object (BarCodeObjects, BarCodeHandle, 'all', 'candidate_regions')
* 
* Display all candidate regions
dev_set_colored (12)
dev_display (Image)
dev_display (BarCodeObjects)
Message := 'Candidate regions with default settings'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
Message := 'Adjusting the parameters \'barcode_width_min\' and'
Message[1] := '\'barcode_height_min\' to decrease the number of'
Message[2] := 'found candidate regions and thus to increase the'
Message[3] := 'robustness of the application.'
disp_message (WindowHandle, Message, 'window', 40, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Minimal bar code width
* -----------------------------
* Set the minimal bar code width and search for bar codes again
set_bar_code_param (BarCodeHandle, 'barcode_width_min', MinWidth)
find_bar_code (Image, SymbolRegions, BarCodeHandle, 'Code 39', DecodedDataStrings)
* 
* Get all candidate regions
get_bar_code_object (BarCodeObjects, BarCodeHandle, 'all', 'candidate_regions')
* 
* Display the results
dev_display (Image)
dev_display (BarCodeObjects)
Message := 'Candidate regions with adjusted parameter:'
Message[1] := '  \'barcode_width_min\' = ' + MinWidth
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Minimal bar code height
* -------------------------
* Set the minimal bar code height and search for bar codes again
set_bar_code_param (BarCodeHandle, 'barcode_height_min', MinHeight)
find_bar_code (Image, SymbolRegions, BarCodeHandle, 'Code 39', DecodedDataStrings)
* 
* Get all candidate regions
get_bar_code_object (BarCodeObjects, BarCodeHandle, 'all', 'candidate_regions')
* 
* Display the results
dev_display (Image)
dev_display (BarCodeObjects)
Message := 'Candidate region with adjusted parameters:'
Message[1] := '  \'barcode_width_min\'  = ' + MinWidth
Message[2] := '  \'barcode_height_min\' =  ' + MinHeight
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* Display the symbol region and the decoded string
dev_display (Image)
dev_set_color ('red')
dev_display (BarCodeObjects)
dev_set_color ('lime green')
dev_display (SymbolRegions)
disp_message (WindowHandle, 'Search with adjusted parameters', 'window', 12, 12, 'black', 'true')
disp_message (WindowHandle, 'Decoded string: ' + DecodedDataStrings, 'window', 40, 12, 'black', 'true')
disp_message (WindowHandle, ['Candidate regions','Symbol region'], 'window', 170, 12, ['red','lime green'], 'true')

没有设置set_bar_code_param (BarCodeHandle, ‘barcode_height_min’, MinHeight) 的情况下
在这里插入图片描述> 设置之后对条码的识别
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/240646.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux---Ubuntu操作系统

1. Ubuntu操作系统的介绍 Ubuntu操作系统是属于Linux操作系统中的一种&#xff0c;它是免费、稳定又可以拥有绚丽界面的一个操作系统 2. Ubuntu图形界面的介绍 任务栏 窗口操作按钮 窗口菜单条 任务栏效果图: 窗口操作按钮效果图: 窗口菜单条效果图: 3. 与Windows目录结…

『C++成长记』拷贝构造函数

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;C &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、拷贝构造函数 &#x1f4d2;1.1拷贝构造函数的概念 &#x1f4d2;1.2拷贝构造…

Java项目-瑞吉外卖Day6

导入用户地址功能&#xff0c;为用户添加地址&#xff1a; 添加AddressBook实体类&#xff0c;创建相关service&#xff0c;mapper&#xff0c;serviceImpl&#xff0c;controller类。 controller类直接使用的资料提供的代码。 实现菜品展示移动端开发&#xff1a; 看到前端发…

添加,更换和删除 vSphere License

目录 1. 删除 License2. 添加 License&#xff08;1&#xff09;输入许可证密钥&#xff08;2&#xff09;编辑许可证名称&#xff08;3&#xff09;确认许可证信息 3. 分配/更换 License&#xff08;1&#xff09;为 vCenter Server 分配 License&#xff08;2&#xff09;为 …

Android : 序列化 Parcelable 简单应用

1.Parcelable 介绍 Parcelable 是 Android 提供的一个序列化接口&#xff0c;用于将数据写入 Parcel&#xff0c;以及从 Parcel 中读取数据。一个类只要实现了这个接口&#xff0c;该类的对象就可以被序列化&#xff0c;主要用于 IPC&#xff08;进程间通信&#xff09;、Bind…

产品经理之如何编写竞品分析(医疗HIS系统管理详细案例模板)

目录 一.项目周期 二.竞品分析的目的 三.竞品分析包含的维度 四.如何选择竞品 五.竞品画布 六.案例模板 一.项目周期 在整个项目的周期&#xff0c;产品经理所做的事情主要在项目前期做市场分析、需求调研等&#xff0c;下面一张图概况了整个项目周期产品经理、开发工程师…

网络安全——Iptables防DDoS攻击实验

一、实验目的要求&#xff1a; 二、实验设备与环境&#xff1a; 三、实验原理&#xff1a; 四、实验步骤&#xff1a; 五、实验现象、结果记录及整理&#xff1a; 六、分析讨论与思考题解答&#xff1a; 一、实验目的要求&#xff1a; 1、掌握常见DDoS攻击SYN Flood的攻击…

gdb本地调试版本移植至ARM-Linux系统

移植ncurses库 本文使用的ncurses版本为ncurses-5.9.tar.gz 下载地址&#xff1a;https://ftp.gnu.org/gnu/ncurses/ncurses-5.9.tar.gz 1. 将ncurses压缩包拷贝至Linux主机或使用wget命令下载并解压 tar-zxvf ncurses-5.9.tar.gz 2. 解压后进入到ncurses-5.9目录…

解决员工安全隐患的终极方案!迅软DSE答疑员工终端安全管控策略揭秘!

企业终端安全管控对于企事业单位来说至关重要。迅软DSE终端安全系统提供了丰富的终端安全桌面管理策略&#xff0c;可以对终端用户的上网行为和终端操作行为进行管理和控制&#xff0c;从而实现桌面终端的标准化管理&#xff0c;解决终端安全管理问题&#xff0c;并提高员工工作…

阿里云SLB的使用总结

一、什么是SLB 实现k8s的服务service的一种推荐方式&#xff0c;也是服务上云后&#xff0c;替代LVS的一个必选产品。 那么它有什么作用呢&#xff1f; 1、负载均衡&#xff0c;是它与生俱来的。可以配置多个服务器组&#xff1a;包括虚拟服务器组、默认服务器组、主备服务器…

小程序使用Nodejs作为服务端,Nodejs与与MYSQL数据库相连

小程序使用Nodejs作为服务端,Nodejs与与MYSQL数据库相连 一、搭建环境二、配置Nodejs三、与小程序交互四、跨域处理/报错处理五、nodejs连接mysql数据库六、微信小程序连接nodejs报错七、小程序成功与服务端相连,且能操作数据库一、搭建环境 新建空文件夹:Win + R进入cmd命令…

C++STL的list模拟实现

文章目录 前言 list实现push_back迭代器(重点)普通迭代器const迭代器 inserterase析构函数构造函数拷贝构造赋值 vector和list的区别 前言 要实现STL的list, 首先我们还得看一下list的源码。 我们看到这么一个东西&#xff0c;我们知道C兼容C&#xff0c;可以用struct来创建一…

Quartus II + Modelsim 脚本仿真

软件版本&#xff1a;Intel Quartus Prime Design Suite: 23.2 方式参考附件Intel 官方文档&#xff1a;Questa*-Intel FPGA Edition Quick-Start: Intel Quartus Prime Pro Edition 第1步&#xff0c;创建一个ram ip&#xff0c;并形成一个例化的top层ip 第2步&#xff0c;自…

独立完成软件的功能的测试(2)

独立完成软件的功能的测试&#xff08;2&#xff09; &#xff08;12.13&#xff09; 1. 对穷举场景设计测试点&#xff08;等价类划分法&#xff09; 等价类划分法的概念&#xff1a; 说明&#xff1a;数据有共同特征&#xff0c;成功失败分类&#xff1a; 有效&#xff1a…

FPGA使用乘法的方式

FPGA使用乘法的方式 方法一:直接使用乘法符“*” 源代码 module multiply(input [7:0] a,input [7:0] b,output wire [15:0] result);(*use_dsp48 = "yes"*) wire [15:0] result;assign result = a*b; endmodule仿真代码 module multiply_tb();reg [7:0] a; re…

大象慧云:从设立分部到迁移总部 与贵阳贵安共筑税务数字化未来

近年来&#xff0c;贵阳贵安着力提升政务服务水平&#xff0c;通过擦亮“贵人服务”品牌&#xff0c;持续优化营商环境。在这样的环境下&#xff0c;再加上“大数据基因”&#xff0c;对于希望在大数据领域大展拳脚的企业来说&#xff0c;贵阳贵安无疑成为了一个极具吸引力的选…

MySQL笔记-第11章_数据处理之增删改

视频链接&#xff1a;【MySQL数据库入门到大牛&#xff0c;mysql安装到优化&#xff0c;百科全书级&#xff0c;全网天花板】 文章目录 第11章_数据处理之增删改1. 插入数据1.1 实际问题1.2 方式1&#xff1a;VALUES的方式添加1.3 方式2&#xff1a;将查询结果插入到表中 2. 更…

C语言—每日选择题—Day46

第一题 1. 下列程序段的输出结果是&#xff08;&#xff09; #include <stdio.h> int main() {int x 1,a 0,b 0;switch(x) {case 0: b;case 1: a;case 2: a;b;}printf("a%d,b%d\n", a, b);return 0; } A&#xff1a;a2,b1 B&#xff1a;a1,b1 C&#xf…

CGAL的3D Alpha Wrapping

1、介绍 几何建模和处理中的各种任务都需要将三维对象表示为有效的曲面网格&#xff0c;其中“有效”指的是不透水、无交叉、可定向和2流形的网格。这样的表示提供了内部/外部和测地线邻域的定义良好的概念。 3D数据通常是通过测量和重建获得的&#xff0c;由人类设计&#xff…

深入理解网络 I/O 多路复用:Epoll

&#x1f52d; 嗨&#xff0c;您好 &#x1f44b; 我是 vnjohn&#xff0c;在互联网企业担任 Java 开发&#xff0c;CSDN 优质创作者 &#x1f4d6; 推荐专栏&#xff1a;Spring、MySQL、Nacos、Java&#xff0c;后续其他专栏会持续优化更新迭代 &#x1f332;文章所在专栏&…