用Halcon解码时,如果一张图里面有多个码,它通常可以把这些码都解出来,并且生成对应的解码结果字符串元组(也就是下面的DecodedDataStrings),如果有多个码,那么该元组就有多个元素。

① find_bar_code(Image : SymbolRegions : BarCodeHandle, CodeType : DecodedDataStrings)

② find_data_code_2d(Image : SymbolXLDs : DataCodeHandle, GenParamName, GenParamValue : ResultHandles, DecodedDataStrings)

一维码和二维码解码的区别是:一维码解码后的显示区域是一个region(SymbolRegions ),而二维码解码后的显示区域是一个xld(SymbolXLDs )

码的显示区域和解码字符串是一一对应的。但是有多个码时,不同码的显示区域顺序本身是乱排的,并不是按照“行坐标”或者“列坐标”排序的。如何让它们有序排列,并且字符串和它们的对应关系不变呢?这篇文章即是为了解决这个问题。

先了解一个排序算子:tuple_sort_index( : : Tuple : Indices)

基本上,Halcon中绝大多数的排序问题,都需要用到这个算子。关于这个算子的理解,详见我之前的文章:Halcon选择一堆region中面积第N大的region的算法实现

排序算法设计分析:

① 需排序的数据对假设是(region1, string1)、(region2, string2)、(region3, string3)、(region4, string4)……

② 以一维码、二维码以及它们对应的字符串为例,一维码解码显示区域是region,二维码解码显示区域是xld,所以该排序函数要兼容region和xld两种图形格式。

③ 为简单起见,均只设计为从小到大排序。设计了四种排序规则,分别是'row1'(最小外接矩形左上角行坐标)、'row'(中心点行坐标)、'column1'(最小外接矩形左上角列坐标)、'column'(中心点列坐标)

封装的函数签名为:sort_objects_strings(SourceObjects : SortedObjects : SourceStrings, ObjectType, SortRule : SortedStrings)

sort_objects_strings函数代码为:

 tuple_regexp_replace (ObjectType, ['\\s*','replace_all'], '', ObjectType)
tuple_regexp_replace (SortRule, ['\\s*','replace_all'], '', SortRule) *是region还是xld
if (ObjectType == 'region')
ObjectType := 'region'
else
ObjectType := 'xld'
endif *如果SourceStrings为空,或者SourceObjects和SourceStrings个数不同,这些都属异常,需return()
count_obj (SourceObjects, Num)
if (|SourceStrings| == or |SourceStrings| != Num)
SortedObjects := SourceObjects
SortedStrings := SourceStrings
return ()
endif *逻辑判断(如果是region)
if (ObjectType == 'region')
*row1 row column1 column, 看按哪种规则排序(下同)
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 *逻辑判断(如果是xld)
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 * sort_region (SourceObjects, SortedObjects, 'upper_left', 'true', 'row')
* sort_contours_xld (SourceObjects, SortedObjects, 'upper_left', 'true', 'row') tuple_sort_index (SortItems, Indices)

*SourceStrings和SourceObjects的排序
SortedStrings := []
gen_empty_obj (SortedObjects)
for i := to Num- by
SortedStrings[i] := SourceStrings[Indices[i]]
select_obj (SourceObjects, ObjectSelected, Indices[i] + 1)
concat_obj (SortedObjects, ObjectSelected, SortedObjects)
endfor return ()

【示例】

程序是用Halcon 17.12写的,如果是低版本Halcon,那么文本显示和字体设置的语句略有不同。

 dev_set_draw ('margin')
dev_set_line_width ()
set_display_font (, , 'Courier', 'true', 'false') read_image (Image, 'SortCodes')
create_data_code_2d_model ('QR Code', 'default_parameters', 'enhanced_recognition', DataCodeHandleQR) *'stop_after_result_num', :意思是最大可找到10个码,如果不设置该参数,那么只会找到一个码
find_data_code_2d (Image, SymbolXLDs, DataCodeHandleQR, 'stop_after_result_num', , ResultHandles, SourceStrings)
sort_objects_strings (SymbolXLDs, SymbolXLDsSort, SourceStrings, 'xld', 'row1', SortedStrings)

dev_display (Image)
for Index := to |SourceStrings|- by
select_obj (SymbolXLDsSort, ObjectSelected, Index + )
dev_display (ObjectSelected)
area_center_xld (ObjectSelected, Area, Row, Column, PointOrder)
disp_message (, (Index + ) + '、' + SortedStrings[Index], 'image', Row, Column-, 'black', 'true')
endfor clear_data_code_2d_model (DataCodeHandleQR)

① 按'row1'规格排序,效果图为:

② 按'row'规格排序,效果图为:

③ 按'column1'规格排序,效果图为:

④ 按'column'规格排序,效果图为:

请读者朋友们自己观察一下这四种效果图,体会一下'row1'、'row'、'column1'、'column'这四种排序规则的区别。

