sort_region算子對多個區域進行排序研究

 

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

 

這四種排序模式不算常用,而且理解比較繞,就不過多介紹了。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章