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)的最高点位置来排序的

 

这四种排序模式不算常用,而且理解比较绕,就不过多介绍了。

 

 

 

posted on 2022-08-10 17:33  xh6300  阅读(4109)  评论(0编辑  收藏  举报