create_bar_code_model创建条形码模型。返回的句柄提供有关条形码结构的所有必要信息。
find_bar_code读取条形码。可以指定要搜索的模型和条形码类型。返回指定类型的所有条码区域和解码字符串。
clear_bar_code_model销毁条码模型。
读取下图所示的EAN 13条形码。
create_bar_code_model创建条形码模型。find_bar_code(CodeType设置为'EAN-13')返回找到的条形码的区域和解码的字符串。clear_bar_code_model销毁条形码模型。
read_image (image, 'barcode/ean13/ean1301') create_bar_code_model ([], [], BarCodeHandle) find_bar_code (image, SymbolRegions, BarCodeHandle, 'EAN-13', DecodedDataStrings) clear_bar_code_model (BarCodeHandle) |
16.1.1 预处理图像
如果条形码图像有点模糊,则可以使用emphasize来增强图像的高频区域,从而使其看起来更清晰。
zoom_image_factor放大了太小而无法读取的条形码。
scale_image缩放灰度值范围(或使用外部程序scale_image_range),可以增强图像的对比度。
HALCON希望条形码在浅色背景上打印为深色。要在深色背景上读取浅色条形码,必须先使用操作符invert_image反转图像。
16.1.2 校正图像
条形码阅读器可以在一定程度上处理透视变形。对于非常强烈的失真,需要在应用条形码阅读器之前纠正图像。
CD上环形打印的条形码进行校正,示例程序circular_barcode.hdev。
16.1.3 创建条码模型
可以调整参数(如元素大小的范围)('element_size_min','element_size_max'),以获得更好的结果。可以在此处更改所有可用参数,也可以在稍后的步骤中使用set_bar_code_param更改。
16.1.4 配置条码模型参数
在大多数情况下,使用HALCON读取条形码不需要调整参数。但是,如果条形码读取失败,则可以在应用find_bar_code之前使用算子set_bar_code_param调整以下参数。
(1) 调整条形码与元素大小
可以使用参数调整条形码大小和条形码元素宽度的范围
• ’barcode_width_min’,
• ’barcode_height_min’,
• ’element_size_min’,
• ’element_size_max’
barcode_typical_cases.hdev显示了元素大小的调整如何改善解码率。
(2) 确定校验字符
对于具有校验字符的码类型,可以指定校验字符是用于检测结果还是作为已解码字符串的一部分返回。('check_char')
(3) 调整提取元素边缘的阈值
两个阈值参数控制扫描线识别条码边缘。'meas_thresh'为一个相对阈值,一般取值[0.05 , 0.2]。除非图像包含大量噪音,否则'meas_thresh'效果很好。当灰度值范围较小时,可能会检测到错误边缘。
'meas_thresh_abs'为所有图像设置了5.0的绝对阈值。这意味着元素边界的最亮和最暗值之间的差异必须大于5.0才能被归类为边缘。因此,在具有小动态范围的图像中不会检测到错误边缘。有时需要设置为低阈值,例如,当照明不均匀,图像即具有高动态范围也具有低动态范围。需要在减小'meas_thresh'的值之前将'meas_thresh_abs'设置为0.0。
(4) 加速
有两种情况可以改善性能。
第一种情况,每个错误候选者使用默认值10扫描线扫描,而有效条形码本身通常在一次或两次扫描后被解码。因此,减少扫描线的数量会明显加速。请注意,如果在减少扫描线数量后无法检测到条形码,则必须再次增加该数量。
第二种情况涉及带有堆叠条形码的图像(目前是RSS-14 Stacked,RSS-14 Stacked Omnidirectional和RSS Expanded Stacked)。阅读器默认的扫描线数量,RSS-14 Stacked为20,RSS Expanded Stacked为55,可能高于必要值。RSS Expanded Stacked码可能没有最大的扫描数,则使用参数'num_scanlines'指定扫描行数很有用(阅读器每行使用5条扫描线)。因此,性能提高了。示例barcode_param_num_scanlines.hdev。
如果已知每个图像的条形码数量,则可以通过set_bar_code_param或set_bar_code_param_specific的参数’stop_after_result_num’指定该数量来减少解码时间。
(5) 提高条码检测的鲁棒性
'min_identical_scanlines'认定成功解码所需的最少扫描线数。例:barcode_param_scanning_control.hdev
如果未设置此参数,则在第一个扫描线成功解码后,条形码被视为已解码。
'majority_voting' 选择解码结果的模式。如果未设置该参数,满足上所述最小解码扫描线的数量,则成功解码条形码。如果此参数设置为“true”,在不同扫描线数之间进行选择,并且整个结果由多数扫描线解码。示例barcode_param_majority_voting.hdev。
(6) 强制检测空白区域
即使两侧空白区存在干扰,HALCON也能读取条形码。但是,参数'quiet_zone'可用于更严格地处理空白区违规(默认为false)。示例barcode_quiet_zone.hdev。
(7) 调整匹配的容忍度
'start_stop_tolerance'指定检测起始符和终止符的“容许误差”。设为’high’,容许误差大。如果图像质量好,会增加找到条码的机会;如果图像噪声大,可能会引起误检。设为’low’,容许误差小,会提高条码检测的正确性,但会降低找到条码的概率。请注意,该参数目前仅针对Code 128实现。示例barcode_param_scanning_control.hdev。
get_bar_code_param查询当前用于各个参数的值。
自动训练确定条形码参数的最佳值。可以确定的参数包括'element_size_min','element_size_max','orientation','orientation_tol','barcode_width_min','meas_thresh'和'meas_thresh_abs'。
训练模式,使用create_bar_code_model为训练创建模型,将参数设置为’ train’,选择具体的训练项名称或设置为’all’。
create_bar_code_model ('train', 'all', BarCodeHandle) get_bar_code_param (BarCodeHandle, 'train', TrainParNames) |
query_bar_code_params 设置参数 'trained_general' 及 'trained_general' 获取参数名称,get_bar_code_param 参数名称可以获得具体数值。示例barcode_training.hdev演示了如何进行训练。
find_bar_code允许在一次调用中找到一种条形码类型或多种条形码类型。读取已知的码类型时,配置’CodeType’参数。
(1) 自动识别
将“CodeType”设置为“auto”可以读取多种类型的条码。但是会增加运行时间,且可能会降低解码的可靠性。最好只扫描预知的条形码类型(见图16.2)。barcode_autodiscrimination.hdev自动识别的用法。set_bar_code_param_specific和get_bar_code_param_specific专门为某些条形码类型设置模型参数,这对于自动识别尤其有用。
图 16.2 自动识别出不同类型的条码,其结果为Code 39与EAN-13码
(2) 固定区域识别
如果条码总是出现在每个图像中的大致相同位置,则可以使用decode_bar_code_rectangle2。条码的位置以任意方向的矩形给出。需注意,方向很重要。它需要与元素垂直。
(3) 获得结果
find_bar_code读取条形码后,get_bar_code_object显式查询已解码条形码的区域或其候选区域。get_bar_code_result查询解码的字符串或配置数据(包括开始/停止字符)。
(4) 诊断状态信息
get_bar_code_result设置为'status'或'status_id'并提供候选区域句柄,每个扫描行的状态消息将在Tuple中返回(如图16.3)。get_bar_code_object的'scanlines_all'查询所有的扫描线,或'scanlines_valid'查询所有有效的扫描线。如果要进一步处理扫描线信息,可以使用'scanlines_all_plain'和'scanlines_valid_plain'。它们将检测到的扫描线作为XLD轮廓返回。请注意,只有在’persistence’模式下才能评估条形码扫描线的状态。 ’persistence’ 模式允许在条形码解码期间存储中间结果。确定状态会增加运行时间,因此只有在需要调试信息时才应执行。示例barcode_status.hdev演示了条形码参数'status'和'status-id'的使用。
图 16.3 状态消息可用于解决读取条形码时可能出现的问题
如果条形码读取失败:
(1)使用decode_bar_code_rectangle2指定位置。
(2)调整参数element_size_min或element_size_max设置为条形码的实际大小。barcode_typical_cases.hdev。读取失败的错误消息以 ‘edges’,’decoding’或’check’ 开头。这些类别表示条码在解码过程中读取失败的的状态。首先,检测条码的边缘,然后根据特定的条码类型解码代码,最后执行几个测试(’check’)以确保结果正确。
Error Message(s) |
Possible Solution |
|
edges: not enough edges detected. |
通过get_bar_code_object和get_bar_code_result查询区域和扫描线来检查区域。 |
|
edges: not enough edges for a start, a stop and at least one data character. |
||
edges: too many edges detected. |
||
edges: center of scanline not within domain. |
更改ROI或使用full_domain搜索整个图像。 如果已知条码的位置,则可以使用decode_bar_code_rectangle2来指定确切的位置。 |
|
decoding: could not find stop character. |
检查找到的条形码区域或通过设置set_bar_code_param(_specific)参数num_scanlines增加扫描线的数量 |
|
decoding: could not find start and stop characters. |
||
decoding: number of wide bars of a single character is not equal to 2. |
检查是否为find_bar_code指定了正确的码类型“CodeType” |
|
decoding: invalid encoding pattern. |
||
decoding: invalid mix of character sets. |
||
decoding: error decoding the reference to a human readable string. |
||
decoding: could not detect center guard pattern. |
||
decoding: could not detect left and/or right guard patterns. |
||
decoding: could not detect add-on guard pattern. |
||
decoding: could not detect enough finder patterns. |
||
decoding: no segment found. |
||
check: detected EAN-13 bar code type instead of specified type. |
||
check: checksum test failed. |
检查条码是否有校验和。如果没有,请将set_bar_code_param_specific的参数'check_char'设置为'absent' |
|
check: check of add-on symbol failed. |
检查条码是否有附加标签。 如果没有,请将find_bar_code的“CodeType”更改为非附加类型。 |
|
check: symbol region overlaps with another symbol region. |
跳过整个区域,因为已经解码了与该区域重叠的另一个条码区域。 这不是错误。 将set_bar_code_param或set_bar_code_param_specific的'stop_after_result_num'设置为预期条码的数量 |
|
Warning Message(s) |
Possible Solution |
|
White spaces too wide. |
提高图像质量并防止出错,请参阅示例程序barcode_typical_cases.hdev |
|
White spaces too narrow. |
||
Bars too wide. |
||
Bars too narrow. |
||
Possible saturation of gray values. |
||
No composite component found. |
检查复合码是否完全在图像中 |
|
get_bar_code_result,它根据标准ISO / IEC 15416对条码打印质量进行分级。对于简单的一维条码, 打印质量包含在Tuple以下九个元素中:
query_isoiec15416_labels查询名称和顺序。
quality_isoiec_15416_values返回一个Tuple包含以下的值:
Symbol Contrast、Minimal Reflectance、Minimal Edge Contrast、Modulation、Defects、Decodabilit
示例 barcode_typical_cases.hdev。
案例一提供了可以获得中间结果的两个状态(见图16.4)。
本地函数 disp_bar_code_candidates 显示检测到条码候选区。要查询扫描线,必须先找到候选区域。本地函数disp_bar_code_scanlines显示扫描线。两个过程都使用get_bar_code_object,分别设置参数'candidate_regions','scanlines_all'或'scanlines_valid'。
图 16.4 (a) 条码图像 (b)候选区域 (c) 有效的扫描线
案例二检测低对比度图像中的条形码(见图16.5)。首先,没有找到候选区域。但是,利用scale_image_range缩放图像的灰度值范围,简单地改善对比度。要获得缩放范围,先查看图像的灰度直方图是很有用的。
(a) (b)
(c) (d)
图 16.5 a)低对比度的条形码 b)低对比度图像的直方图
c)缩放灰度值可以解码条形码 d)灰度值的缩放直方图
案例三,图像中的光照分布不均匀(见图16.6a)。减小'meas_thresh'的值可以检测和读取整个条形码。但是,首先要将 'meas_thresh_abs'设置为0,因为'meas_thresh_abs'设置的默认阈值为5.0,在这种情况下太高了。
set_bar_code_param (BarCodeHandle, 'meas_thresh_abs', 0.0) set_bar_code_param (BarCodeHandle, 'meas_thresh', 0. |
图16.6 (a)不均匀照明下的条码 (b) 减小'meas_thresh'的值使条码可读
示例 circular_barcode.hdev
图16.7(a)显示了打印在CD上的环状条形码图像,条码阅读器不能直接读取这种条码,所以必须先对图像进行变换,使得条形码呈平行状。
图16.7 (a) 分割后的圆环图像
(b) 变换后的解码条形码
首先分割出条形码的暗环。使用threshold, closing_circle和connection来执行。此分割返回图像中的所有暗区,包括暗环。select_shape选择目标区域。
threshold (Image, Region, 0, 100) closing_circle (Region, Region, 3.5) connection (Region, ConnectedRegions) select_shape (ConnectedRegions, Ring, ['width','height'], 'and', [550,550], [750,750]) |
之后,确定外圆和内圆的参数。使用shape_trans直接确定外圆。 提取内圆比较复杂。 这里,通过创建外圆的补集,然后通过shape_trans选择内原。 使用smallest_circle,确定内圆和外圆的参数。
shape_trans (Ring, OuterCircle, 'outer_circle') complement (Ring, RegionComplement) connection (RegionComplement,ConnectedRegions) select_shape (ConnectedRegions, InnerCircle, ['width','height'], 'and',[450,450],[650,650]) smallest_circle (Ring, Row, Column, OuterRadius) smallest_circle (InnerCircle, InnerRow, InnerColumn, InnerRadius) |
内圆和外圆的参数是极坐标变换的输入(polar_trans_image_ext),它将圆环的图像转换为矩形区域。 然后,对图像取反,以获得暗背景上的亮条形码(见图16.7b)。
WidthPolar := 1440 HeightPolar := round(OuterRadius - InnerRadius - 10) polar_trans_image_ext (Image, PolarTransImage, Row, Column, rad(360), 0, \ OuterRadius - 5, InnerRadius + 5, WidthPolar, \ HeightPolar, 'bilinear') invert_image (PolarTransImage, ImageInvert) |
读取条形码,首先使用create_bar_code_model创建模型。 由于条形码元素非常窄,因此使用set_bar_code_param调整参数。 将'element_size_min'设置为1.5, 'meas_thresh'设置为0.1。 find_bar_code解码条形码,该条形码为“Code 128”类型。 clear_bar_code_model销毁条形码模型。
create_bar_code_model ([], [], BarCodeHandle) set_bar_code_param (BarCodeHandle, 'element_size_min', 1.5) set_bar_code_param (BarCodeHandle, 'meas_thresh', 0.3) find_bar_code (ImageZoomed, SymbolRegions, BarCodeHandle, 'Code 128', \ DecodedDataStrings) clear_bar_code_model (BarCodeHandle) |
最后,find_bar_code返回的条形码区域由polar_trans_region_inv转换回条形码的原始形状,并显示在图像中。
polar_trans_region_inv (SymbolRegions, CodeRegionCircular, Row, Column, \ rad(360), 0, OuterRadius - 5, InnerRadius + 5, \WidthPolar, HeightPolar, Width, Height, \ 'nearest_neighbor') dev_display (CodeRegionCircular) |
例程 print_quality_isoiec15416.hdev
根据ISO / IEC 15416标准检查条码的打印质量,以获得对比度,最小反射率,调制,边缘最小对比度,缺陷,可解码性和附加要求等参数。以"Contrast"等级为例,如图16.8所示。 此外,可以返回某些项的等级的原始值,以查明质量缺陷的原因。
首先,在图像中检测条码,然后get_bar_code_result检查条码的打印质量。
find_bar_code (ImageDefect, SymbolRegions, BarCodeHandle, 'EAN-13', DecodedDataStrings) get_bar_code_result (BarCodeHandle, 0, 'quality_isoiec15416', Quality) |
最后,在消息中显示结果,项名称,质量等级,质量原始值。
min_max_gray (SymbolRegions, ImageDefect, 0, Min, Max, Range) Contrast := Range / 255 dev_display (ImageDefect) dev_set_color ('green') dev_display (SymbolRegions) grade_message_text (Labels, Quality, QualityValues, GRADE_CONTRAST, Message) disp_message (WindowHandle, Message, 'window', 10, 12, 'black', 'true') |
图16.8 (a) 具有高对比度的条形码得到4级,原始值为82.45% (b) 低对比度的缺陷条形码得到0级,原始值为15.84%