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.dev;
\r
33 import jp.nyatla.nyartoolkit.NyARException;
\r
34 import jp.nyatla.nyartoolkit.core.labeling.NyARLabelOverlapChecker;
\r
35 import jp.nyatla.nyartoolkit.core.labeling.rlelabeling.*;
\r
36 import jp.nyatla.nyartoolkit.core.param.NyARCameraDistortionFactor;
\r
37 import jp.nyatla.nyartoolkit.core.squaredetect.NyARCoord2SquareVertexIndexes;
\r
38 import jp.nyatla.nyartoolkit.core.squaredetect.NyARSquare;
\r
39 import jp.nyatla.nyartoolkit.core.types.NyARDoublePoint2d;
\r
40 import jp.nyatla.nyartoolkit.core.types.NyARIntPoint2d;
\r
41 import jp.nyatla.nyartoolkit.core.types.NyARIntSize;
\r
42 import jp.nyatla.nyartoolkit.core.types.NyARLinear;
\r
43 import jp.nyatla.nyartoolkit.core.raster.*;
\r
44 import jp.nyatla.nyartoolkit.core.squaredetect.*;
\r
45 import jp.nyatla.nyartoolkit.core.param.*;
\r
53 public class NyARSquareDetector_Vector
\r
55 private static final int AR_AREA_MAX = 100000;// #define AR_AREA_MAX 100000
\r
56 private static final int AR_AREA_MIN = 70;// #define AR_AREA_MIN 70
\r
57 private final int _width;
\r
58 private final int _height;
\r
59 private final int[] _xcoord;
\r
60 private final int[] _ycoord;
\r
62 private final NyARLabeling_Rle _labeling;
\r
64 private final NyARLabelOverlapChecker<NyARRleLabelFragmentInfoStack.RleLabelFragmentInfo> _overlap_checker = new NyARLabelOverlapChecker<NyARRleLabelFragmentInfoStack.RleLabelFragmentInfo>(32,NyARRleLabelFragmentInfoStack.RleLabelFragmentInfo.class);
\r
65 private final SquareContourDetector_Vector _sqconvertor;
\r
66 private final NyARContourPickup _cpickup=new NyARContourPickup();
\r
67 private final NyARRleLabelFragmentInfoStack _stack;
\r
69 private final int _max_coord;
\r
71 * 最大i_squre_max個のマーカーを検出するクラスを作成する。
\r
75 public NyARSquareDetector_Vector(NyARCameraDistortionFactor i_dist_factor_ref,NyARIntSize i_size) throws NyARException
\r
77 this._width = i_size.w;
\r
78 this._height = i_size.h;
\r
79 //ラベリングのサイズを指定したいときはsetAreaRangeを使ってね。
\r
80 this._labeling = new NyARLabeling_Rle(this._width,this._height);
\r
81 this._labeling.setAreaRange(AR_AREA_MAX, AR_AREA_MIN);
\r
82 this._sqconvertor=new SquareContourDetector_Vector(i_size,i_dist_factor_ref);
\r
83 this._stack=new NyARRleLabelFragmentInfoStack(i_size.w*i_size.h*2048/(320*240)+32);//検出可能な最大ラベル数
\r
86 // 輪郭の最大長は画面に映りうる最大の長方形サイズ。
\r
87 int number_of_coord = (this._width + this._height) * 2;
\r
90 this._max_coord = number_of_coord;
\r
91 this._xcoord = new int[number_of_coord];
\r
92 this._ycoord = new int[number_of_coord];
\r
97 * arDetectMarker2を基にした関数
\r
98 * この関数はNyARSquare要素のうち、directionを除くパラメータを取得して返します。
\r
99 * directionの確定は行いません。
\r
101 * 解析する2値ラスタイメージを指定します。
\r
102 * @param o_square_stack
\r
103 * 抽出した正方形候補を格納するリスト
\r
104 * @throws NyARException
\r
106 public final void detectMarker(NyARGrayscaleRaster i_gs,int i_th,NyARSquareStack o_square_stack) throws NyARException
\r
108 final NyARRleLabelFragmentInfoStack flagment=this._stack;
\r
109 final NyARLabelOverlapChecker<NyARRleLabelFragmentInfoStack.RleLabelFragmentInfo> overlap = this._overlap_checker;
\r
112 o_square_stack.clear();
\r
115 final int label_num=this._labeling.labeling(i_gs,i_th, 0, i_gs.getHeight(), flagment);
\r
116 if (label_num < 1) {
\r
120 flagment.sortByArea();
\r
122 NyARRleLabelFragmentInfoStack.RleLabelFragmentInfo[] labels=flagment.getArray();
\r
124 final int xsize = this._width;
\r
125 final int ysize = this._height;
\r
126 final int coord_max = this._max_coord;
\r
127 int[] xcoord = this._xcoord;
\r
128 int[] ycoord = this._ycoord;
\r
132 overlap.setMaxLabels(label_num);
\r
134 for (int i=0; i < label_num; i++) {
\r
135 final NyARRleLabelFragmentInfoStack.RleLabelFragmentInfo label_pt=labels[i];
\r
136 final int label_area = label_pt.area;
\r
138 // クリップ領域が画面の枠に接していれば除外
\r
139 if (label_pt.clip_l == 0 || label_pt.clip_r == xsize-1){
\r
142 if (label_pt.clip_t == 0 || label_pt.clip_b == ysize-1){
\r
145 // 既に検出された矩形との重なりを確認
\r
146 if (!overlap.check(label_pt)) {
\r
152 final int coord_num = _cpickup.getContour(i_gs,i_th,label_pt.entry_x,label_pt.clip_t, coord_max, xcoord, ycoord);
\r
153 if (coord_num == coord_max) {
\r
159 NyARSquare square_ptr = o_square_stack.prePush();
\r
160 if(!this._sqconvertor.coordToSquare(i_gs,xcoord,ycoord,coord_num,label_area,square_ptr)){
\r
161 o_square_stack.pop();// 頂点の取得が出来なかったので破棄
\r
164 // 検出済の矩形の属したラベルを重なりチェックに追加する。
\r
165 overlap.push(label_pt);
\r
173 public NyARRleLabelFragmentInfoStack _getFragmentStack()
\r
175 return this._stack;
\r
177 /********************************************************************************
\r
181 ********************************************************************************/
\r
182 private class SquareContourDetector_Vector
\r
184 private final NyARObserv2IdealMap2 _distmap;
\r
185 private final int[] __detectMarker_mkvertex = new int[4];
\r
186 private final NyARCoord2SquareVertexIndexes _coord2vertex=new NyARCoord2SquareVertexIndexes();
\r
187 public SquareContourDetector_Vector(NyARIntSize i_size,NyARCameraDistortionFactor i_distfactor_ref)
\r
189 this._distmap=new NyARObserv2IdealMap2(i_distfactor_ref,i_size);
\r
193 public boolean coordToSquare(NyARGrayscaleRaster i_raster,int[] i_xcoord,int[] i_ycoord,int i_coord_num,int i_label_area,NyARSquare o_square) throws NyARException
\r
196 final int[] mkvertex = this.__detectMarker_mkvertex;
\r
199 if (!this._coord2vertex.getVertexIndexes(i_xcoord, i_ycoord,i_coord_num, i_label_area, mkvertex)) {
\r
200 // 頂点の取得が出来なかったので破棄
\r
204 if (!getSquareLine(i_raster,mkvertex, i_xcoord, i_ycoord,i_coord_num, o_square)){
\r
211 * 指定した範囲の輪郭点ベクトル・座標を、加算する。
\r
221 private boolean addCoordVecPos(NyARGrayscaleRaster i_raster,int[] i_xcoord, int[] i_ycoord,int i_st,int i_ed,NyARIntPoint2d io_vecsum)
\r
227 for(int i=i_st;i<i_ed;i++){
\r
229 if(i_xcoord[i]<1 || i_ycoord[i]<1 || i_xcoord[i]>=319 || i_ycoord[i]>=239){
\r
233 i_raster.getPixelVector8(i_xcoord[i],i_ycoord[i],io_vecsum);
\r
243 private NyARDoublePoint2d __work_pos=new NyARDoublePoint2d();
\r
245 private boolean getSquareLine(NyARGrayscaleRaster i_raster,int[] i_mkvertex, int[] i_xcoord, int[] i_ycoord,int i_cood_num, NyARSquare o_square) throws NyARException
\r
247 final NyARLinear[] l_line = o_square.line;
\r
248 final NyARDoublePoint2d[] l_sqvertex = o_square.sqvertex;
\r
249 final NyARIntPoint2d[] l_imvertex = o_square.imvertex;
\r
250 final NyARDoublePoint2d idealcenter=this.__work_pos;
\r
252 NyARIntPoint2d vecsum=new NyARIntPoint2d();
\r
253 for (int i = 0; i < 4; i++){
\r
255 int ver1=i_mkvertex[i];
\r
256 int ver2=i_mkvertex[(i+1)%4];
\r
261 if(ver2>=i_mkvertex[i]){
\r
262 //頂点[i]から頂点[i+1]までの輪郭が、1区間にあるとき
\r
263 w1 = (double) (ver2 - ver1 + 1) * 0.05 + 0.5;
\r
265 st = (int) (ver1+w1);
\r
266 ed = (int) (ver2 - w1);
\r
268 //頂点[i]から頂点[i+1]までの輪郭が、2区間に分かれているとき
\r
269 w1 = (double) (ver2+i_cood_num-ver1+1)%i_cood_num * 0.05 + 0.5;
\r
271 st = (int) (ver1+w1)%i_cood_num;
\r
272 ed = (int) (ver2+i_cood_num-w1)%i_cood_num;
\r
274 vecsum.x=vecsum.y=0;
\r
279 addCoordVecPos(i_raster,i_xcoord,i_ycoord,st,ed+1,vecsum);
\r
280 this._distmap.getIdealCoodCenter(i_xcoord, i_ycoord,st,n,idealcenter);
\r
284 n=ed+i_cood_num-st+1;
\r
285 addCoordVecPos(i_raster,i_xcoord,i_ycoord,st,i_cood_num,vecsum);
\r
286 addCoordVecPos(i_raster,i_xcoord,i_ycoord,0,ed,vecsum);
\r
288 this._distmap.getIdealCoodCenter(i_xcoord, i_ycoord,st,i_cood_num-st,idealcenter);
\r
291 this._distmap.getIdealCoodCenter(i_xcoord, i_ycoord,0,ed+1,idealcenter);
\r
292 idealcenter.x=(idealcenter.x+cx)/2;
\r
293 idealcenter.y=(idealcenter.y+cy)/2;
\r
295 //中央値を歪修正(ほんとはピクセル単位にゆがみ矯正するべきだと思う)
\r
297 double l=Math.sqrt((double)(vecsum.x*vecsum.x+vecsum.y*vecsum.y));
\r
298 final NyARLinear l_line_i = l_line[i];
\r
300 l_line_i.dy = vecsum.x/l;
\r
301 l_line_i.dx = -vecsum.y/l;
\r
303 l_line_i.c = -(l_line_i.dy * (idealcenter.x) + l_line_i.dx * (idealcenter.y));
\r
305 // 頂点インデクスから頂点座標を得て保存
\r
306 l_imvertex[i].x = i_xcoord[ver1];
\r
307 l_imvertex[i].y = i_ycoord[ver1];
\r
310 for(int i=0;i<4;i++)
\r
312 if(!NyARLinear.crossPos(l_line[i],l_line[(i + 3) % 4],l_sqvertex[i])){
\r
321 * 輪郭線の中心位置を計算する関数を追加したマップクラス
\r
323 private class NyARObserv2IdealMap2 extends NyARObserv2IdealMap
\r
325 public NyARObserv2IdealMap2(NyARCameraDistortionFactor i_distfactor,NyARIntSize i_screen_size)
\r
327 super(i_distfactor,i_screen_size);
\r
330 * 歪み矯正した座標における、各座標の合計値を
\r
337 public void getIdealCoodCenter(int[] i_x_coord, int[] i_y_coord,int i_start, int i_num,NyARDoublePoint2d o_center)
\r
342 final double[] mapx=this._mapx;
\r
343 final double[] mapy=this._mapy;
\r
344 final int stride=this._stride;
\r
345 for (int j = 0; j < i_num; j++){
\r
346 idx=i_x_coord[i_start + j]+i_y_coord[i_start + j]*stride;
\r
350 o_center.x=x/(double)i_num;
\r
351 o_center.y=y/(double)i_num;
\r