值得说明的是:这种排序算法是通用的,它不仅仅局限解码项目中的数据处理,其他类似的排序需求,也是可以用的。

region、xld有对应的字符串时,将region、xld按照行或列排序的算法实现的更多相关文章

  1. sqlserver 行转列、字符串行转列、自动生产行转列脚本

    行转列,老生常谈的问题.这里总结一下网上的方法. 1.生成测试数据: CREATE TABLE human( name ), --姓名 norm ), --指标 score INT , --分数 gr ...

  2. 将数据转化成字符串时:用字符串的链接 还是 StringBuilder

    /* 目的:将数据转化成字符串时:用字符串的链接 还是 StringBuilder呢? */ public class Test{ public static void main(String[] a ...

  3. C#反序列化json字符串时,提示:应为来自命名空间“”的元素“root”。。遇到名称为“”、命名空间为“”的“None”。

    反序列化调用接口返回的字符串时,出现:应为来自命名空间“”的元素“root”..遇到名称为“”.命名空间为“”的“None”.,导致反序列化数据失败,这种失败并有时候并不会直接提示反序列化失败(抛异常 ...

  4. java.text.MessageFormat格式化字符串时的小技巧

    java.text.MessageFormat格式化字符串时的小技巧 public static void main(String[] args) throws InterruptedExceptio ...

  5. fastjson中对象转化为字符串时过滤某字段

    fastjson中对象转化为字符串时过滤某字段,有两种方法: 一.在该字符定义上方添加"@JSONField(serialize=false)"注解: 二.调用含有Property ...

  6. 使用 springmvc请求 返回 字符串时 ,中文出现乱码

    @RequestMapping(value="/askQuestion" ,method = RequestMethod.GET , produces = {"appli ...

  7. JSON.parse 解析json字符串时,遇换行符报错

    Json字符串转换成Json对象时候,有两种方式: 假设d是json字符串: 1,eval('(' + d + ')'). 2,JSON.parse(d): 但是以上方式有隐患,如果Json字符串有换 ...

  8. 此类目的是防治序列化Json字符串时的循环引用问题-------最好解决方案

    http://james.newtonking.com/json/help/index.html using Newtonsoft.Json;using System;using System.Col ...

  9. 解决like '%字符串%'时索引不被使用的方法

    解决like '%字符串%'时索引不被使用的方法   分步阅读 解决like '%字符串%'时索引不被使用的方法,如果like以通配符开头('%abc')时索引会失效会变成全表扫描的操作. 工具/原料 ...

随机推荐

  1. 执行redis命令redis-trib.rb查看集群信息报错cannot load such file -- redis (LoadError)

    问题描述: 在执行redis-trib.rb命令查看集群状态的时候,报错: [aiprd@hadoop1 ~]$ redis-trib.rb check Traceback (most recent ...

  2. python初级(302) 7 列表

    一.列表的概念: 1.创建一个列表 friends = list() 2.列表可以包含的内容: m_list = [5, 7, 9, 20] letters = ['a', 'b', 'e'] 3.从 ...

  3. 配置Pods和containers--为Containers和Pods分配CPU资源

    指定CPU请求和CPU限制 要为容器指定CPU请求,在容器资源清单中使用resources:requests字段.要指定CPU限制,使用resources:limits. cpu-request-li ...

  4. PMP 第12~13章错题总结

    1.合同解释应该遵循几个主要原则: 1)主导语言原则 2)适用法律原则 3)整体解释原则 4)公平诚信原则2.合同收尾包括的工作: 1)产品核实 2)可交付成果验收 3)财务结算 4)退还保证金或担保 ...

  5. oracle 统计成绩

    set serveroutput on; declare cursor c1 is select dno,dname from dep; pdno dep.dno%TYPE; pdname dep.d ...

  6. 文件组 'PRIMARY' 已满 解决办法

    修改一个字段类型时,报的这个错. 此时需要增加次要数据文件 次要数据文件 次要数据文件包含除主要数据文件外的所有数据文件.有些数据库可能没有次要数据文件,而有些数据库则有多个次要数据文件.次要数据文件 ...

  7. 双写mq后碰到没有消费问题记录

    上周双写mq后碰到遇到个问题,mq双写的一台机器有produce,另一台一直没有,但是有的那台机器没有消费者,导致另一个服务 一直没有可以消费的mq.原因是 mq在双写初始化配置的时候两个类文件重复了 ...

  8. 对于之前已经push的项目增加.gitignore配置文件不起作用的处理

    .gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的. 解决方法就是先把本地缓存删除(改变成未track状态),然后再提交 ...

  9. STL之空间配置器allocator

    摘要 C++STL的空间配置器将内存的分配.释放,对象的构造.析构都分开执行,内存分配由alloc::allocate()负责,内存的释放由alloc::deallocate()负责:对象的构造由:: ...

  10. 【bat】【windows】win10查看所有wifi密码

    win10的可以,win7的好像不行 @echo off & setlocal EnableDelayedExpansion title 查看所有wifi和密码 for /f "us ...