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 version ARToolkit class library.
\r
11 * Copyright (C)2008 R.Iizuka
\r
13 * This program is free software; you can redistribute it and/or
\r
14 * modify it under the terms of the GNU General Public License
\r
15 * as published by the Free Software Foundation; either version 2
\r
16 * of the License, or (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 framework; if not, write to the Free Software
\r
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
27 * For further information please contact.
\r
28 * http://nyatla.jp/nyatoolkit/
\r
29 * <airmail(at)ebony.plala.or.jp>
\r
32 package jp.nyatla.nyartoolkit.dev;
\r
34 import jp.nyatla.nyartoolkit.NyARException;
\r
35 import jp.nyatla.nyartoolkit.core.NyARSquare;
\r
36 import jp.nyatla.nyartoolkit.core.raster.rgb.*;
\r
37 import jp.nyatla.nyartoolkit.core.rasterreader.*;
\r
38 import jp.nyatla.nyartoolkit.core.types.*;
\r
39 import jp.nyatla.nyartoolkit.core.utils.*;
\r
40 import jp.nyatla.nyartoolkit.core.labeling.NyARLabelingLabel;
\r
41 import jp.nyatla.nyartoolkit.core.pickup.*;
\r
42 import jp.nyatla.nyartoolkit.nyidmarker.MarkerPattEncoder;
\r
43 import jp.nyatla.nyartoolkit.nyidmarker.PerspectivePixelReader;
\r
48 * 1区間にある1個のエッジ位置を推定するクラスです。
\r
51 class NyARSingleEdgeFinder2
\r
53 public static class TEdgeInfo
\r
55 double point; //検出したエッジの位置
\r
58 private int[] _work;
\r
60 private int _height;
\r
61 public NyARSingleEdgeFinder2(int i_width,int i_height)
\r
63 this._work=new int[(i_width>i_height?i_width:i_height)+1];
\r
64 this._work[this._work.length-1]=0;
\r
65 this._width=i_width;
\r
66 this._height=i_height;
\r
70 * この関数は、一区間に1個のエッジが含まれていると仮定して、その位置を推定します。
\r
71 * [n]個の配列を与えた場合、[n+2]~[n-1]の間にあるエッジを検出します。
\r
79 public boolean scanSingleEdgeLeftToRight(int[] i_pixcel,int i_y,TEdgeInfo o_out)
\r
81 final int[] temp=this._work;
\r
83 final int length=this._width-1;
\r
84 int p=i_y*this._width;
\r
85 for(int i2=0;i2<length;i2++){
\r
86 temp[i2]=i_pixcel[p+1]-i_pixcel[p];
\r
89 return scanSingleEdge(temp,length,o_out);
\r
93 * この関数は、1区間に1個のエッジが含まれていると仮定して、その位置を推定します。
\r
94 * [n]個の配列を与えた場合、[n+2]~[n-1]の間にあるエッジを検出します。
\r
102 public boolean scanSingleEdgeRightToLeft(int[] i_pixcel,int i_y,TEdgeInfo o_out)
\r
104 final int[] temp=this._work;
\r
106 final int length=this._width-1;
\r
107 int p=(i_y+1)*this._width-1;
\r
108 for(int i2=0;i2<length;i2++){
\r
109 temp[i2]=i_pixcel[p-1]-i_pixcel[p];
\r
112 return scanSingleEdge(temp,length,o_out);
\r
114 public boolean scanSingleEdgeTopToBottom(int[] i_pixcel,int i_x,TEdgeInfo o_out)
\r
116 final int[] temp=this._work;
\r
118 final int step=this._width;
\r
119 final int length=this._height-1;
\r
121 for(int i2=0;i2<length;i2++){
\r
122 temp[i2]=i_pixcel[p+step]-i_pixcel[p];
\r
125 return scanSingleEdge(temp,length,o_out);
\r
127 public boolean scanSingleEdgeBottomToTop(int[] i_pixcel,int i_x,TEdgeInfo o_out)
\r
129 final int[] temp=this._work;
\r
131 final int step=this._width;
\r
132 final int length=this._height-1;
\r
133 int p=i_x+step*length;
\r
134 for(int i2=0;i2<length;i2++){
\r
135 temp[i2]=i_pixcel[p-step]-i_pixcel[p];
\r
138 return scanSingleEdge(temp,length,o_out);
\r
140 private boolean scanSingleEdge(int[] i_pixels,int i_length,TEdgeInfo o_out)
\r
142 //微分(2回目)して、極値2か所を得る
\r
143 int max_index,min_index;
\r
144 int length=i_length-1;
\r
145 max_index=min_index=0;
\r
146 int max_value,min_value;
\r
147 max_value=min_value=0;
\r
148 for(int i2=0;i2<length;i2++){
\r
149 int t=i_pixels[i2+1]-i_pixels[i2];
\r
159 //同符号である場合、範囲内にエッジはない
\r
160 if(max_value*min_value>=0){
\r
163 o_out.point=(max_index+min_index)/2.0;
\r
164 o_out.sub=max_value-min_value;
\r
167 public int scanEdgeLeftToRight(int[] i_pixel,int i_y,int i_noise_th,double[] o_edge_index)
\r
169 final int[] temp=this._work;
\r
171 final int length=this._width-1;
\r
172 int p=i_y*this._width;
\r
173 for(int i2=0;i2<length;i2++){
\r
174 temp[i2]=i_pixel[p+1]-i_pixel[p];
\r
177 //0終端させるために1要素を後続に追加
\r
178 return scanEdge(temp,length+1,i_noise_th,o_edge_index);
\r
180 private int scanEdge(int[] i_pixels,int i_length,int i_noise_th,double[] o_out)
\r
183 final int length=i_length;
\r
185 for(int i2=0;i2<length;i2++){
\r
186 int t=i_pixels[i2];
\r
190 for(;i2<length;i2++){
\r
195 o_out[points]=(st+i2)/2.0;
\r
206 }else if(t<-i_noise_th){
\r
209 for(;i2<length;i2++){
\r
214 o_out[points]=(st+i2)/2.0;
\r
229 * 指定した配列をノイズパターンとして、ノイズ値を計算します。
\r
230 * このノイズ値は、scanEdgeのノイズ値として使用できます。
\r
235 public int getNoiseValue(int[] i_pixels,int i_length)
\r
237 //1回微分して、その最大値と最小値を計算
\r
238 int length=i_length-1;
\r
239 int max_value,min_value;
\r
240 max_value=min_value=0;
\r
241 for(int i2=0;i2<length;i2++){
\r
242 int t=i_pixels[i2+1]-i_pixels[i2];
\r
250 return (-min_value>max_value)?-min_value:max_value;
\r
254 class MarkerEncoder2
\r
256 private final static int[] _bit_table_3={
\r
257 25, 26, 27, 28, 29, 30, 31,
\r
258 48, 9, 10, 11, 12, 13, 32,
\r
259 47, 24, 1, 2, 3, 14, 33,
\r
260 46, 23, 8, 0, 4, 15, 34,
\r
261 45, 22, 7, 6, 5, 16, 35,
\r
262 44, 21, 20, 19, 18, 17, 36,
\r
263 43, 42, 41, 40, 39, 38, 37
\r
265 private final static int[] _bit_table_2={
\r
270 21, 20, 19, 18, 17};
\r
271 private final static int[][] _bit_tables={
\r
272 _bit_table_2,_bit_table_3
\r
276 * RECT(1):[1]=(1-8)
\r
277 * RECT(2):[2]=(9-16),[3]=(17-24)
\r
278 * RECT(3):[4]=(25-32),[5]=(33-40),[6]=(41-48)
\r
281 int[] _bits=new int[16];
\r
282 int[] _work=new int[16];
\r
284 public void setBitByBitIndex(int i_index_no,int i_value)
\r
286 assert i_value==0 || i_value==1;
\r
287 final int bit_no=this._bit_table[i_index_no];
\r
289 this._bits[0]=i_value;
\r
291 int bidx=(bit_no-1)/8+1;
\r
292 int sidx=(bit_no-1)%8;
\r
293 this._bits[bidx]=(this._bits[bidx]&(~(0x01<<sidx)))|(i_value<<sidx);
\r
298 public void setBit(int i_bit_no,int i_value)
\r
300 assert i_value==0 || i_value==1;
\r
302 this._bits[0]=i_value;
\r
304 int bidx=(i_bit_no-1)/8+1;
\r
305 int sidx=(i_bit_no-1)%8;
\r
306 this._bits[bidx]=(this._bits[bidx]&(~(0x01<<sidx)))|(i_value<<sidx);
\r
310 public int getBit(int i_bit_no)
\r
313 return this._bits[0];
\r
315 int bidx=(i_bit_no-1)/8+1;
\r
316 int sidx=(i_bit_no-1)%8;
\r
317 return (this._bits[bidx]>>(sidx))&(0x01);
\r
320 public boolean initEncoder(int i_model)
\r
322 if(i_model>=4 || i_model<2){
\r
323 //Lv4以降に対応する時は、この制限を変える。
\r
326 this._bit_table=_bit_tables[i_model-2];
\r
327 this._model=i_model;
\r
330 private int getDirection()
\r
333 switch(this._model){
\r
336 t=this._bits[2] & 0x07;
\r
337 r=(this._bits[2] & 0x70)>>4;
\r
338 b=this._bits[3] & 0x07;
\r
339 l=(this._bits[3] & 0x70)>>4;
\r
348 return (b!=0x05 && l!=0x05)?2:-2;
\r
350 return (b!=0x05 && r!=0x05)?3:-2;
\r
354 return (t!=0x05 && l!=0x05)?1:-2;
\r
356 return (t!=0x05 && r!=0x05)?0:-2;
\r
362 public boolean encode()
\r
364 int d=getDirection();
\r
370 rotateDirection(d);
\r
375 private void rotateDirection(int i_direction)
\r
377 int sl=i_direction*2;
\r
383 this._bits[1]=(w1<<sl)|(w1>>sr);
\r
388 w1=this._bits[2]|(this._bits[3]<<8);
\r
389 w1=(w1<<sl)|(w1>>sr);
\r
390 this._bits[2]=w1 & 0xff;
\r
391 this._bits[3]=(w1>>8) & 0xff;
\r
400 w1=this._bits[4]|(this._bits[5]<<8)|(this._bits[6]<<16);
\r
401 w1=(w1<<sl)|(w1>>sr);
\r
402 this._bits[4]=w1 & 0xff;
\r
403 this._bits[5]=(w1>>8) & 0xff;
\r
404 this._bits[6]=(w1>>16) & 0xff;
\r
409 //RECT4(Lv4以降はここの制限を変える)
\r
410 // shiftLeft(this._bits,7,3,i_direction*);
\r
414 public void shiftLeft(int[] i_pack,int i_start,int i_length,int i_ls)
\r
416 int[] work=this._work;
\r
418 final int mod_shift=i_ls%8;
\r
419 for(int i=i_length-1;i>=1;i--){
\r
420 work[i]=(i_pack[i+i_start]<<mod_shift)|(0xff&(i_pack[i+i_start-1]>>(8-mod_shift)));
\r
422 work[0]=(i_pack[i_start]<<mod_shift)|(0xff&(i_pack[i_start+i_length-1]>>(8-mod_shift)));
\r
424 final int byte_shift=(i_ls/8)%i_length;
\r
425 for(int i=i_length-1;i>=0;i--){
\r
426 i_pack[(byte_shift+i)%i_length+i_start]=0xff & work[i];
\r
436 * NyARColorPatt_NyIdMarkerがラスタからPerspective変換して読みだすためのクラス
\r
439 class PerspectivePixelReader2 extends NyARPerspectiveParamGenerator_O1
\r
441 private double[] _cparam=new double[8];
\r
443 public PerspectivePixelReader2(int i_local_x,int i_local_y,int i_width, int i_height)
\r
445 super(i_local_x,i_local_y,i_width,i_height);
\r
446 this._temp1=new int[i_width];
\r
447 this._temp2=new int[i_width];
\r
448 this._pixcel_temp=new int[i_width*3];
\r
452 private int[] _temp1;
\r
453 private int[] _temp2;
\r
454 private int[] _pixcel_temp;
\r
455 private INyARRgbRaster _raster;
\r
456 public void setSourceRaster(INyARRgbRaster i_raster)
\r
458 this._raster=i_raster;
\r
461 public boolean setSourceSquare(NyARIntPoint2d[] i_vertex)throws NyARException
\r
463 return this.getParam(i_vertex, this._cparam);
\r
465 public void rectPixels(int i_lt_x,int i_lt_y,int i_width,int i_height,int[] o_pixcel)throws NyARException
\r
467 final double[] cpara=this._cparam;
\r
468 final INyARRgbPixelReader reader=this._raster.getRgbPixelReader();
\r
469 final int[] ref_x=this._temp1;
\r
470 final int[] ref_y=this._temp2;
\r
471 final int[] pixcel_temp=this._pixcel_temp;
\r
474 for(int i=0;i<i_height;i++){
\r
475 //1列分のピクセルのインデックス値を計算する。
\r
476 int cy0=1+i+i_lt_y;
\r
477 double cpy0_12=cpara[1]*cy0+cpara[2];
\r
478 double cpy0_45=cpara[4]*cy0+cpara[5];
\r
479 double cpy0_7=cpara[7]*cy0+1.0;
\r
481 for(int i2=0;i2<i_width;i2++)
\r
483 int cx0=1+i2+i_lt_x;
\r
485 double cp6_0=cpara[6]*cx0;
\r
486 double cpx0_0=cpara[0]*cx0;
\r
487 double cpx3_0=cpara[3]*cx0;
\r
489 final double d=cp6_0+cpy0_7;
\r
490 ref_x[pt]=(int)((cpx0_0+cpy0_12)/d);
\r
491 ref_y[pt]=(int)((cpx3_0+cpy0_45)/d);
\r
494 //1行分のピクセルを取得(場合によっては専用アクセサを書いた方がいい)
\r
495 reader.getPixelSet(ref_x,ref_y,i_width,pixcel_temp);
\r
496 //グレースケールにしながら、line→mapへの転写
\r
497 for(int i2=0;i2<i_width;i2++){
\r
499 o_pixcel[out_index]=(pixcel_temp[index+0]+pixcel_temp[index+1]+pixcel_temp[index+2])/3;
\r
509 //タイミングパターン用のパラメタ(FRQ_POINTS*FRQ_STEPが100を超えないようにすること)
\r
510 private static int FRQ_STEP=2;
\r
511 private static int FRQ_POINTS=45;
\r
512 public static int FRQ_EDGE=5;
\r
516 * i_y1行目とi_y2行目を平均して、タイミングパターンの周波数を得ます。
\r
517 * LHLを1周期として、たとえばLHLHLの場合は2を返します。LHLHやHLHL等の始端と終端のレベルが異なるパターンを
\r
524 * @param o_edge_index
\r
525 * 検出したエッジ位置(H->L,L->H)のインデクスを受け取る配列です。
\r
526 * [FRQ_POINTS]以上の配列を指定してください。
\r
528 * @throws NyARException
\r
530 public int getRowFrequency(int i_y1,int i_th_h,int i_th_l,int[] o_edge_index)throws NyARException
\r
532 final double[] cpara=this._cparam;
\r
533 final INyARRgbPixelReader reader=this._raster.getRgbPixelReader();
\r
534 final int[] ref_x=this._temp1;
\r
535 final int[] ref_y=this._temp2;
\r
536 final int[] pixcel_temp=this._pixcel_temp;
\r
538 //2行分のピクセルインデックスを計算
\r
540 double cpy0_12=cpara[1]*cy0+cpara[2];
\r
541 double cpy0_45=cpara[4]*cy0+cpara[5];
\r
542 double cpy0_7=cpara[7]*cy0+1.0;
\r
546 for(int i2=0;i2<FRQ_POINTS;i2++)
\r
549 final int cx0=1+i2*FRQ_STEP+FRQ_EDGE;
\r
550 d=(cpara[6]*cx0)+cpy0_7;
\r
551 ref_x[pt]=(int)((cpara[0]*cx0+cpy0_12)/d);
\r
552 ref_y[pt]=(int)((cpara[3]*cx0+cpy0_45)/d);
\r
556 //ピクセルを取得(入力画像を多様化するならここから先を調整すること)
\r
557 reader.getPixelSet(ref_x,ref_y,FRQ_POINTS,pixcel_temp);
\r
558 return getFreqInfo(pixcel_temp,i_th_h,i_th_l,o_edge_index);
\r
560 public int getColFrequency(int i_x1,int i_th_h,int i_th_l,int[] o_edge_index)throws NyARException
\r
562 final double[] cpara=this._cparam;
\r
563 final INyARRgbPixelReader reader=this._raster.getRgbPixelReader();
\r
564 final int[] ref_x=this._temp1;
\r
565 final int[] ref_y=this._temp2;
\r
566 final int[] pixcel_temp=this._pixcel_temp;
\r
568 final int cx0=1+i_x1;
\r
569 final double cp6_0=cpara[6]*cx0;
\r
570 final double cpx0_0=cpara[0]*cx0;
\r
571 final double cpx3_0=cpara[3]*cx0;
\r
574 for(int i2=0;i2<FRQ_POINTS;i2++)
\r
577 int cy=1+i2*FRQ_STEP+FRQ_EDGE;
\r
578 double cpy_12=cpara[1]*cy+cpara[2];
\r
579 double cpy_45=cpara[4]*cy+cpara[5];
\r
580 double cpy_7=cpara[7]*cy+1.0;
\r
583 ref_x[pt]=(int)((cpx0_0+cpy_12)/d);
\r
584 ref_y[pt]=(int)((cpx3_0+cpy_45)/d);
\r
589 //ピクセルを取得(入力画像を多様化するならここから先を調整すること)
\r
590 reader.getPixelSet(ref_x,ref_y,FRQ_POINTS,pixcel_temp);
\r
591 return getFreqInfo(pixcel_temp,i_th_h,i_th_l,o_edge_index);
\r
595 * デバックすんだらstaticにしておk
\r
599 * @param o_edge_index
\r
602 private int getFreqInfo(int[] i_pixcels,int i_th_h,int i_th_l,int[] o_edge_index)
\r
608 while(i<FRQ_POINTS){
\r
610 while(i<FRQ_POINTS){
\r
611 final int index=i*3;
\r
612 final int pix=(i_pixcels[index+0]+i_pixcels[index+1]+i_pixcels[index+2])/3;
\r
615 o_edge_index[frq_l2h+frq_h2l]=i;
\r
623 while(i<FRQ_POINTS){
\r
624 final int index=i*3;
\r
625 final int pix=(i_pixcels[index+0]+i_pixcels[index+1]+i_pixcels[index+2])/3;
\r
628 o_edge_index[frq_l2h+frq_h2l]=i;
\r
636 return frq_l2h==frq_h2l?frq_l2h:-1;
\r
641 public boolean readDataBits(double[] i_index_x,double[] i_index_y,int i_size,int i_th,MarkerPattEncoder o_bitbuffer)throws NyARException
\r
644 assert i_size*4<this._width;
\r
646 final double[] cpara=this._cparam;
\r
648 final int[] ref_x=this._temp1;
\r
649 final int[] ref_y=this._temp2;
\r
650 final INyARRgbPixelReader reader=this._raster.getRgbPixelReader();
\r
651 final int[] pixcel_temp=this._pixcel_temp;
\r
654 for(int i=0;i<i_size;i++){
\r
655 //1列分のピクセルのインデックス値を計算する。
\r
656 double cy0=1+i_index_y[i*2+0];
\r
657 double cy1=1+i_index_y[i*2+1];
\r
658 double cpy0_12=cpara[1]*cy0+cpara[2];
\r
659 double cpy0_45=cpara[4]*cy0+cpara[5];
\r
660 double cpy0_7=cpara[7]*cy0+1.0;
\r
661 double cpy1_12=cpara[1]*cy1+cpara[2];
\r
662 double cpy1_45=cpara[4]*cy1+cpara[5];
\r
663 double cpy1_7=cpara[7]*cy1+1.0;
\r
666 for(int i2=0;i2<i_size;i2++)
\r
670 double cx0=1+i_index_x[i2*2+0];
\r
671 double cx1=1+i_index_x[i2*2+1];
\r
673 double cp6_0=cpara[6]*cx0;
\r
674 double cp6_1=cpara[6]*cx1;
\r
675 double cpx0_0=cpara[0]*cx0;
\r
676 double cpx3_0=cpara[3]*cx0;
\r
679 ref_x[pt]=(int)((cpx0_0+cpy0_12)/d);
\r
680 ref_y[pt]=(int)((cpx3_0+cpy0_45)/d);
\r
684 ref_x[pt]=(int)((cpx0_0+cpy1_12)/d);
\r
685 ref_y[pt]=(int)((cpx3_0+cpy1_45)/d);
\r
689 ref_x[pt]=(int)((cpara[0]*cx1+cpy0_12)/d);
\r
690 ref_y[pt]=(int)((cpara[3]*cx1+cpy0_45)/d);
\r
694 ref_x[pt]=(int)((cpara[0]*cx1+cpy1_12)/d);
\r
695 ref_y[pt]=(int)((cpara[3]*cx1+cpy1_45)/d);
\r
698 //1行分のピクセルを取得(場合によっては専用アクセサを書いた方がいい)
\r
699 reader.getPixelSet(ref_x,ref_y,i_size*4,pixcel_temp);
\r
700 //グレースケールにしながら、line→mapへの転写
\r
701 for(int i2=0;i2<i_size;i2++){
\r
703 int pixel=( pixcel_temp[index+0]+pixcel_temp[index+1]+pixcel_temp[index+2]+
\r
704 pixcel_temp[index+3]+pixcel_temp[index+4]+pixcel_temp[index+5]+
\r
705 pixcel_temp[index+6]+pixcel_temp[index+7]+pixcel_temp[index+8]+
\r
706 pixcel_temp[index+9]+pixcel_temp[index+10]+pixcel_temp[index+11])/(4*3);
\r
707 o_bitbuffer.setBitByBitIndex(p,pixel>i_th?1:0);
\r
714 public boolean setSquare(NyARIntPoint2d[] i_vertex) throws NyARException
\r
716 if (!getParam(i_vertex,this._cparam)) {
\r
724 * 遠近法を使ったパースペクティブ補正付きのINyARColorPatt
\r
727 public class CopyOfNyARColorPatt_NyIdMarker implements INyARColorPatt
\r
729 private int[] _patdata;
\r
730 private NyARBufferReader _buf_reader;
\r
731 private NyARRgbPixelReader_INT1D_GLAY_8 _pixelreader;
\r
732 private NyARIntSize _size;
\r
733 PerspectivePixelReader2 _perspective_gen;
\r
734 private static final int LOCAL_LT=1;
\r
741 * @param i_edge_percentage
\r
742 * エッジ幅の割合(ARToolKit標準と同じなら、25)
\r
744 public CopyOfNyARColorPatt_NyIdMarker(int i_model)
\r
748 int resolution=i_model*2+1;
\r
749 this._size=new NyARIntSize(resolution,resolution);
\r
750 this._patdata = new int[resolution*resolution];
\r
751 this._buf_reader=new NyARBufferReader(this._patdata,NyARBufferReader.BUFFERFORMAT_INT1D_GLAY_8);
\r
752 this._pixelreader=new NyARRgbPixelReader_INT1D_GLAY_8(this._patdata,this._size);
\r
753 this._perspective_gen=new PerspectivePixelReader2(LOCAL_LT,LOCAL_LT,100,100);
\r
757 public final int getWidth()
\r
759 return this._size.w;
\r
761 public final int getHeight()
\r
763 return this._size.h;
\r
765 public final NyARIntSize getSize()
\r
769 public final INyARBufferReader getBufferReader()
\r
771 return this._buf_reader;
\r
773 public final INyARRgbPixelReader getRgbPixelReader()
\r
775 return this._pixelreader;
\r
779 public int[] vertex_x=new int[49*4];
\r
780 public int[] vertex_y=new int[49*4];
\r
781 public int[] vertex2_x=new int[400];
\r
782 public int[] vertex2_y=new int[400];
\r
783 public int[] line1=new int[45];
\r
784 public int[] line2=new int[45];
\r
785 public int[] sv=new int[4];
\r
786 private int[] temp_pixcel=new int[144];
\r
787 // private NyARSingleEdgeFinder _edge_finder=new NyARSingleEdgeFinder(12,12);
\r
793 private class TMarkerParam{
\r
796 private double[] index_x=new double[25*2];
\r
797 private double[] index_y=new double[25*2];
\r
801 * 次段半周期が、前段の80%より大きく、120%未満であるものを、等間隔周期であるとみなす。
\r
805 private boolean checkFreqWidth(int[] i_freq,int i_width)
\r
807 int c=i_freq[1]-i_freq[0];
\r
808 for(int i=1;i<i_width*2-1;i++){
\r
809 final int n=i_freq[i+1]-i_freq[i];
\r
810 final int v=n*100/c;
\r
818 private static int MIN_FREQ=3;
\r
819 private static int MAX_FREQ=10;
\r
821 private int getRowFreq(int i_y,int i_th_h,int i_th_l,int[] o_freq_index)throws NyARException
\r
824 int freq_index1[]=new int[45];
\r
825 int freq_count_table[]=new int[10];
\r
826 //0,2,4,6,8,10,12,14,16,18,20の要素を持つ配列
\r
827 int freq_table[][]=new int[10][20];
\r
830 //10-20ピクセル目からタイミングパターンを検出
\r
831 for(int i=i_y;i<i_y+10;i++){
\r
832 final int freq_t=this._perspective_gen.getRowFrequency(i,i_th_h,i_th_l,freq_index1);
\r
834 if(freq_t<MIN_FREQ || freq_t>MAX_FREQ){
\r
838 if(!checkFreqWidth(freq_index1,freq_t)){
\r
842 freq_count_table[freq_t]++;
\r
843 for(int i2=0;i2<freq_t*2;i2++){
\r
844 freq_table[freq_t][i2]+=freq_index1[i2];
\r
850 for(int i=0;i<MAX_FREQ;i++){
\r
851 if(max<freq_count_table[i]){
\r
853 max=freq_count_table[i];
\r
857 for(int i=0;i<index*2;i++)
\r
859 o_freq_index[i]=freq_table[index][i]/max;
\r
863 private int getColFreq(int i_y,int i_th_h,int i_th_l,int[] o_freq_index)throws NyARException
\r
866 int freq_index1[]=new int[45];
\r
867 int freq_count_table[]=new int[10];
\r
868 int freq_table[][]=new int[10][20];
\r
871 //10-20ピクセル目からタイミングパターンを検出
\r
872 for(int i=i_y;i<i_y+10;i++){
\r
873 final int freq_t=this._perspective_gen.getColFrequency(i,i_th_h,i_th_l,freq_index1);
\r
875 if(freq_t<MIN_FREQ || freq_t>MAX_FREQ){
\r
879 if(!checkFreqWidth(freq_index1,freq_t)){
\r
883 freq_count_table[freq_t]++;
\r
884 for(int i2=0;i2<freq_t*2;i2++){
\r
885 freq_table[freq_t][i2]+=freq_index1[i2];
\r
891 for(int i=0;i<MAX_FREQ;i++){
\r
892 if(max<freq_count_table[i]){
\r
894 max=freq_count_table[i];
\r
897 for(int i=0;i<10;i++){
\r
898 System.out.print(freq_count_table[i]+",");
\r
900 System.out.println();
\r
905 for(int i=0;i<index*2;i++)
\r
907 o_freq_index[i]=freq_table[index][i]/max;
\r
911 private boolean detectMarkerParam(INyARRgbPixelReader i_reader,TMarkerParam o_param)throws NyARException
\r
913 TThreshold th=new TThreshold();
\r
915 detectThresholdValue(i_reader,10,10,th);
\r
916 //周波数測定(最も正しい周波数を検出する)
\r
921 //左上,右下から、12x12(抽出範囲は10x10)の調査用矩形を抽出
\r
926 int freq_index1[]=new int[45];
\r
927 int freq_index2[]=new int[45];
\r
928 int frq_t=getRowFreq(10,th.th_h,th.th_l,freq_index1);
\r
929 int frq_b=getRowFreq(80,th.th_h,th.th_l,freq_index2);
\r
931 if((frq_t<0 && frq_b<0) || frq_t==frq_b){
\r
932 System.out.print("FRQ_R");
\r
935 //タイミングパターンからインデクスを作成
\r
945 for(int i=0;i<freq*2-1;i++){
\r
946 o_param.index_x[i*2]=((index[i+1]-index[i])*2/5+index[i])*2+PerspectivePixelReader.FRQ_EDGE;
\r
947 o_param.index_x[i*2+1]=((index[i+1]-index[i])*3/5+index[i])*2+PerspectivePixelReader.FRQ_EDGE;
\r
949 int frq_l=getColFreq(10,th.th_h,th.th_l,freq_index1);
\r
950 int frq_r=getColFreq(80,th.th_h,th.th_l,freq_index2);
\r
952 if((frq_l<0 && frq_r<0) || frq_l==frq_r){
\r
953 System.out.print("FRQ_C");
\r
956 //タイミングパターンからインデクスを作成
\r
964 for(int i=0;i<freq*2-1;i++){
\r
965 o_param.index_y[i*2]=((index[i+1]-index[i])*2/5+index[i])*2+PerspectivePixelReader.FRQ_EDGE;
\r
966 o_param.index_y[i*2+1]=((index[i+1]-index[i])*3/5+index[i])*2+PerspectivePixelReader.FRQ_EDGE;
\r
973 System.out.print("LVL_4");
\r
976 o_param.model=freq-1;
\r
977 o_param.threshold=th.th;
\r
981 private class TThreshold{
\r
987 * 指定した場所のピクセル値を調査して、閾値を計算して返します。
\r
992 * @throws NyARException
\r
994 private void detectThresholdValue(INyARRgbPixelReader i_reader,int i_x,int i_y,TThreshold o_threshold)throws NyARException
\r
996 final int[] temp_pixel=this.temp_pixcel;
\r
998 this._perspective_gen.rectPixels(i_x,i_y,10,10,temp_pixel);
\r
1001 int h = len *13/10;
\r
1004 for (int i = 0; i + h < len; i++) {
\r
1005 if (temp_pixel[i + h] > temp_pixel[i]) {
\r
1006 final int temp = temp_pixel[i + h];
\r
1007 temp_pixel[i + h] = temp_pixel[i];
\r
1008 temp_pixel[i] = temp;
\r
1020 //値の大きい方と小さい方の各4点を取得
\r
1022 final int th_l=temp_pixel[99]+temp_pixel[98]+temp_pixel[97]+temp_pixel[96];
\r
1023 final int th_h=temp_pixel[0]+temp_pixel[1]+temp_pixel[2]+temp_pixel[3];
\r
1024 int th_sub=(th_h-th_l)/(4*5);//ヒステリシス(20%)
\r
1025 int th=(th_h+th_l)/8;
\r
1026 o_threshold.th=th;
\r
1027 o_threshold.th_h=th+th_sub;//ヒステリシス付き閾値
\r
1028 o_threshold.th_l=th-th_sub;//ヒステリシス付き閾値
\r
1029 System.out.println(o_threshold.th+","+o_threshold.th_h+","+o_threshold.th_l);
\r
1038 * @return 切り出しに失敗した
\r
1039 * @throws Exception
\r
1041 public boolean pickFromRaster(INyARRgbRaster image, NyARSquare i_square)throws NyARException
\r
1043 this._perspective_gen.setSourceRaster(image);
\r
1044 i_square.imvertex[0].x=149;
\r
1045 i_square.imvertex[0].y=179;
\r
1046 i_square.imvertex[0].x=27;
\r
1047 i_square.imvertex[0].y=96;
\r
1048 i_square.imvertex[0].x=152;
\r
1049 i_square.imvertex[0].y=29;
\r
1050 i_square.imvertex[0].x=280;
\r
1051 i_square.imvertex[0].y=72;
\r
1054 if(!this._perspective_gen.setSourceSquare(i_square.imvertex)){
\r
1058 final INyARRgbPixelReader reader=image.getRgbPixelReader();
\r
1061 TMarkerParam param=new TMarkerParam();
\r
1062 MarkerPattEncoder encoder=new MarkerPattEncoder();
\r
1064 if(!detectMarkerParam(reader,param))
\r
1066 System.out.println("E");
\r
1069 final int resolution=(param.model*2)+1;
\r
1072 if(!encoder.initEncoder(param.model)){
\r
1075 //int i_stx,int i_sty,int size_x,int size_y,int i_resolution,int i_th,
\r
1076 //this._perspective_gen.readDataBits(st_x,st_y,size_x,size_y,resolution, param.threshold, encoder);
\r
1077 this._perspective_gen.readDataBits(param.index_x,param.index_y,resolution, param.threshold, encoder);
\r
1080 for(int i=0;i<49*4;i++){
\r
1081 this.vertex_x[i]=0;
\r
1082 this.vertex_y[i]=0;
\r
1084 for(int i=0;i<resolution*2;i++){
\r
1085 for(int i2=0;i2<resolution*2;i2++){
\r
1086 this.vertex_x[i*resolution*2+i2]=(int)param.index_x[i2];
\r
1087 this.vertex_y[i*resolution*2+i2]=(int)param.index_y[i];
\r
1092 System.out.println(param.model);
\r
1095 for(int i=0;i<size*size;i++){
\r
1096 this._patdata[i]=encoder.getBit(_role_table[i])==0?0:255;
\r
1103 public static void main(String[] args)
\r
1106 double[] a=new double[10];
\r
1108 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
\r
1109 0,0,0,0,0,0,0,1,5,1,2,0,0,0,1,2,5,2,1,0,
\r
1110 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
\r
1111 NyARSingleEdgeFinder px=new NyARSingleEdgeFinder(20,2);
\r
1112 System.out.print(px.scanEdgeLeftToRight(d,0,0,a));
\r
1113 System.out.print("");
\r
1114 } catch (Exception e) {
\r
1115 e.printStackTrace();
\r