OSDN Git Service

02e677d4029ce30305a4b37d44048af1edd9695a
[nyartoolkit-and/nyartoolkit-and.git] / trunk / src / jp / nyatla / nyartoolkit / core / labeling / rlelabeling / NyARLabeling_Rle.java
1 /* このソースは実験用のソースです。\r
2  * 動いたり動かなかったりします。\r
3  * \r
4  */\r
5 package jp.nyatla.nyartoolkit.core.labeling.rlelabeling;\r
6 \r
7 import jp.nyatla.nyartoolkit.NyARException;\r
8 import jp.nyatla.nyartoolkit.core.raster.*;\r
9 \r
10 \r
11 \r
12 /**\r
13  * [strage class]\r
14  */\r
15 \r
16 \r
17 class RleElement\r
18 {\r
19         short l;\r
20         short r;\r
21         short id;\r
22         public static RleElement[] createArray(int i_length)\r
23         {\r
24                 RleElement[] ret = new RleElement[i_length];\r
25                 for (int i = 0; i < i_length; i++) {\r
26                         ret[i] = new RleElement();\r
27                 }\r
28                 return ret;\r
29         }\r
30 }\r
31 \r
32 // RleImageをラベリングする。\r
33 public class NyARLabeling_Rle\r
34 {\r
35         private RleElement[] _rle1;\r
36 \r
37         private RleElement[] _rle2;\r
38 \r
39         private short number_of_fragment; // 現在のフラグメントの数\r
40 \r
41         public NyARLabeling_Rle(int i_width)\r
42         {\r
43                 this._rle1 = RleElement.createArray(i_width/2+1);\r
44                 this._rle2 = RleElement.createArray(i_width/2+1);\r
45                 return;\r
46         }\r
47 \r
48         /**\r
49          * i_bin_bufのbinイメージをREL圧縮する。\r
50          * \r
51          * @param i_bin_raster\r
52          */\r
53         private int toRel(int[] i_bin_buf, int i_st, int i_len, RleElement[] i_out)\r
54         {\r
55                 short current = 0;\r
56                 short r = -1;\r
57                 // 行確定開始\r
58                 int x = i_st;\r
59                 final int right_edge = i_st + i_len - 1;\r
60                 while (x < right_edge) {\r
61                         // 暗点(0)スキャン\r
62                         if (i_bin_buf[x] != 0) {\r
63                                 x++;\r
64                                 continue;\r
65                         }\r
66                         // 暗点発見→暗点長を調べる\r
67                         r = (short) (x - i_st);\r
68                         i_out[current].l = r;\r
69                         r++;// 暗点+1\r
70                         x++;\r
71                         while (x < right_edge) {\r
72                                 if (i_bin_buf[x] != 0) {\r
73                                         // 明点(1)→暗点(0)配列終了>登録\r
74                                         i_out[current].r = r;\r
75                                         current++;\r
76                                         x++;// 次点の確認。\r
77                                         r = -1;// 右端の位置を0に。\r
78                                         break;\r
79                                 } else {\r
80                                         // 暗点(0)長追加\r
81                                         r++;\r
82                                         x++;\r
83                                 }\r
84                         }\r
85                 }\r
86                 // 最後の1点だけ判定方法が少し違うの。\r
87                 if (i_bin_buf[x] != 0) {\r
88                         // 明点→rカウント中なら暗点配列終了>登録\r
89                         if (r >= 0) {\r
90                                 i_out[current].r = r;\r
91                                 current++;\r
92                         }\r
93                 } else {\r
94                         // 暗点→カウント中でなければl1で追加\r
95                         if (r >= 0) {\r
96                                 i_out[current].r = (short) (r + 1);\r
97                         } else {\r
98                                 // 最後の1点の場合\r
99                                 i_out[current].l = (short) (i_st + i_len - 1);\r
100                                 i_out[current].r = (short) (i_st + i_len);\r
101                         }\r
102                         current++;\r
103                 }\r
104                 // 行確定\r
105                 return current;\r
106         }\r
107 \r
108         private void addFragment(RleElement i_rel_img, short i_nof, int i_row_index, int i_rel_index,RleLabelFragmentInfoStack o_stack) throws NyARException\r
109         {\r
110                 i_rel_img.id = i_nof;// REL毎の固有ID\r
111                 RleLabelFragmentInfoStack.RleLabelFragmentInfo v = o_stack.prePush();\r
112                 v.id = i_nof;\r
113                 v.entry_x = i_rel_img.l;\r
114                 v.entry_y = (short) i_row_index;\r
115                 v.area = i_rel_img.r - i_rel_img.l;\r
116                 return;\r
117         }\r
118 \r
119         //\r
120         public void labeling(NyARBinRaster i_bin_raster, int i_top, int i_bottom,RleLabelFragmentInfoStack o_stack) throws NyARException\r
121         {\r
122                 // リセット処理\r
123                 this.number_of_fragment = 0;\r
124                 o_stack.clear();\r
125                 //\r
126                 RleElement[] rle_prev = this._rle1;\r
127                 RleElement[] rle_current = this._rle2;\r
128                 int len_prev = 0;\r
129                 int len_current = 0;\r
130                 final int width = i_bin_raster.getWidth();\r
131                 int[] in_buf = (int[]) i_bin_raster.getBufferReader().getBuffer();\r
132 \r
133                 short nof = this.number_of_fragment;\r
134                 // 初段登録\r
135 \r
136                 len_prev = toRel(in_buf, i_top, width, rle_prev);\r
137                 for (int i = 0; i < len_prev; i++) {\r
138                         // フラグメントID=フラグメント初期値、POS=Y値、RELインデクス=行\r
139                         addFragment(rle_prev[i], nof, i_top, i,o_stack);\r
140                         nof++;\r
141                         // nofの最大値チェック\r
142                 }\r
143                 RleLabelFragmentInfoStack.RleLabelFragmentInfo[] f_array = o_stack.getArray();\r
144                 // 次段結合\r
145                 for (int y = i_top + 1; y < i_bottom; y++) {\r
146                         // カレント行の読込\r
147                         len_current = toRel(in_buf, y * width, width, rle_current);\r
148                         int index_prev = 0;\r
149 \r
150                         SCAN_CUR: for (int i = 0; i < len_current; i++) {\r
151                                 // index_prev,len_prevの位置を調整する\r
152                                 short id = -1;\r
153                                 // チェックすべきprevがあれば確認\r
154                                 SCAN_PREV: while (index_prev < len_prev) {\r
155                                         if (rle_current[i].l - rle_prev[index_prev].r > 0) {// 0なら8方位ラベリング\r
156                                                 // prevがcurの左方にある→次のフラグメントを探索\r
157                                                 index_prev++;\r
158                                                 continue;\r
159                                         } else if (rle_prev[index_prev].l - rle_current[i].r > 0) {// 0なら8方位ラベリングになる\r
160                                                 // prevがcur右方にある→独立フラグメント\r
161                                                 addFragment(rle_current[i], nof, y, i,o_stack);\r
162                                                 nof++;\r
163                                                 // 次のindexをしらべる\r
164                                                 continue SCAN_CUR;\r
165                                         }\r
166                                         // 結合対象->prevのIDをコピーして、対象フラグメントの情報を更新\r
167                                         id = f_array[rle_prev[index_prev].id].id;\r
168                                         RleLabelFragmentInfoStack.RleLabelFragmentInfo prev_ptr;\r
169                                         final RleLabelFragmentInfoStack.RleLabelFragmentInfo id_ptr = f_array[id];\r
170                                         prev_ptr = f_array[rle_prev[index_prev].id];\r
171                                         rle_current[i].id = id;\r
172                                         id_ptr.area += (rle_current[i].r - rle_current[i].l);\r
173                                         // エントリポイントの情報をコピー\r
174                                         id_ptr.entry_x = prev_ptr.entry_x;\r
175                                         id_ptr.entry_y = prev_ptr.entry_y;\r
176                                         // 多重リンクの確認\r
177 \r
178                                         index_prev++;\r
179                                         while (index_prev < len_prev) {\r
180                                                 if (rle_current[i].l - rle_prev[index_prev].r > 0) {// 0なら8方位ラベリング\r
181                                                         // prevがcurの左方にある→prevはcurに連結していない。\r
182                                                         break SCAN_PREV;\r
183                                                 } else if (rle_prev[index_prev].l - rle_current[i].r > 0) {// 0なら8方位ラベリングになる\r
184                                                         // prevがcurの右方にある→prevはcurに連結していない。\r
185                                                         index_prev--;\r
186                                                         continue SCAN_CUR;\r
187                                                 }\r
188                                                 // prevとcurは連結している。\r
189                                                 final short prev_id = rle_prev[index_prev].id;\r
190                                                 prev_ptr = f_array[prev_id];\r
191                                                 if (id != prev_id) {\r
192                                                         id_ptr.area += prev_ptr.area;\r
193                                                         prev_ptr.area = 0;\r
194                                                         // 結合対象->現在のidをインデクスにセット\r
195                                                         prev_ptr.id = id;\r
196                                                         // エントリポイントを訂正\r
197                                                         if (id_ptr.entry_y > prev_ptr.entry_y) {\r
198                                                                 // 現在のエントリポイントの方が下にある。(何もしない)\r
199                                                         }\r
200                                                         if (id_ptr.entry_y < prev_ptr.entry_y) {\r
201                                                                 // 現在のエントリポイントの方が上にある。(エントリポイントの交換)\r
202                                                                 prev_ptr.entry_y = id_ptr.entry_y;\r
203                                                                 prev_ptr.entry_x = id_ptr.entry_x;\r
204                                                         } else {\r
205                                                                 // 水平方向で小さい方がエントリポイント。\r
206                                                                 if (id_ptr.entry_x < prev_ptr.entry_x) {\r
207                                                                         prev_ptr.entry_y = id_ptr.entry_y;\r
208                                                                         prev_ptr.entry_x = id_ptr.entry_x;\r
209                                                                 }\r
210                                                         }\r
211                                                 }\r
212                                                 index_prev++;\r
213                                         }\r
214                                         index_prev--;\r
215                                         break;\r
216                                 }\r
217                                 // curにidが割り当てられたかを確認\r
218                                 // 右端独立フラグメントを追加\r
219                                 if (id < 0) {\r
220                                         addFragment(rle_current[i], nof, y, i,o_stack);\r
221                                         nof++;\r
222                                 }\r
223                         }\r
224                         // prevとrelの交換\r
225                         RleElement[] tmp = rle_prev;\r
226                         rle_prev = rle_current;\r
227                         len_prev = len_current;\r
228                         rle_current = tmp;\r
229                 }\r
230                 // フラグメントの数を更新\r
231                 this.number_of_fragment = nof;\r
232         }       \r
233 }\r
234 \r
235 \r
236 \r