基于Halcon的Region与XLD图形对象按行列排序方法
在使用Halcon进行条码或二维码解码时,一张图片中可能包含多个码。函数find_bar_code和find_data_code_2d会返回解码结果字符串元组DecodedDataStrings,其元素数量与检测到的码数量一致。区别在于:一维码的显示区域为region,二维码的显示区域为xld。
这些显示区域(region或xld)与解码字符串之间存在一一对应关系。然而,当存在多个码时,显示区域的顺序是随机的,不会按照行坐标或列坐标自动排序。为了保持对应关系不变并实现有序排列,需要设计排序算法。
核心算子tuple_sort_index用于获取排序索引。该算子输入一个元组,输出排序后的索引序列。
排序策略设计
- 数据对组合:例如 (region1, string1)、(region2, string2) 等。
- 兼容性:函数需同时支持region和xld两种图形格式。
- 排序规则:四种模式,均按升序排列:
'row1':基于最小外接矩形左上角行坐标'row':基于中心点行坐标'column1':基于最小外接矩形左上角列坐标'column':基于中心点列坐标
函数实现:sort_objects_strings
tuple_regexp_replace(ObjectType, ['\\s*','replace_all'], '', ObjectType)
tuple_regexp_replace(SortRule, ['\\s*','replace_all'], '', SortRule)
* 确定图形类型
if (ObjectType == 'region')
ObjectType := 'region'
else
ObjectType := 'xld'
endif
* 输入有效性检查
count_obj(SourceObjects, Num)
if (|SourceStrings| == 0 or |SourceStrings| != Num)
SortedObjects := SourceObjects
SortedStrings := SourceStrings
return()
endif
* 根据图形类型选择排序依据
if (ObjectType == 'region')
if (SortRule == 'row1')
smallest_rectangle1(SourceObjects, SortItems, Column1, Row2, Column2)
elseif (SortRule == 'column1')
smallest_rectangle1(SourceObjects, Row1, SortItems, Row2, Column2)
elseif (SortRule == 'row')
area_center(SourceObjects, Area, SortItems, Column)
else
area_center(SourceObjects, Area, Row, SortItems)
endif
else
if (SortRule == 'row1')
smallest_rectangle1_xld(SourceObjects, SortItems, Column1, Row2, Column2)
elseif (SortRule == 'column1')
smallest_rectangle1_xld(SourceObjects, Row1, SortItems, Row2, Column2)
elseif (SortRule == 'row')
area_center_xld(SourceObjects, Area, SortItems, Column, PointOrder)
else
area_center_xld(SourceObjects, Area, Row, SortItems, PointOrder)
endif
endif
* 获取排序索引
tuple_sort_index(SortItems, Indices)
* 根据索引重新排序对象和字符串
SortedStrings := []
gen_empty_obj(SortedObjects)
for i := 0 to Num-1 by 1
SortedStrings[i] := SourceStrings[Indices[i]]
select_obj(SourceObjects, ObjectSelected, Indices[i] + 1)
concat_obj(SortedObjects, ObjectSelected, SortedObjects)
endfor
return()
应用示例
以下代码演示如何对二维码XLD对象按'row1'规则排序:
dev_set_draw('margin')
dev_set_line_width(3)
set_display_font(200000, 22, 'Courier', 'true', 'false')
read_image(Image, 'SortCodes')
create_data_code_2d_model('QR Code', 'default_parameters', 'enhanced_recognition', DataCodeHandleQR)
* 最多查找10个码
find_data_code_2d(Image, SymbolXLDs, DataCodeHandleQR, 'stop_after_result_num', 10, ResultHandles, SourceStrings)
sort_objects_strings(SymbolXLDs, SymbolXLDsSort, SourceStrings, 'xld', 'row1', SortedStrings)
dev_display(Image)
for Index := 0 to |SourceStrings|-1 by 1
select_obj(SymbolXLDsSort, ObjectSelected, Index + 1)
dev_display(ObjectSelected)
area_center_xld(ObjectSelected, Area, Row, Column, PointOrder)
disp_message(200000, (Index + 1) + '、' + SortedStrings[Index], 'image', Row, Column-50, 'black', 'true')
endfor
clear_data_code_2d_model(DataCodeHandleQR)
效果对比
- 按
'row1'排序:基于左上角行坐标排序 - 按
'row'排序:基于中心点行坐标排序 - 按
'column1'排序:基于左上角列坐标排序 - 按
'column'排序:基于中心点列坐标排序
该算法具有通用性,不仅适用于解码场景,也可推广至其他需要对图形对象及其关联数据进行排序的需求。