OSDN Git Service

[Backup]NyARToolkit for Java
[nyartoolkit-and/nyartoolkit-and.git] / trunk / test / jp / nyatla / nyartoolkit / dev / LabelingTest.java
index b9b7c28..b91dca2 100644 (file)
 package jp.nyatla.nyartoolkit.dev;\r
 \r
 import java.awt.Frame;\r
+import java.awt.*;\r
+import java.awt.event.WindowAdapter;\r
+import java.awt.event.WindowEvent;\r
 import java.io.File;\r
 import java.io.FileInputStream;\r
 \r
+import jp.nyatla.nyartoolkit.NyARException;\r
 import jp.nyatla.nyartoolkit.core.raster.*;\r
 import jp.nyatla.nyartoolkit.core.raster.rgb.NyARRgbRaster_BGRA;\r
-import jp.nyatla.nyartoolkit.core.labeling.*;\r
+import jp.nyatla.nyartoolkit.core.rasterfilter.rgb2bin.*;\r
+\r
 \r
-import jp.nyatla.nyartoolkit.core2.rasteranalyzer.*;\r
 import jp.nyatla.utils.j2se.*;\r
 \r
 public class LabelingTest extends Frame\r
 {\r
-    private final String data_file  ="../Data/320x240ABGR.raw";\r
-    public void drawImage() throws Exception\r
-    {\r
-       File f=new File(data_file);\r
-       FileInputStream fs=new FileInputStream(data_file);\r
-       byte[] buf=new byte[(int)f.length()];\r
-       fs.read(buf);\r
-       NyARRgbRaster_BGRA ra=NyARRgbRaster_BGRA.wrap(buf, 320, 240);\r
-       NyARLabelingImage limage=new NyARLabelingImage(320,240);\r
-       INyARLabeling labeling=new NyARLabeling_ARToolKit();\r
-//     INyARLabeling labeling=new NyLineLabeling();\r
-       INyARRasterReaderFactory rf=new NyARRasterReaderFactory_RgbTotal();\r
-       labeling.attachDestination(limage);\r
-       labeling.labeling(rf.createReader(ra));\r
-       LabelingBufferdImage img=new LabelingBufferdImage(320,240,LabelingBufferdImage.COLOR_125_COLOR);\r
-       img.setLabelingImage(limage);\r
-       this.getGraphics().drawImage(img, 32,32,this);\r
-    }\r
-    public static void main(String[] args)\r
-    {\r
-       try{\r
-           LabelingTest app=new LabelingTest();\r
-           app.setVisible(true);\r
-           app.setBounds(0,0,640,480);\r
-           app.drawImage();\r
-       }catch(Exception e){\r
-           e.printStackTrace();\r
+       private final String data_file = "../Data/320x240ABGR.raw";\r
+\r
+       final int W=10;\r
+       final int H=10;\r
+       public void drawImage() throws Exception\r
+       {\r
+               File f = new File(data_file);\r
+               FileInputStream fs = new FileInputStream(data_file);\r
+               byte[] buf = new byte[(int) f.length()];\r
+               fs.read(buf);\r
+               NyARRgbRaster_BGRA ra = NyARRgbRaster_BGRA.wrap(buf, W, H);\r
+               // 二値化\r
+               NyARRasterFilter_ARToolkitThreshold filter = new NyARRasterFilter_ARToolkitThreshold(110, ra.getBufferReader().getBufferType());\r
+               NyARBinRaster bin = new NyARBinRaster(W,240);\r
+               filter.doFilter(ra, bin);\r
+               int[] t = (int[]) bin.getBufferReader().getBuffer();\r
+               int[] s = {\r
+                               1,1,1,1,1,1,1,1,1,1,\r
+\r
+                               1,0,0,0,0,1,0,1,1,1,\r
+                               1,0,1,1,0,1,0,1,1,1,\r
+                               1,1,1,1,1,0,1,1,1,1,\r
+                               1,1,1,1,1,1,1,1,1,1,\r
+                               1,1,1,1,1,1,1,1,1,1,\r
+                               1,1,1,1,1,1,1,1,1,1,\r
+                               1,1,1,1,1,1,1,1,1,1,\r
+                               1,1,1,1,1,1,1,1,1,1,\r
+                               1,1,1,1,1,1,1,1,1,1,                            0};\r
+               System.arraycopy(s, 0, t, 0, 10*10);\r
+               NyARRasterImageIO sink = new NyARRasterImageIO(W, H);\r
+               RleImage rle = new RleImage(bin.getWidth(),bin.getHeight());\r
+               RleLabelingTable table=createRelTable(rle,bin,sink);\r
+               for(int i=0;;i++){\r
+                       int nof=i%table.number_of_fragment;\r
+                       if(table._fragment_area[nof]==0){\r
+                               continue;\r
+                       }\r
+                       drawLabelingImage(nof,rle,table,bin,sink);\r
+                       Graphics g;\r
+                       g=this.getGraphics();\r
+                       g.drawImage(sink, 100, 100,100,100, this);\r
+                       Thread.sleep(500);\r
+               }\r
+       }\r
+       public void drawLabelingImage(int id,RleImage rle, RleLabelingTable i_table,NyARBinRaster i_source,NyARRasterImageIO i_img)\r
+       {\r
+//             RleImage rle = new RleImage(i_source.getWidth(),i_source.getHeight());\r
+//             i_table.labeling(rle,0,10);\r
+               int p=0;\r
+               for(int i=0;i<H;i++){\r
+                       for(int i2=0;i2<W;i2++){\r
+                               i_img.setRGB(i2,i,0xffffff);\r
+                       }\r
+                       for(int i2=0;i2<rle.row_length[i];i2++){\r
+                               for(int i3=rle.rle_img_l[rle.row_index[i]+i2];i3<rle.rle_img_r[rle.row_index[i]+i2];i3++)\r
+                               {\r
+                                       int c=0x0000ff;\r
+                                       int tid=i_table._fragment_id[i_table.rle_img_id[p]];\r
+                                       if(tid==id){\r
+                                               c=0x00ff00;\r
+                                       }\r
+                                       i_img.setRGB(i3,i,c);\r
+                               }\r
+                               p++;\r
+                       }\r
+               }\r
+\r
+               i_img.setRGB(i_table._flagment_entry_x[id],i_table._flagment_entry_y[id],0xff0000);\r
+//             i_img.setRGB(i_table._flagment_entry_x[id]+1,i_table._flagment_entry_y[id],0xff0000);\r
+//             i_img.setRGB(i_table._flagment_entry_x[id],i_table._flagment_entry_y[id]+1,0xff0000);\r
+//             i_img.setRGB(i_table._flagment_entry_x[id]+1,i_table._flagment_entry_y[id]+1,0xff0000);\r
+       }\r
+       \r
+       public RleLabelingTable createRelTable(RleImage rle,NyARBinRaster i_source,NyARRasterImageIO i_img)\r
+       {\r
+               // RELイメージの作成\r
+               rle.toRel(i_source);\r
+               // 1行目のテーブル登録\r
+               RleLabelingTable table = new RleLabelingTable(10000);\r
+               table.labeling(rle,0,H);\r
+               return table;\r
+       }\r
+\r
+       public LabelingTest() throws NyARException\r
+       {\r
+               this.addWindowListener(new WindowAdapter() {\r
+                       public void windowClosing(WindowEvent e)\r
+                       {\r
+                               System.exit(0);\r
+                       }\r
+               });\r
+       }\r
+\r
+       public static void main(String[] args)\r
+       {\r
+               try {\r
+                       LabelingTest app = new LabelingTest();\r
+                       app.setVisible(true);\r
+                       app.setBounds(0, 0, 640, 480);\r
+                       app.drawImage();\r
+               } catch (Exception e) {\r
+                       e.printStackTrace();\r
+               }\r
+       }\r
+\r
+       class RleImage\r
+       {\r
+               int _width;\r
+\r
+               int _height;\r
+\r
+               // RELデータ\r
+               short[] rle_img_l;// RELのフラグメント左\r
+\r
+               short[] rle_img_r;// RELのフラグメント右\r
+\r
+               // Rowデータ\r
+               int[] row_index;\r
+\r
+               short[] row_length;\r
+\r
+               int rle_buf_size;\r
+\r
+               public RleImage(int i_width, int i_height)\r
+               {\r
+                       final int size = i_width * i_height / 2;\r
+                       // 1/2に圧縮できることを想定。\r
+                       this.rle_img_l = new short[size]; // RELのフラグメント長\r
+                       this.rle_img_r = new short[size]; // RELの開始位置\r
+                       this.rle_buf_size = size;\r
+\r
+                       this.row_index = new int[i_height];\r
+                       this.row_length = new short[i_height];\r
+                       this._width = i_width;\r
+                       this._height = i_height;\r
+                       return;\r
+               }\r
+\r
+               /**\r
+                * binラスタからRELに変換する\r
+                * \r
+                * @param i_bin_raster\r
+                */\r
+               public void toRel(NyARBinRaster i_bin_raster)\r
+               {\r
+                       final int width = this._width;\r
+                       final int height = this._height;\r
+                       int[] in_buf = (int[]) i_bin_raster.getBufferReader().getBuffer();\r
+\r
+                       short current = 0;\r
+                       short r = -1;\r
+                       for (int y = 0; y < height; y++) {\r
+                               this.row_index[y] = current;\r
+                               // 行確定開始\r
+                               int row_index = y * width;\r
+                               int x = row_index;\r
+                               final int right_edge = (y + 1) * width - 1;\r
+                               while (x < right_edge) {\r
+                                       // 暗点(0)スキャン\r
+                                       if (in_buf[x] != 0) {\r
+                                               x++;\r
+                                               continue;\r
+                                       }\r
+                                       // 暗点発見→暗点長を調べる\r
+                                       r = (short) (x - row_index);\r
+                                       this.rle_img_l[current] = r;\r
+                                       r++;// 暗点+1\r
+                                       x++;\r
+                                       while (x < right_edge) {\r
+                                               if (in_buf[x] != 0) {\r
+                                                       // 明点(1)→暗点(0)配列終了>登録\r
+                                                       this.rle_img_r[current] = r;\r
+                                                       current++;\r
+                                                       x++;// 次点の確認。\r
+                                                       r = -1;// 右端の位置を0に。\r
+                                                       break;\r
+                                               } else {\r
+                                                       // 暗点(0)長追加\r
+                                                       r++;\r
+                                                       x++;\r
+                                               }\r
+                                       }\r
+                               }\r
+                               // 最後の1点だけ判定方法が少し違うの。\r
+                               if (in_buf[x] != 0) {\r
+                                       // 明点→rカウント中なら暗点配列終了>登録\r
+                                       if (r >= 0) {\r
+                                               this.rle_img_r[current] = r;\r
+                                               current++;\r
+                                       }\r
+                               } else {\r
+                                       // 暗点→カウント中でなければl1で追加\r
+                                       if (r >= 0) {\r
+                                               this.rle_img_r[current] = (short) (x + 1);\r
+                                       } else {\r
+                                               // 最後の1点の場合\r
+                                               this.rle_img_l[current] = (short) (width - 1);\r
+                                               this.rle_img_r[current] = (short) (width);\r
+                                       }\r
+                                       current++;\r
+                               }\r
+                               // 行確定\r
+                               this.row_length[y] = (short) (current - this.row_index[y]);\r
+                       }\r
+               }\r
+\r
+               public void fromRel(NyARBinRaster i_bin_raster)\r
+               {\r
+\r
+               }\r
+       }\r
+\r
+       // RleImageをラベリングする。\r
+       class RleLabelingTable\r
+       {\r
+               short[] rle_img_id;\r
+\r
+               short[] _fragment_id; // フラグメントラベルのインデクス\r
+\r
+               int[] _fragment_area; // フラグメントラベルの領域数\r
+\r
+               int[] _fragment_pos_x; // フラグメントラベルの位置\r
+\r
+               int[] _fragment_pos_y; // フラグメントラベルの位置\r
+\r
+               short[] _flagment_entry_x; // フラグメントラベルの位置\r
+\r
+               short[] _flagment_entry_y; // フラグメントラベルの位置\r
+\r
+               short number_of_fragment; // 現在のフラグメントの数\r
+\r
+               public RleLabelingTable(int i_max_fragment)\r
+               {\r
+                       this.rle_img_id = new short[i_max_fragment];\r
+                       this._fragment_id = new short[i_max_fragment];\r
+                       this._fragment_area = new int[i_max_fragment];\r
+                       this._fragment_pos_x = new int[i_max_fragment];\r
+                       this._fragment_pos_y = new int[i_max_fragment];\r
+                       this._flagment_entry_x = new short[i_max_fragment];\r
+                       this._flagment_entry_y = new short[i_max_fragment];\r
+               }\r
+\r
+               private void addFragment(RleImage i_rel_img, short i_nof, int i_row_index, int i_rel_index)\r
+               {\r
+                       this.rle_img_id[i_rel_index] = i_nof;// REL毎の固有ID\r
+                       this._fragment_id[i_nof] = i_nof;\r
+                       this._flagment_entry_x[i_nof] = i_rel_img.rle_img_l[i_rel_index];\r
+                       this._flagment_entry_y[i_nof] = (short) i_row_index;\r
+                       this._fragment_area[i_nof] = i_rel_img.rle_img_r[i_rel_index] - i_rel_img.rle_img_l[i_rel_index];\r
+                       return;\r
+               }\r
+\r
+\r
+\r
+               // 指定した行のフラグメントをマージします。\r
+               public void labeling(RleImage i_rel_img, int i_top, int i_bottom)\r
+               {\r
+                       short[] rle_l = i_rel_img.rle_img_l;\r
+                       short[] rle_r = i_rel_img.rle_img_r;\r
+                       short nof = this.number_of_fragment;\r
+                       // 初段登録\r
+                       int index = i_rel_img.row_index[i_top];\r
+                       int eol = i_rel_img.row_length[i_top];\r
+                       for (int i = index; i < index + eol; i++) {\r
+                               // フラグメントID=フラグメント初期値、POS=Y値、RELインデクス=行\r
+                               addFragment(i_rel_img, nof, i_top, i);\r
+                               nof++;\r
+                               // nofの最大値チェック\r
+                       }\r
+                       // 次段結合\r
+                       for (int y = i_top+1; y < i_bottom; y++) {\r
+                               int index_prev = i_rel_img.row_index[y - 1];\r
+                               int eol_prev = index_prev + i_rel_img.row_length[y - 1];\r
+                               index = i_rel_img.row_index[y];\r
+                               eol = index + i_rel_img.row_length[y];\r
+\r
+                               SCAN_CUR:for (int i = index; i < eol; i++) {\r
+                                       // index_prev,len_prevの位置を調整する\r
+                                       short id = -1;\r
+                                       //チェックすべきprevがあれば確認\r
+                                       SCAN_PREV: while (index_prev < eol_prev) {\r
+                                               if (rle_l[i] - rle_r[index_prev] > 0) {// 0なら8方位ラベリング\r
+                                                       // prevがcurの左方にある→次のフラグメントを探索\r
+                                                       index_prev++;\r
+                                                       continue;\r
+                                               } else if (rle_l[index_prev] - rle_r[i] > 0) {// 0なら8方位ラベリングになる\r
+                                                       // prevがcur右方にある→独立フラグメント\r
+                                                       addFragment(i_rel_img, nof, y, i);\r
+                                                       nof++;\r
+                                                       // 次のindexをしらべる\r
+                                                       continue SCAN_CUR;\r
+                                               }\r
+                                               // 結合対象->prevのIDをコピーして、対象フラグメントの情報を更新\r
+                                               id = this._fragment_id[this.rle_img_id[index_prev]];\r
+                                               this.rle_img_id[i] = id;\r
+                                               this._fragment_area[id] += (rle_r[i] - rle_l[i]);\r
+                                               // エントリポイントの情報をコピー\r
+                                               this._flagment_entry_x[id] = this._flagment_entry_x[this.rle_img_id[index_prev]];\r
+                                               this._flagment_entry_y[id] = this._flagment_entry_y[this.rle_img_id[index_prev]];\r
+                                               //多重リンクの確認\r
+\r
+                                               index_prev++;\r
+                                               while (index_prev < eol_prev) {\r
+                                                       if (rle_l[i] - rle_r[index_prev] > 0) {// 0なら8方位ラベリング\r
+                                                               // prevがcurの左方にある→prevはcurに連結していない。\r
+                                                               break SCAN_PREV;\r
+                                                       } else if (rle_l[index_prev] - rle_r[i] > 0) {// 0なら8方位ラベリングになる\r
+                                                               // prevがcurの右方にある→prevはcurに連結していない。\r
+                                                               index_prev--;\r
+                                                               continue SCAN_CUR;\r
+                                                       }\r
+                                                       // prevとcurは連結している。\r
+                                                       final short prev_id = this.rle_img_id[index_prev];\r
+                                                       if (id != prev_id) {\r
+                                                               this._fragment_area[id] += this._fragment_area[prev_id];\r
+                                                               this._fragment_area[prev_id] = 0;\r
+                                                               // 結合対象->現在のidをインデクスにセット\r
+                                                               this._fragment_id[prev_id]=id;\r
+                                                               // エントリポイントを訂正\r
+                                                               if (this._flagment_entry_y[id] > this._flagment_entry_y[prev_id]) {\r
+                                                                       // 現在のエントリポイントの方が下にある。(何もしない)\r
+                                                               }\r
+                                                               if (this._flagment_entry_y[id] < this._flagment_entry_y[prev_id]) {\r
+                                                                       // 現在のエントリポイントの方が上にある。(エントリポイントの交換)\r
+                                                                       this._flagment_entry_y[id] = this._flagment_entry_y[prev_id];\r
+                                                                       this._flagment_entry_x[id] = this._flagment_entry_x[prev_id];\r
+                                                               } else {\r
+                                                                       // 水平方向で小さい方がエントリポイント。\r
+                                                                       if (this._flagment_entry_x[id] > this._flagment_entry_x[prev_id]) {\r
+                                                                               this._flagment_entry_y[id] = this._flagment_entry_y[prev_id];\r
+                                                                               this._flagment_entry_x[id] = this._flagment_entry_x[prev_id];\r
+                                                                       }\r
+                                                               }\r
+                                                       }\r
+                                                       index_prev++;\r
+                                               }\r
+                                               index_prev--;\r
+                                               break;\r
+                                       }\r
+                                       // curにidが割り当てられたかを確認\r
+                                       // 右端独立フラグメントを追加\r
+                                       if (id < 0) {\r
+                                               addFragment(i_rel_img, nof, y, i);\r
+                                               nof++;\r
+                                       }\r
+\r
+                               }\r
+                       }\r
+                       // フラグメントの数を更新\r
+                       this.number_of_fragment = nof;\r
+               }\r
        }\r
-    }\r
 }\r
+\r
+// REL圧縮配列を作成\r
+// REL結合\r
+// 面積計算\r
+// 参照インデクス化\r
+// ラベルイメージ化\r