sort_region是个很有用的算子,在对多个Region进行排序时,经常用到。
算子含义:根据区域的相对位置对区域进行排序。(Sorting of regions with respect to their relative position.)
算子签名:sort_region(Regions : SortedRegions : SortMode, Order, RowOrCol : )
例如:
sort_region (Regions, SortedRegions, 'first_point', 'true', 'row')
其中Regions是待排序的多个区域; 'first_point' 是排序模式(SortMode); 'true' 是递增,如果是'false' 则是递减;'row' 是按照“行”来排序。
排序模式一共有上面7种,其中最常用的是前三种,而'first_point'、'last_point'是刚好相反的排序方式。因此只需要研究前两种排序模式就可以了:'character'、 'first_point' 。
一、'first_point'
sort_region (Regions, SortedRegions, 'first_point', 'true', 'row')
含义:根据各个区域的行坐标的最小值,按照从小到大的递增方式,对Regions进行排序。
下图中,矩形和圆的“行坐标的最小值”点如下所示:
写个程序验证一下:(图中细黑线是为了便于观察不同Region的相对关系)
1 dev_get_window (WindowHandle)
2 dev_set_color ('red')
3 set_display_font (WindowHandle, 13, 'Courier', 'true', 'false')
4
5 read_image (Image, '黑框.jpg')
6 threshold (Image, Region, 0, 120)
7 fill_up (Region, Region)
8 opening_circle (Region, Region, 3.5)
9 connection (Region, Regions)
10
11 sort_region (Regions, SortedRegions, 'first_point', 'true', 'row')
12
13 dev_display (Image)
14
15 count_obj (SortedRegions, Number)
16 for Index := 1 to Number by 1
17 select_obj (SortedRegions, CurrentRect, Index)
18 dev_display (CurrentRect)
19 area_center (CurrentRect, Area, Row, Column)
20 disp_message (WindowHandle, ' ' + Index, 'image', Row - 8, Column - 20, 'black', 'true')
21 endfor
观察4号区域,虽然4号区域的中心点坐标的Row值都大于5号、6号、7号区域,但是4号区域反而排在前面。
这说明不是按照“中心点”的行坐标排序的,而可能是按照“最高点”的行坐标来排序的(多次设计程序验证,发现确实如此)。
二、'character'
sort_region (Regions, SortedRegions, 'character', 'true', 'row')
这种排序方式的探究,是本文的重点。网上搜到的资料,多把它的作用描述为:先根据行从小到大排序,再根据列从小到大排序。
这种描述当然没有问题,但是语焉不详,它回避了一个问题:哪些区域该被先划为同一行?如果垂直方向上区域有重叠怎么办?
看一下帮助文档中怎么说的:
翻译:这些区域将被视为一行中的字符,并将根据它们在行中的顺序进行排序:如果两个区域水平重叠,则将根据其列值对其进行排序,否则将根据其行值对其进行排序。为了能够正确地对“行”进行排序,行中的所有区域必须在垂直方向上相互重叠(?)。 此外,相邻行中的区域不得重叠。
有这么几个要点:('character', 'true', 'row')
① 同一行中有1个或多个区域,这些区域合起来叫做“同一行”。
② “同一行”的若干个区域可以重叠,因为可以通过“列”区分开。
③ 相邻的“同一行”区域(的最小外接正矩形)不能有任何重叠,如果有重叠,则排序结果不可控。
④ 确定哪些区域属于“同一行”是核心。
注意:这里带双引号的“同一行”都有特殊的相同意义,后文同。
下面用程序验证:
1 dev_get_window (WindowHandle)
2 dev_set_color ('blue')
3 set_display_font (WindowHandle, 18, 'Courier', 'true', 'false')
4
5 read_image (Image, '红线图.jpg')
6
7 * 反复改变下面的部分矩形的中心点坐标、长宽,观察
8 gen_rectangle2 (Region1, 80, 120, 0, 40, 30)
9 gen_rectangle2 (Region2, 83, 350, 0, 40, 30)
10 gen_rectangle2 (Region3, 77, 580, 0, 40, 30)
11
12 gen_rectangle2 (Region4, 245, 300, 0, 40, 121)
13
14 gen_rectangle2 (Region5, 400, 235, 0, 40, 30)
15 gen_rectangle2 (Region6, 396, 450, 0, 40, 30)
16
17 concat_obj (Region1, Region2, RectHubs)
18 concat_obj (RectHubs, Region3, RectHubs)
19 concat_obj (RectHubs, Region4, RectHubs)
20 concat_obj (RectHubs, Region5, RectHubs)
21 concat_obj (RectHubs, Region6, RectHubs)
22
23 * 将RectHubs按'character'规则排序
24 sort_region (RectHubs, SortedRegions, 'character', 'true', 'row')
25
26 dev_display (Image)
27
28 count_obj (SortedRegions, Number)
29 for Index := 1 to Number by 1
30 select_obj (SortedRegions, CurrentRect, Index)
31 dev_display (CurrentRect)
32 area_center (CurrentRect, Area, Row, Column)
33 disp_message (WindowHandle, ' ' + Index, 'image', Row - 12, Column - 26, 'black', 'true')
34 endfor
分析:
“第一行”:矩形1、2、3
“第二行”:矩形4
“第三行”:矩形5、6
这三“行”,彼此之间都没有任何重叠。
将上面程序第12行标红的数字121改成128,运行得到的排序就变了:
上图中,长矩形5和矩形4在“垂直方向”有重叠。注意:不需要两个Region有实际的重叠交集区域,只需要Row坐标有重叠就算“垂直方向”重叠。
此时行的分组变成了:
“第一行”:矩形1、2、3
“第二行”:矩形4、5、6
没有“第三行”了。
如果再乱一点,那就没办法根据这种规律排序了,如下图:
再跑一下前面的“黑框.jpg”图体会一下:
1 dev_get_window (WindowHandle)
2 dev_set_color ('red')
3 set_display_font (WindowHandle, 13, 'Courier', 'true', 'false')
4
5 read_image (Image, '黑框.jpg')
6 threshold (Image, Region, 0, 120)
7 fill_up (Region, Region)
8 opening_circle (Region, Region, 3.5)
9 connection (Region, Regions)
10
11 sort_region (Regions, SortedRegions, 'character', 'true', 'row')
12
13 dev_display (Image)
14
15 count_obj (SortedRegions, Number)
16 for Index := 1 to Number by 1
17 select_obj (SortedRegions, CurrentRect, Index)
18 dev_display (CurrentRect)
19 area_center (CurrentRect, Area, Row, Column)
20 disp_message (WindowHandle, ' ' + Index, 'image', Row - 8, Column - 20, 'black', 'true')
21 endfor
其运行结果和“分行”情况,如下图所示:
因此,确定哪些区域属于“同一行”是 'character' 模式排序的核心。
三、'upper_left'
跟'upper_left'相似的一共有4个:
研究发现,'upper_left'排序模式是根据不同区域的“最小外接斜矩形”(rectangle2)的最高点位置来排序的。
这四种排序模式不算常用,而且理解比较绕,就不过多介绍了。
--------------------------------------------
本文系原创,转载请注明出处。
如果文章对您有帮助,可以点击下方的【好文要顶】或【关注我】;如果您想进一步表示感谢,可通过网页右侧的【打赏】功能进行打赏。
感谢您的支持,我会继续写出更多的相关文章!文章有不理解的地方欢迎跟帖交流,博主经常在线!^_^