OSDN Git Service

Merge branch 'git-svn'
[nyartoolkit-and/nyartoolkit-and.git] / trunk / test / jp / nyatla / nyartoolkit / dev / LabelingTest.java
1 /* このソースは実験用のソースです。\r
2  * 動いたり動かなかったりします。\r
3  * \r
4  */\r
5 package jp.nyatla.nyartoolkit.dev;\r
6 \r
7 import java.awt.*;\r
8 import java.awt.event.WindowAdapter;\r
9 import java.awt.event.WindowEvent;\r
10 import java.io.File;\r
11 import java.io.FileInputStream;\r
12 \r
13 import jp.nyatla.nyartoolkit.NyARException;\r
14 import jp.nyatla.nyartoolkit.core.raster.*;\r
15 import jp.nyatla.nyartoolkit.core.raster.rgb.NyARRgbRaster_BGRA;\r
16 import jp.nyatla.nyartoolkit.core.rasterfilter.gs2bin.*;\r
17 import jp.nyatla.nyartoolkit.utils.j2se.*;\r
18 \r
19 \r
20 \r
21 public class LabelingTest extends Frame\r
22 {\r
23         private final String data_file = "../Data/320x240ABGR.raw";\r
24 \r
25         final int W=10;\r
26         final int H=10;\r
27         public void drawImage() throws Exception\r
28         {\r
29                 File f = new File(data_file);\r
30                 FileInputStream fs = new FileInputStream(data_file);\r
31                 byte[] buf = new byte[(int) f.length()];\r
32                 fs.read(buf);\r
33                 NyARRgbRaster_BGRA ra = NyARRgbRaster_BGRA.wrap(buf, W, H);\r
34                 // 二値化\r
35                 NyARRasterFilterBuilder_RgbToBin filter = new NyARRasterFilterBuilder_RgbToBin(110, ra.getBufferReader().getBufferType());\r
36                 NyARBinRaster bin = new NyARBinRaster(W,240);\r
37                 filter.doFilter(ra, bin);\r
38                 int[] t = (int[]) bin.getBuffer();\r
39                 int[] s = {\r
40                                 1,1,1,1,1,1,1,1,1,1,\r
41 \r
42                                 1,0,0,0,0,1,0,1,1,1,\r
43                                 1,0,1,1,0,1,0,1,1,1,\r
44                                 1,1,1,1,1,0,1,1,1,1,\r
45                                 1,1,1,1,1,1,1,1,1,1,\r
46                                 1,1,1,1,1,1,1,1,1,1,\r
47                                 1,1,1,1,1,1,1,1,1,1,\r
48                                 1,1,1,1,1,1,1,1,1,1,\r
49                                 1,1,1,1,1,1,1,1,1,1,\r
50                                 1,1,1,1,1,1,1,1,1,1,                            0};\r
51                 System.arraycopy(s, 0, t, 0, 10*10);\r
52                 NyARRasterImageIO sink = new NyARRasterImageIO(W, H);\r
53                 RleImage rle = new RleImage(bin.getWidth(),bin.getHeight());\r
54                 RleLabelingTable table=createRelTable(rle,bin,sink);\r
55                 for(int i=0;;i++){\r
56                         int nof=i%table.number_of_fragment;\r
57                         if(table._fragment_area[nof]==0){\r
58                                 continue;\r
59                         }\r
60                         drawLabelingImage(nof,rle,table,bin,sink);\r
61                         Graphics g;\r
62                         g=this.getGraphics();\r
63                         g.drawImage(sink, 100, 100,100,100, this);\r
64                         Thread.sleep(500);\r
65                 }\r
66         }\r
67         public void drawLabelingImage(int id,RleImage rle, RleLabelingTable i_table,NyARBinRaster i_source,NyARRasterImageIO i_img)\r
68         {\r
69 //              RleImage rle = new RleImage(i_source.getWidth(),i_source.getHeight());\r
70 //              i_table.labeling(rle,0,10);\r
71                 int p=0;\r
72                 for(int i=0;i<H;i++){\r
73                         for(int i2=0;i2<W;i2++){\r
74                                 i_img.setRGB(i2,i,0xffffff);\r
75                         }\r
76                         for(int i2=0;i2<rle.row_length[i];i2++){\r
77                                 for(int i3=rle.rle_img_l[rle.row_index[i]+i2];i3<rle.rle_img_r[rle.row_index[i]+i2];i3++)\r
78                                 {\r
79                                         int c=0x0000ff;\r
80                                         int tid=i_table._fragment_id[i_table.rle_img_id[p]];\r
81                                         if(tid==id){\r
82                                                 c=0x00ff00;\r
83                                         }\r
84                                         i_img.setRGB(i3,i,c);\r
85                                 }\r
86                                 p++;\r
87                         }\r
88                 }\r
89 \r
90                 i_img.setRGB(i_table._flagment_entry_x[id],i_table._flagment_entry_y[id],0xff0000);\r
91 //              i_img.setRGB(i_table._flagment_entry_x[id]+1,i_table._flagment_entry_y[id],0xff0000);\r
92 //              i_img.setRGB(i_table._flagment_entry_x[id],i_table._flagment_entry_y[id]+1,0xff0000);\r
93 //              i_img.setRGB(i_table._flagment_entry_x[id]+1,i_table._flagment_entry_y[id]+1,0xff0000);\r
94         }\r
95         \r
96         public RleLabelingTable createRelTable(RleImage rle,NyARBinRaster i_source,NyARRasterImageIO i_img)\r
97         {\r
98                 // RELイメージの作成\r
99                 rle.toRel(i_source);\r
100                 // 1行目のテーブル登録\r
101                 RleLabelingTable table = new RleLabelingTable(10000);\r
102                 table.labeling(rle,0,H);\r
103                 return table;\r
104         }\r
105 \r
106         public LabelingTest() throws NyARException\r
107         {\r
108                 this.addWindowListener(new WindowAdapter() {\r
109                         public void windowClosing(WindowEvent e)\r
110                         {\r
111                                 System.exit(0);\r
112                         }\r
113                 });\r
114         }\r
115 \r
116         public static void main(String[] args)\r
117         {\r
118                 try {\r
119                         LabelingTest app = new LabelingTest();\r
120                         app.setVisible(true);\r
121                         app.setBounds(0, 0, 640, 480);\r
122                         app.drawImage();\r
123                 } catch (Exception e) {\r
124                         e.printStackTrace();\r
125                 }\r
126         }\r
127 \r
128         class RleImage\r
129         {\r
130                 int _width;\r
131 \r
132                 int _height;\r
133 \r
134                 // RELデータ\r
135                 short[] rle_img_l;// RELのフラグメント左\r
136 \r
137                 short[] rle_img_r;// RELのフラグメント右\r
138 \r
139                 // Rowデータ\r
140                 int[] row_index;\r
141 \r
142                 short[] row_length;\r
143 \r
144                 int rle_buf_size;\r
145 \r
146                 public RleImage(int i_width, int i_height)\r
147                 {\r
148                         final int size = i_width * i_height / 2;\r
149                         // 1/2に圧縮できることを想定。\r
150                         this.rle_img_l = new short[size]; // RELのフラグメント長\r
151                         this.rle_img_r = new short[size]; // RELの開始位置\r
152                         this.rle_buf_size = size;\r
153 \r
154                         this.row_index = new int[i_height];\r
155                         this.row_length = new short[i_height];\r
156                         this._width = i_width;\r
157                         this._height = i_height;\r
158                         return;\r
159                 }\r
160 \r
161                 /**\r
162                  * binラスタからRELに変換する\r
163                  * \r
164                  * @param i_bin_raster\r
165                  */\r
166                 public void toRel(NyARBinRaster i_bin_raster)\r
167                 {\r
168                         final int width = this._width;\r
169                         final int height = this._height;\r
170                         int[] in_buf = (int[]) i_bin_raster.getBuffer();\r
171 \r
172                         short current = 0;\r
173                         short r = -1;\r
174                         for (int y = 0; y < height; y++) {\r
175                                 this.row_index[y] = current;\r
176                                 // 行確定開始\r
177                                 int row_index = y * width;\r
178                                 int x = row_index;\r
179                                 final int right_edge = (y + 1) * width - 1;\r
180                                 while (x < right_edge) {\r
181                                         // 暗点(0)スキャン\r
182                                         if (in_buf[x] != 0) {\r
183                                                 x++;\r
184                                                 continue;\r
185                                         }\r
186                                         // 暗点発見→暗点長を調べる\r
187                                         r = (short) (x - row_index);\r
188                                         this.rle_img_l[current] = r;\r
189                                         r++;// 暗点+1\r
190                                         x++;\r
191                                         while (x < right_edge) {\r
192                                                 if (in_buf[x] != 0) {\r
193                                                         // 明点(1)→暗点(0)配列終了>登録\r
194                                                         this.rle_img_r[current] = r;\r
195                                                         current++;\r
196                                                         x++;// 次点の確認。\r
197                                                         r = -1;// 右端の位置を0に。\r
198                                                         break;\r
199                                                 } else {\r
200                                                         // 暗点(0)長追加\r
201                                                         r++;\r
202                                                         x++;\r
203                                                 }\r
204                                         }\r
205                                 }\r
206                                 // 最後の1点だけ判定方法が少し違うの。\r
207                                 if (in_buf[x] != 0) {\r
208                                         // 明点→rカウント中なら暗点配列終了>登録\r
209                                         if (r >= 0) {\r
210                                                 this.rle_img_r[current] = r;\r
211                                                 current++;\r
212                                         }\r
213                                 } else {\r
214                                         // 暗点→カウント中でなければl1で追加\r
215                                         if (r >= 0) {\r
216                                                 this.rle_img_r[current] = (short) (x + 1);\r
217                                         } else {\r
218                                                 // 最後の1点の場合\r
219                                                 this.rle_img_l[current] = (short) (width - 1);\r
220                                                 this.rle_img_r[current] = (short) (width);\r
221                                         }\r
222                                         current++;\r
223                                 }\r
224                                 // 行確定\r
225                                 this.row_length[y] = (short) (current - this.row_index[y]);\r
226                         }\r
227                 }\r
228 \r
229                 public void fromRel(NyARBinRaster i_bin_raster)\r
230                 {\r
231 \r
232                 }\r
233         }\r
234 \r
235         // RleImageをラベリングする。\r
236         class RleLabelingTable\r
237         {\r
238                 short[] rle_img_id;\r
239 \r
240                 short[] _fragment_id; // フラグメントラベルのインデクス\r
241 \r
242                 int[] _fragment_area; // フラグメントラベルの領域数\r
243 \r
244                 int[] _fragment_pos_x; // フラグメントラベルの位置\r
245 \r
246                 int[] _fragment_pos_y; // フラグメントラベルの位置\r
247 \r
248                 short[] _flagment_entry_x; // フラグメントラベルの位置\r
249 \r
250                 short[] _flagment_entry_y; // フラグメントラベルの位置\r
251 \r
252                 short number_of_fragment; // 現在のフラグメントの数\r
253 \r
254                 public RleLabelingTable(int i_max_fragment)\r
255                 {\r
256                         this.rle_img_id = new short[i_max_fragment];\r
257                         this._fragment_id = new short[i_max_fragment];\r
258                         this._fragment_area = new int[i_max_fragment];\r
259                         this._fragment_pos_x = new int[i_max_fragment];\r
260                         this._fragment_pos_y = new int[i_max_fragment];\r
261                         this._flagment_entry_x = new short[i_max_fragment];\r
262                         this._flagment_entry_y = new short[i_max_fragment];\r
263                 }\r
264 \r
265                 private void addFragment(RleImage i_rel_img, short i_nof, int i_row_index, int i_rel_index)\r
266                 {\r
267                         this.rle_img_id[i_rel_index] = i_nof;// REL毎の固有ID\r
268                         this._fragment_id[i_nof] = i_nof;\r
269                         this._flagment_entry_x[i_nof] = i_rel_img.rle_img_l[i_rel_index];\r
270                         this._flagment_entry_y[i_nof] = (short) i_row_index;\r
271                         this._fragment_area[i_nof] = i_rel_img.rle_img_r[i_rel_index] - i_rel_img.rle_img_l[i_rel_index];\r
272                         return;\r
273                 }\r
274 \r
275 \r
276 \r
277                 // 指定した行のフラグメントをマージします。\r
278                 public void labeling(RleImage i_rel_img, int i_top, int i_bottom)\r
279                 {\r
280                         short[] rle_l = i_rel_img.rle_img_l;\r
281                         short[] rle_r = i_rel_img.rle_img_r;\r
282                         short nof = this.number_of_fragment;\r
283                         // 初段登録\r
284                         int index = i_rel_img.row_index[i_top];\r
285                         int eol = i_rel_img.row_length[i_top];\r
286                         for (int i = index; i < index + eol; i++) {\r
287                                 // フラグメントID=フラグメント初期値、POS=Y値、RELインデクス=行\r
288                                 addFragment(i_rel_img, nof, i_top, i);\r
289                                 nof++;\r
290                                 // nofの最大値チェック\r
291                         }\r
292                         // 次段結合\r
293                         for (int y = i_top+1; y < i_bottom; y++) {\r
294                                 int index_prev = i_rel_img.row_index[y - 1];\r
295                                 int eol_prev = index_prev + i_rel_img.row_length[y - 1];\r
296                                 index = i_rel_img.row_index[y];\r
297                                 eol = index + i_rel_img.row_length[y];\r
298 \r
299                                 SCAN_CUR:for (int i = index; i < eol; i++) {\r
300                                         // index_prev,len_prevの位置を調整する\r
301                                         short id = -1;\r
302                                         //チェックすべきprevがあれば確認\r
303                                         SCAN_PREV: while (index_prev < eol_prev) {\r
304                                                 if (rle_l[i] - rle_r[index_prev] > 0) {// 0なら8方位ラベリング\r
305                                                         // prevがcurの左方にある→次のフラグメントを探索\r
306                                                         index_prev++;\r
307                                                         continue;\r
308                                                 } else if (rle_l[index_prev] - rle_r[i] > 0) {// 0なら8方位ラベリングになる\r
309                                                         // prevがcur右方にある→独立フラグメント\r
310                                                         addFragment(i_rel_img, nof, y, i);\r
311                                                         nof++;\r
312                                                         // 次のindexをしらべる\r
313                                                         continue SCAN_CUR;\r
314                                                 }\r
315                                                 // 結合対象->prevのIDをコピーして、対象フラグメントの情報を更新\r
316                                                 id = this._fragment_id[this.rle_img_id[index_prev]];\r
317                                                 this.rle_img_id[i] = id;\r
318                                                 this._fragment_area[id] += (rle_r[i] - rle_l[i]);\r
319                                                 // エントリポイントの情報をコピー\r
320                                                 this._flagment_entry_x[id] = this._flagment_entry_x[this.rle_img_id[index_prev]];\r
321                                                 this._flagment_entry_y[id] = this._flagment_entry_y[this.rle_img_id[index_prev]];\r
322                                                 //多重リンクの確認\r
323 \r
324                                                 index_prev++;\r
325                                                 while (index_prev < eol_prev) {\r
326                                                         if (rle_l[i] - rle_r[index_prev] > 0) {// 0なら8方位ラベリング\r
327                                                                 // prevがcurの左方にある→prevはcurに連結していない。\r
328                                                                 break SCAN_PREV;\r
329                                                         } else if (rle_l[index_prev] - rle_r[i] > 0) {// 0なら8方位ラベリングになる\r
330                                                                 // prevがcurの右方にある→prevはcurに連結していない。\r
331                                                                 index_prev--;\r
332                                                                 continue SCAN_CUR;\r
333                                                         }\r
334                                                         // prevとcurは連結している。\r
335                                                         final short prev_id = this.rle_img_id[index_prev];\r
336                                                         if (id != prev_id) {\r
337                                                                 this._fragment_area[id] += this._fragment_area[prev_id];\r
338                                                                 this._fragment_area[prev_id] = 0;\r
339                                                                 // 結合対象->現在のidをインデクスにセット\r
340                                                                 this._fragment_id[prev_id]=id;\r
341                                                                 // エントリポイントを訂正\r
342                                                                 if (this._flagment_entry_y[id] > this._flagment_entry_y[prev_id]) {\r
343                                                                         // 現在のエントリポイントの方が下にある。(何もしない)\r
344                                                                 }\r
345                                                                 if (this._flagment_entry_y[id] < this._flagment_entry_y[prev_id]) {\r
346                                                                         // 現在のエントリポイントの方が上にある。(エントリポイントの交換)\r
347                                                                         this._flagment_entry_y[id] = this._flagment_entry_y[prev_id];\r
348                                                                         this._flagment_entry_x[id] = this._flagment_entry_x[prev_id];\r
349                                                                 } else {\r
350                                                                         // 水平方向で小さい方がエントリポイント。\r
351                                                                         if (this._flagment_entry_x[id] > this._flagment_entry_x[prev_id]) {\r
352                                                                                 this._flagment_entry_y[id] = this._flagment_entry_y[prev_id];\r
353                                                                                 this._flagment_entry_x[id] = this._flagment_entry_x[prev_id];\r
354                                                                         }\r
355                                                                 }\r
356                                                         }\r
357                                                         index_prev++;\r
358                                                 }\r
359                                                 index_prev--;\r
360                                                 break;\r
361                                         }\r
362                                         // curにidが割り当てられたかを確認\r
363                                         // 右端独立フラグメントを追加\r
364                                         if (id < 0) {\r
365                                                 addFragment(i_rel_img, nof, y, i);\r
366                                                 nof++;\r
367                                         }\r
368 \r
369                                 }\r
370                         }\r
371                         // フラグメントの数を更新\r
372                         this.number_of_fragment = nof;\r
373                 }\r
374         }\r
375 }\r
376 \r
377 // REL圧縮配列を作成\r
378 // REL結合\r
379 // 面積計算\r
380 // 参照インデクス化\r
381 // ラベルイメージ化\r