2 * PROJECT: NyARToolkit
\r
3 * --------------------------------------------------------------------------------
\r
4 * This work is based on the original ARToolKit developed by
\r
7 * HITLab, University of Washington, Seattle
\r
8 * http://www.hitl.washington.edu/artoolkit/
\r
10 * The NyARToolkit is Java edition ARToolKit class library.
\r
11 * Copyright (C)2008-2009 Ryo Iizuka
\r
13 * This program is free software: you can redistribute it and/or modify
\r
14 * it under the terms of the GNU General Public License as published by
\r
15 * the Free Software Foundation, either version 3 of the License, or
\r
16 * (at your option) any later version.
\r
18 * This program is distributed in the hope that it will be useful,
\r
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
21 * GNU General Public License for more details.
\r
23 * You should have received a copy of the GNU General Public License
\r
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
\r
26 * For further information please contact.
\r
27 * http://nyatla.jp/nyatoolkit/
\r
28 * <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
\r
31 package jp.nyatla.nyartoolkit.core.squaredetect;
\r
33 import jp.nyatla.nyartoolkit.NyARException;
\r
34 import jp.nyatla.nyartoolkit.core.raster.*;
\r
35 import jp.nyatla.nyartoolkit.core.types.*;
\r
38 * このクラスは、輪郭線の抽出クラスです。
\r
39 * 画像中の1点を開始点として、8方位探索で輪郭線を抽出します。出力は輪郭点の配列です。
\r
40 * <p>入力できる画素形式 - {@link #getContour}に入力できる画素形式に制限があります。<br/>
\r
41 * {@link NyARBinRaster}
\r
43 * <li>{@link NyARBufferType#INT1D_BIN_8}
\r
45 * {@link NyARGrayscaleRaster}
\r
47 * <li>{@link NyARBufferType#INT1D_GRAY_8}
\r
51 public class NyARContourPickup
\r
53 //巡回参照できるように、テーブルを二重化
\r
54 // 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6
\r
56 protected final static int[] _getContour_xdir = { 0, 1, 1, 1, 0,-1,-1,-1 , 0, 1, 1, 1, 0,-1,-1};
\r
58 protected final static int[] _getContour_ydir = {-1,-1, 0, 1, 1, 1, 0,-1 ,-1,-1, 0, 1, 1, 1, 0};
\r
61 * この関数は、ラスタの指定点を基点に、輪郭線を抽出します。
\r
62 * 開始点は、輪郭の一部である必要があります。
\r
63 * 通常は、ラべリングの結果の上辺クリップとX軸エントリポイントを開始点として入力します。
\r
65 * 輪郭線を抽出するラスタを指定します。
\r
71 * 輪郭点を格納するオブジェクトを指定します。
\r
73 * 輪郭線がo_coordの長さを超えた場合、falseを返します。
\r
74 * @throws NyARException
\r
76 public boolean getContour(NyARBinRaster i_raster,int i_entry_x,int i_entry_y,NyARIntCoordinates o_coord) throws NyARException
\r
78 assert(i_raster.isEqualBufferType(NyARBufferType.INT1D_BIN_8));
\r
79 NyARIntSize s=i_raster.getSize();
\r
80 return impl_getContour(i_raster,0,0,s.w-1,s.h-1,0,i_entry_x,i_entry_y,o_coord);
\r
83 * この関数は、ラスタの指定点を基点に、画像の特定の範囲内から輪郭線を抽出します。
\r
84 * 開始点は、輪郭の一部である必要があります。
\r
85 * 通常は、ラべリングの結果の上辺クリップとX軸エントリポイントを開始点として入力します。
\r
87 * 輪郭線を抽出するラスタを指定します。
\r
89 * 輪郭線の抽出範囲を指定する矩形。i_rasterのサイズ内である必要があります。
\r
95 * 輪郭点を格納するオブジェクトを指定します。
\r
97 * 輪郭線がo_coordの長さを超えた場合、falseを返します。
\r
98 * @throws NyARException
\r
100 public boolean getContour(NyARBinRaster i_raster,NyARIntRect i_area,int i_entry_x,int i_entry_y,NyARIntCoordinates o_coord) throws NyARException
\r
102 assert(i_raster.isEqualBufferType(NyARBufferType.INT1D_BIN_8));
\r
103 return impl_getContour(i_raster,i_area.x,i_area.y,i_area.x+i_area.w-1,i_area.h+i_area.y-1,0,i_entry_x,i_entry_y,o_coord);
\r
106 * この関数は、ラスタの指定点を基点に、輪郭線を抽出します。
\r
107 * 開始点は、輪郭の一部である必要があります。
\r
108 * 通常は、ラべリングの結果の上辺クリップとX軸エントリポイントを開始点として入力します。
\r
110 * 輪郭線を抽出するラスタを指定します。
\r
112 * 輪郭とみなす暗点の敷居値を指定します。
\r
118 * 輪郭点を格納する配列を指定します。i_array_sizeよりも大きなサイズの配列が必要です。
\r
120 * 輪郭の抽出に成功するとtrueを返します。輪郭抽出に十分なバッファが無いと、falseになります。
\r
121 * @throws NyARException
\r
123 public boolean getContour(NyARGrayscaleRaster i_raster,int i_th,int i_entry_x,int i_entry_y,NyARIntCoordinates o_coord) throws NyARException
\r
125 assert(i_raster.isEqualBufferType(NyARBufferType.INT1D_GRAY_8));
\r
126 NyARIntSize s=i_raster.getSize();
\r
127 return impl_getContour(i_raster,0,0,s.w-1,s.h-1,i_th,i_entry_x,i_entry_y,o_coord);
\r
130 * この関数は、ラスタの指定点を基点に、画像の特定の範囲内から輪郭線を抽出します。
\r
131 * 開始点は、輪郭の一部である必要があります。
\r
132 * 通常は、ラべリングの結果の上辺クリップとX軸エントリポイントを開始点として入力します。
\r
134 * 輪郭線を抽出するラスタを指定します。
\r
136 * 輪郭線の抽出範囲を指定する矩形。i_rasterのサイズ内である必要があります。
\r
138 * 輪郭とみなす暗点の敷居値を指定します。
\r
144 * 輪郭点を格納するオブジェクトを指定します。
\r
146 * 輪郭線がo_coordの長さを超えた場合、falseを返します。
\r
147 * @throws NyARException
\r
149 public boolean getContour(NyARGrayscaleRaster i_raster,NyARIntRect i_area,int i_th,int i_entry_x,int i_entry_y,NyARIntCoordinates o_coord) throws NyARException
\r
151 assert(i_raster.isEqualBufferType(NyARBufferType.INT1D_GRAY_8));
\r
152 return impl_getContour(i_raster,i_area.x,i_area.y,i_area.x+i_area.w-1,i_area.h+i_area.y-1,i_th,i_entry_x,i_entry_y,o_coord);
\r
167 * @throws NyARException
\r
169 private boolean impl_getContour(INyARRaster i_raster,int i_l,int i_t,int i_r,int i_b,int i_th,int i_entry_x,int i_entry_y,NyARIntCoordinates o_coord) throws NyARException
\r
171 assert(i_t<=i_entry_x);
\r
172 NyARIntPoint2d[] coord=o_coord.items;
\r
173 final int[] xdir = _getContour_xdir;// static int xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1};
\r
174 final int[] ydir = _getContour_ydir;// static int ydir[8] = {-1,-1, 0, 1, 1, 1, 0,-1};
\r
176 final int[] buf=(int[])i_raster.getBuffer();
\r
177 final int width=i_raster.getWidth();
\r
178 //クリップ領域の上端に接しているポイントを得る。
\r
181 int max_coord=o_coord.items.length;
\r
183 coord[0].x = i_entry_x;
\r
184 coord[0].y = i_entry_y;
\r
190 dir = (dir + 5) % 8;//dirの正規化
\r
191 //ここは頑張ればもっと最適化できると思うよ。
\r
192 //4隅以外の境界接地の場合に、境界チェックを省略するとかね。
\r
193 if(c>i_l && c<i_r && r>i_t && r<i_b){
\r
194 for(;;){//gotoのエミュレート用のfor文
\r
195 //境界に接していないとき(暗点判定)
\r
196 if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
\r
200 if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
\r
204 if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
\r
208 if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
\r
212 if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
\r
216 if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
\r
220 if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
\r
224 if (buf[(r + ydir[dir])*width+(c + xdir[dir])] <= i_th) {
\r
228 //8方向全て調べたけどラベルが無いよ?
\r
229 throw new NyARException();
\r
234 for (i = 0; i < 8; i++){
\r
235 final int x=c + xdir[dir];
\r
236 final int y=r + ydir[dir];
\r
238 if(x>=i_l && x<=i_r && y>=i_t && y<=i_b){
\r
239 if (buf[(y)*width+(x)] <= i_th) {
\r
243 dir++;//倍長テーブルを参照するので問題なし
\r
246 //8方向全て調べたけどラベルが無いよ?
\r
247 throw new NyARException();// return(-1);
\r
251 // xcoordとycoordをc,rにも保存
\r
254 coord[coord_num].x = c;
\r
255 coord[coord_num].y = r;
\r
257 if (c == i_entry_x && r == i_entry_y){
\r
258 //開始点と同じピクセルに到達したら、終点の可能性がある。
\r
261 if (coord_num == max_coord) {
\r
266 dir = (dir + 5) % 8;//dirの正規化
\r
268 for (i = 0; i < 8; i++){
\r
269 final int x=c + xdir[dir];
\r
270 final int y=r + ydir[dir];
\r
272 if(x>=i_l && x<=i_r && y>=i_t && y<=i_b){
\r
273 if (buf[(y)*width+(x)] <= i_th) {
\r
277 dir++;//倍長テーブルを参照するので問題なし
\r
280 //8方向全て調べたけどラベルが無いよ?
\r
281 throw new NyARException();
\r
283 //得たピクセルが、[1]と同じならば、末端である。
\r
286 if(coord[1].x ==c && coord[1].y ==r){
\r
288 o_coord.length=coord_num;
\r
292 coord[coord_num].x = c;
\r
293 coord[coord_num].y = r;
\r
298 if (coord_num == max_coord) {
\r