OSDN Git Service

2f7d9e843ecd268efd161c3c3c7329c28afd2445
[nyartoolkit-and/nyartoolkit-and.git] / test / jp / nyatla / nyartoolkit / dev / CopyOfLabelingCamera.java
1 /* このソースは実験用のソースです。
2  * 動いたり動かなかったりします。
3  * 
4  */
5 package jp.nyatla.nyartoolkit.dev;
6
7 import javax.media.*;
8
9 import javax.media.util.BufferToImage;
10 import javax.media.format.*;
11
12 import jp.nyatla.nyartoolkit.NyARException;
13 import jp.nyatla.nyartoolkit.jmf.utils.*;
14 import jp.nyatla.nyartoolkit.core.*;
15 import jp.nyatla.nyartoolkit.toys.x2.NyARLabeling_ARToolKit_X2;
16 import jp.nyatla.nyartoolkit.toys.x2.NyARTransMat_X2;
17
18 import java.awt.*;
19
20 import jp.nyatla.nyartoolkit.core.INyARSquareDetector;
21 import jp.nyatla.nyartoolkit.core.labeling.*;
22 import jp.nyatla.nyartoolkit.core.match.*;
23 import jp.nyatla.nyartoolkit.core.param.*;
24 import jp.nyatla.nyartoolkit.core.pickup.*;
25 import jp.nyatla.nyartoolkit.core.raster.*;
26 import jp.nyatla.nyartoolkit.core.raster.rgb.INyARRgbRaster;
27 import jp.nyatla.nyartoolkit.core.rasterfilter.*;
28 import jp.nyatla.nyartoolkit.core2.rasteranalyzer.*;
29 import jp.nyatla.nyartoolkit.core2.rasteranalyzer.threshold.*;
30 import jp.nyatla.nyartoolkit.core2.rasterfilter.gs2bin.*;
31 import jp.nyatla.nyartoolkit.core2.rasterfilter.rgb2gs.NyARRasterFilter_RgbAve;
32 import jp.nyatla.utils.NyObjectStack;
33 import jp.nyatla.utils.j2se.LabelingBufferdImage;
34 import jp.nyatla.nyartoolkit.core.rasterfilter.rgb2bin.*;
35 import jp.nyatla.nyartoolkit.core.transmat.*;
36 import jp.nyatla.nyartoolkit.core.types.*;
37
38
39 class NyARMkVertexStack extends NyObjectStack
40 {
41         public NyARMkVertexStack(int i_length)
42         {
43                 super(new NyARIntPoint[i_length][]);
44
45         }
46
47         protected void onReservRequest(int i_start, int i_end, Object[] i_buffer)
48         {
49                 for (int i = i_start; i < i_end; i++) {
50                         i_buffer[i] = NyARIntPoint.createArray(4);
51                 }
52         }
53 }
54 /**
55  * QRコードのシンボルを結びつける偉いクラス
56  *
57  */
58 class NyQrCodeSymbolBinder
59 {
60         LabelingBufferdImage bimg;
61         
62         NyARIntPoint[][] _sqare;
63         /**
64          * 最小の三角形を構成する頂点セットを得る
65          * @param i_s0
66          * @param i_s1
67          * @param i_s2
68          * @param o_vertex
69          */
70         public static void getMinimumTriangleVertex(NyARIntPoint[][] i_sqare,int[] o_vertex_id)
71         {
72                 //辺の長さが最小になる頂点の組合せを探す
73                 int d;
74                 int x,y;
75                 int dmax=0x7fffffff;
76                 for(int i=0;i<4;i++)
77                 {
78                         for(int i2=0;i2<4;i2++)
79                         {
80                                 for(int i3=0;i3<4;i3++){
81                                         x=i_sqare[0][i].x-i_sqare[2][i3].x;
82                                         y=i_sqare[0][i].y-i_sqare[2][i3].y;
83                                         d=x*x+y*y;
84                                         x=i_sqare[1][i2].x-i_sqare[2][i3].x;
85                                         y=i_sqare[1][i2].y-i_sqare[2][i3].y;
86                                         d+=x*x+y*y;
87                                         x=i_sqare[1][i2].x-i_sqare[0][i].x;
88                                         y=i_sqare[1][i2].y-i_sqare[0][i].y;
89                                         d+=x*x+y*y;
90                                         if(d<dmax){
91                                                 dmax=d;
92                                                 o_vertex_id[0]=i;                                       
93                                                 o_vertex_id[1]=i2;
94                                                 o_vertex_id[2]=i3;
95                                         }
96                                 }
97                         }
98                 }
99                 return;
100         }
101         /**
102          * 2矩形の頂点距離が最低の組合せを探す
103          * @param i_sqare
104          * @param o_vertex_id
105          */
106         public static void getMinimumLineVertex(NyARIntPoint[] i_sqare0,NyARIntPoint[] i_sqare1,int[] o_vertex_id)
107         {
108                 //辺の長さが最小になる頂点の組合せを探す
109                 int d;
110                 int x,y;
111                 int dmax=0x7fffffff;
112                 for(int i=0;i<4;i++)
113                 {
114                         for(int i2=0;i2<4;i2++)
115                         {
116                                 x=i_sqare1[i2].x-i_sqare0[i].x;
117                                 y=i_sqare1[i2].y-i_sqare0[i].y;
118                                 d=x*x+y*y;
119                                 if(d<dmax){
120                                         dmax=d;
121                                         o_vertex_id[0]=i;                                       
122                                         o_vertex_id[1]=i2;
123                                 }
124                         }
125                 }
126                 return;
127         }       
128         
129         /**
130          * キーシンボルのインデックスを得る
131          * @param i_sqare
132          * @param i_vertex_id
133          * 最小三角形の頂点IDセット
134          * @return
135          */
136         public static int getKeySymble(NyARIntPoint[][] i_sqare,int[] i_vertex_id)
137         {
138                 //シンボルグループの重心を計算
139                 int cx,cy;
140                 cx=cy=0;
141                 for(int i=0;i<3;i++)
142                 {
143                         final NyARIntPoint[] sq_ptr=i_sqare[i];
144                         cx+=sq_ptr[0].x;                        
145                         cx+=sq_ptr[1].x;                        
146                         cx+=sq_ptr[2].x;                        
147                         cx+=sq_ptr[3].x;                        
148                         cy+=sq_ptr[0].y;                        
149                         cy+=sq_ptr[1].y;                        
150                         cy+=sq_ptr[2].y;                        
151                         cy+=sq_ptr[3].y;                        
152                 }
153                 cx/=12;
154                 cy/=12; 
155                 //前段で探した頂点候補のうち、最も重心に近いものが中心シンボルの内対角点
156                 int key_symble_idx=0;
157                 int x=i_sqare[0][i_vertex_id[0]].x-cx;
158                 int y=i_sqare[0][i_vertex_id[0]].y-cy;
159                 int dmax=x*x+y*y;
160                 for(int i=1;i<3;i++){
161                         x=i_sqare[i][i_vertex_id[i]].x-cx;
162                         y=i_sqare[i][i_vertex_id[i]].y-cy;
163                         final int d=x*x+y*y;
164                         if(d<dmax){
165                                 dmax=d;
166                                 key_symble_idx=i;
167                         }
168                 }
169                 return key_symble_idx;
170         }
171         public void getLineFromVertex(NyARIntPoint i_v1,NyARIntPoint i_v2)
172         {
173                 double sx=i_v1.x-i_v2.x;
174                 double sy=i_v1.y-i_v2.y;
175                 double k=sy/sx;
176                 double b=i_v2.y-k*i_v2.x;
177                 Graphics g=this.bimg.getGraphics();
178                 g.setColor(Color.red);
179                 g.drawLine(0,(int)b,320,(int)(k*320+b));
180                 
181         }
182         /**
183          *
184          * @param i_sq
185          * @param o_sq
186          * @return
187          */
188         public boolean margeEdge(NyARIntPoint[][] i_sq,NyARSquare o_sq)
189         {
190                 int[] minimum_triangle_vertex=new int[3];
191                 int[] minimum_line_vertex=new int[2];
192
193                 //辺の長さが最小になる頂点の組合せを探す
194                 getMinimumTriangleVertex(i_sq,minimum_triangle_vertex);
195                 
196                 //キーシンボルのインデクス番号を得る
197                 int key_simble_idx=getKeySymble(i_sq,minimum_triangle_vertex);
198                 
199                 //エッジシンボルのインデックス番号を決める
200                 int symbol_e1_idx=(key_simble_idx+1)%3;
201                 int symbol_e2_idx=(key_simble_idx+2)%3;
202                 
203                 //エッジシンボル間で最短距離を取る頂点ペアを取る
204                 //(角度を低くするとエラーが出やすい。対角線との類似性を確認する方法のほうがいい。多分)
205                 getMinimumLineVertex(i_sq[symbol_e1_idx],i_sq[symbol_e2_idx],minimum_line_vertex);
206                 
207                 //内対角を外対角に変換
208                 int lv1=(minimum_line_vertex[0]+2)%4;
209                 int lv2=(minimum_line_vertex[1]+2)%4;
210                 int kv =(minimum_triangle_vertex[key_simble_idx]+2)%4;
211
212                 getLineFromVertex(i_sq[symbol_e1_idx][(lv1+1)%4],i_sq[symbol_e1_idx][lv1]);
213                 getLineFromVertex(i_sq[symbol_e1_idx][(lv1+3)%4],i_sq[symbol_e1_idx][lv1]);
214                 getLineFromVertex(i_sq[symbol_e2_idx][(lv2+1)%4],i_sq[symbol_e2_idx][lv2]);
215                 getLineFromVertex(i_sq[symbol_e2_idx][(lv2+3)%4],i_sq[symbol_e2_idx][lv2]);
216                 getLineFromVertex(i_sq[key_simble_idx][(kv+2)%4],i_sq[key_simble_idx][kv]);
217                                 
218                 
219                 Graphics g=this.bimg.getGraphics();
220                 //内対角に緑の点を打つ
221                 g.setColor(Color.green);
222                 g.fillRect(i_sq[key_simble_idx][minimum_triangle_vertex[key_simble_idx]].x-2,i_sq[key_simble_idx][minimum_triangle_vertex[key_simble_idx]].y-2,4,4);
223                 g.fillRect(i_sq[symbol_e1_idx][minimum_line_vertex[0]].x-2,i_sq[symbol_e1_idx][minimum_line_vertex[0]].y-2,4,4);
224                 g.fillRect(i_sq[symbol_e2_idx][minimum_line_vertex[1]].x-2,i_sq[symbol_e2_idx][minimum_line_vertex[1]].y-2,4,4);
225                 
226                 
227                 //中央の中心エッジから最も遠い点が
228                 //両端のエッジも探す
229                 
230                 
231                 
232
233 //              this.bimg.getGraphics().fillRect(i_sq[edge1_id][vid1_id].x,i_sq[edge1_id][vid1_id].y,5,5);
234                 
235                 for (int i = 0; i <3; i++) {
236                         int[] xp=new int[4]; 
237                         int[] yp=new int[4]; 
238                         for(int i2=0;i2<4;i2++){
239                                 xp[i2]=i_sq[i][i2].x;
240                                 yp[i2]=i_sq[i][i2].y;
241                         }
242                         this.bimg.getGraphics().setColor(Color.RED);
243                         this.bimg.getGraphics().drawPolygon(xp, yp,4);
244                 }               
245                 
246                 
247                 return false;
248                 
249                 
250                 
251                 
252
253                 
254         }       
255         
256         
257         
258         
259 }
260
261
262 /**
263  * 矩形座標をPCAではなく、頂点座標そのものからSquare位置を計算するクラス
264  * 
265  */
266 class NyARQRCodeDetector implements INyARSquareDetector
267 {
268         LabelingBufferdImage bimg;
269         private static final double VERTEX_FACTOR = 2.0;// 線検出のファクタ
270
271         private static final int AR_AREA_MAX = 100000;// #define AR_AREA_MAX 100000
272
273         private static final int AR_AREA_MIN = 70;// #define AR_AREA_MIN 70
274
275         private final int _width;
276
277         private final int _height;
278
279         private final NyARLabeling_ARToolKit_X2 _labeling;
280
281         private final NyARLabelingImage _limage;
282
283         private final NyARCameraDistortionFactor _dist_factor_ref;
284
285         /**
286          * 最大i_squre_max個のマーカーを検出するクラスを作成する。
287          * 
288          * @param i_param
289          */
290         public NyARQRCodeDetector(NyARCameraDistortionFactor i_dist_factor_ref, NyARIntSize i_size) throws NyARException
291         {
292                 this._width = i_size.w;
293                 this._height = i_size.h;
294                 this._dist_factor_ref = i_dist_factor_ref;
295                 this._labeling = new NyARLabeling_ARToolKit_X2();
296                 this._limage = new NyARLabelingImage(this._width, this._height);
297                 this._labeling.attachDestination(this._limage);
298
299                 // 輪郭の最大長は画面に映りうる最大の長方形サイズ。
300                 int number_of_coord = (this._width + this._height) * 2;
301
302                 // 輪郭バッファは頂点変換をするので、輪郭バッファの2倍取る。
303                 this._max_coord = number_of_coord;
304                 this._xcoord = new int[number_of_coord * 2];
305                 this._ycoord = new int[number_of_coord * 2];
306         }
307
308         private final int _max_coord;
309
310         private final int[] _xcoord;
311
312         private final int[] _ycoord;
313
314         private void normalizeCoord(int[] i_coord_x, int[] i_coord_y, int i_index, int i_coord_num)
315         {
316                 // vertex1を境界にして、後方に配列を連結
317                 System.arraycopy(i_coord_x, 1, i_coord_x, i_coord_num, i_index);
318                 System.arraycopy(i_coord_y, 1, i_coord_y, i_coord_num, i_index);
319         }
320
321         private final int[] __detectMarker_mkvertex = new int[5];
322
323         /**
324          * ARMarkerInfo2 *arDetectMarker2( ARInt16 *limage, int label_num, int *label_ref,int *warea, double *wpos, int *wclip,int area_max, int area_min, double
325          * factor, int *marker_num ) 関数の代替品 ラベリング情報からマーカー一覧を作成してo_marker_listを更新します。 関数はo_marker_listに重なりを除外したマーカーリストを作成します。
326          * 
327          * @param i_raster
328          * 解析する2値ラスタイメージを指定します。
329          * @param o_square_stack
330          * 抽出した正方形候補を格納するリスト
331          * @throws NyARException
332          */
333         public final void detectMarker(NyARBinRaster i_raster, NyARSquareStack o_square_stack) throws NyARException
334         {
335                 final INyARLabeling labeling_proc = this._labeling;
336                 final NyARLabelingImage limage = this._limage;
337
338                 // 初期化
339
340                 // マーカーホルダをリセット
341                 o_square_stack.clear();
342
343                 // ラベリング
344                 labeling_proc.labeling(i_raster);
345
346                 // ラベル数が0ならここまで
347                 final int label_num = limage.getLabelStack().getLength();
348                 if (label_num < 1) {
349                         return;
350                 }
351
352                 final NyARLabelingLabelStack stack = limage.getLabelStack();
353                 final NyARLabelingLabel[] labels = (NyARLabelingLabel[]) stack.getArray();
354
355                 // ラベルを大きい順に整列
356                 stack.sortByArea();
357
358                 // デカいラベルを読み飛ばし
359                 int i;
360                 for (i = 0; i < label_num; i++) {
361                         // 検査対象内のラベルサイズになるまで無視
362                         if (labels[i].area <= AR_AREA_MAX) {
363                                 break;
364                         }
365                 }
366                 
367                 final int xsize = this._width;
368                 final int ysize = this._height;
369                 final int[] xcoord = this._xcoord;
370                 final int[] ycoord = this._ycoord;
371                 final int coord_max = this._max_coord;
372                 final int[] mkvertex = this.__detectMarker_mkvertex;
373                 final int[][] buf = (int[][]) limage.getBufferReader().getBuffer();
374                 final int[] indextable = limage.getIndexArray();
375                 int coord_num;
376                 int label_area;
377                 NyARLabelingLabel label_pt;
378                 NyARMkVertexStack vertex_stack=new NyARMkVertexStack(100);
379
380                 for (; i < label_num; i++) {
381                         label_pt = labels[i];
382                         label_area = label_pt.area;
383                         // 検査対象サイズよりも小さくなったら終了
384                         if (label_area < AR_AREA_MIN) {
385                                 break;
386                         }
387                         // クリップ領域が画面の枠に接していれば除外
388                         if (label_pt.clip_l == 1 || label_pt.clip_r == xsize - 2) {// if(wclip[i*4+0] == 1 || wclip[i*4+1] ==xsize-2){
389                                 continue;
390                         }
391                         if (label_pt.clip_t == 1 || label_pt.clip_b == ysize - 2) {// if( wclip[i*4+2] == 1 || wclip[i*4+3] ==ysize-2){
392                                 continue;
393                         }
394                         // 特徴点候補であるかを確認する。
395                         if (!hasQrEdgeFeature(buf, indextable, label_pt)) {
396                                 continue;
397                         }
398
399                         // 輪郭を取得
400                         coord_num = limage.getContour(i, coord_max, xcoord, ycoord);
401                         if (coord_num == coord_max) {
402                                 // 輪郭が大きすぎる。
403                                 continue;
404                         }
405                         // 頂点候補のインデクスを取得
406                         final int vertex1 = scanVertex(xcoord, ycoord, coord_num);
407
408                         // 頂点候補(vertex1)を先頭に並べなおした配列を作成する。
409                         normalizeCoord(xcoord, ycoord, vertex1, coord_num);
410
411
412                         // 頂点情報を取得
413                         if (!getSquareVertex(xcoord, ycoord, vertex1, coord_num, label_area, mkvertex)) {
414 //                              o_square_stack.pop();// 頂点の取得が出来なかったので破棄
415                                 continue;
416                         }
417                         // 領域を準備する。
418                         NyARIntPoint[] vertex_ptr = (NyARIntPoint[]) vertex_stack.prePush();
419                         vertex_ptr[0].x=xcoord[mkvertex[0]];
420                         vertex_ptr[0].y=ycoord[mkvertex[0]];
421                         vertex_ptr[1].x=xcoord[mkvertex[1]];
422                         vertex_ptr[1].y=ycoord[mkvertex[1]];
423                         vertex_ptr[2].x=xcoord[mkvertex[2]];
424                         vertex_ptr[2].y=ycoord[mkvertex[2]];
425                         vertex_ptr[3].x=xcoord[mkvertex[3]];
426                         vertex_ptr[3].y=ycoord[mkvertex[3]];
427
428 //                      // 頂点情報からライン情報を作っちゃう
429 //                      getSquare(mkvertex, xcoord, ycoord, vertex_ptr);
430                 }
431                 bindQrcodeEdge(vertex_stack);
432                 //エッジ同士の相関関係をしらべる。
433
434                 return;
435         }
436         /**
437          *
438          * @param i_sq
439          * @param o_sq
440          * @return
441          */
442         public boolean margeEdge(NyARIntPoint[][] i_sq,NyARSquare o_sq)
443         {
444                 NyQrCodeSymbolBinder binder=new NyQrCodeSymbolBinder();
445                 binder.bimg=this.bimg;
446                 binder.margeEdge(i_sq, o_sq);
447
448                 return false;
449                 
450                 
451                 
452                 
453         }
454         /**
455          * QRコードのエッジペアを作る
456          * @param i_square_stack
457          */
458         public void bindQrcodeEdge(NyARMkVertexStack i_square_stack)
459         {
460                 
461                 NyARIntPoint[] sq_ptr1,sq_ptr2,sq_ptr3;
462                 int number_of_edge=i_square_stack.getLength();
463                 if(number_of_edge<3){
464                         return;
465                 }
466                 NyARIntPoint[][] sa=(NyARIntPoint[][])i_square_stack.getArray();
467                 for(int i=0;i<number_of_edge;i++)
468                 {       
469                         for(int i2=i+1;i2<number_of_edge;i2++)
470                         {
471                                 sq_ptr2=sa[i2];
472                                 for(int i3=i2+1;i3<number_of_edge;i3++){
473                                         sq_ptr3=sa[i3];
474                                         //3個のエッジの関連性を確認する。
475                                         margeEdge(sa,null);
476                                 }
477                                 //
478                         }
479                 }
480         }
481         /**
482          * 2つの頂点座標を結ぶ直線から、NyARLinearを計算する。
483          * 
484          * @param i_v1
485          * @param i_v2
486          * @param o_line
487          */
488         final private void getLine(NyARDoublePoint2d i_v1, NyARDoublePoint2d i_v2, NyARLinear o_line)
489         {
490                 final double x = i_v1.x - i_v2.x;
491                 final double y = i_v1.y - i_v2.y;
492                 final double x2 = x * x;
493                 final double y2 = y * y;
494                 final double rise_ = Math.sqrt(x2 / (x2 + y2));
495                 o_line.rise = rise_;
496                 o_line.run = Math.sqrt(y2 / (x2 + y2));
497                 if (x < 0) {
498                         if (y < 0) {
499                                 o_line.rise = -o_line.rise;
500                         } else {
501                                 o_line.rise = -o_line.rise;
502                                 o_line.run = -o_line.run;
503                         }
504                 } else {
505                         if (y < 0) {
506                                 o_line.rise = -o_line.rise;
507                                 o_line.run = -o_line.run;
508                         } else {
509                                 o_line.rise = -o_line.rise;
510                         }
511                 }
512                 o_line.intercept = (i_v1.y + (o_line.run / o_line.rise) * (i_v1.x)) * rise_;
513
514         }
515
516         private void getSquare(int[] i_mkvertex, int[] i_xcoord, int[] i_ycoord, NyARSquare o_square)
517         {
518                 final NyARCameraDistortionFactor dist_factor = this._dist_factor_ref;
519                 final NyARDoublePoint2d[] vertex = o_square.sqvertex;
520
521                 NyARIntPoint[] imvertex_ptr=o_square.imvertex;
522                 NyARIntPoint wk_vertex;
523                 //頂点座標取得
524                 for (int i = 0; i < 4; i++) {
525                         final int idx = i_mkvertex[i];
526                         imvertex_ptr[i].x = i_xcoord[idx];
527                         imvertex_ptr[i].y = i_ycoord[idx];
528                 }
529                 // 歪み補正
530                 for (int i = 0; i < 4; i++) {
531                         dist_factor.observ2Ideal(imvertex_ptr[i].x,imvertex_ptr[i].y, vertex[i]);
532                 }
533                 // ライン計算
534                 getLine(vertex[1], vertex[0], o_square.line[0]);
535                 getLine(vertex[2], vertex[1], o_square.line[1]);
536                 getLine(vertex[3], vertex[2], o_square.line[2]);
537                 getLine(vertex[0], vertex[3], o_square.line[3]);
538                 return;
539         }
540
541         /**
542          * 辺からの対角線が最長になる点を対角線候補として返す。
543          * 
544          * @param i_xcoord
545          * @param i_ycoord
546          * @param i_coord_num
547          * @return
548          */
549         private int scanVertex(int[] i_xcoord, int[] i_ycoord, int i_coord_num)
550         {
551                 final int sx = i_xcoord[0];
552                 final int sy = i_ycoord[0];
553                 int d = 0;
554                 int w, x, y;
555                 int ret = 0;
556                 for (int i = 1; i < i_coord_num; i++) {
557                         x = i_xcoord[i] - sx;
558                         y = i_ycoord[i] - sy;
559                         w = x * x + y * y;
560                         if (w > d) {
561                                 d = w;
562                                 ret = i;
563                         }
564                         // ここでうまく終了条件入れられないかな。
565                 }
566                 return ret;
567         }
568
569         private final NyARVertexCounter __getSquareVertex_wv1 = new NyARVertexCounter();
570
571         private final NyARVertexCounter __getSquareVertex_wv2 = new NyARVertexCounter();
572
573         /**
574          * static int arDetectMarker2_check_square( int area, ARMarkerInfo2 *marker_info2, double factor ) 関数の代替関数 OPTIMIZED STEP [450->415] o_squareに頂点情報をセットします。
575          * 
576          * @param i_x_coord
577          * @param i_y_coord
578          * @param i_vertex1_index
579          * @param i_coord_num
580          * @param i_area
581          * @param o_vertex
582          * 要素数はint[4]である事
583          * @return
584          */
585         private boolean getSquareVertex(int[] i_x_coord, int[] i_y_coord, int i_vertex1_index, int i_coord_num, int i_area, int[] o_vertex)
586         {
587                 final NyARVertexCounter wv1 = this.__getSquareVertex_wv1;
588                 final NyARVertexCounter wv2 = this.__getSquareVertex_wv2;
589                 final int end_of_coord = i_vertex1_index + i_coord_num - 1;
590                 final int sx = i_x_coord[i_vertex1_index];// sx = marker_info2->x_coord[0];
591                 final int sy = i_y_coord[i_vertex1_index];// sy = marker_info2->y_coord[0];
592                 int dmax = 0;
593                 int v1 = i_vertex1_index;
594                 for (int i = 1 + i_vertex1_index; i < end_of_coord; i++) {// for(i=1;i<marker_info2->coord_num-1;i++)
595                         // {
596                         final int d = (i_x_coord[i] - sx) * (i_x_coord[i] - sx) + (i_y_coord[i] - sy) * (i_y_coord[i] - sy);
597                         if (d > dmax) {
598                                 dmax = d;
599                                 v1 = i;
600                         }
601                 }
602                 final double thresh = (i_area / 0.75) * 0.01 * VERTEX_FACTOR;
603
604                 o_vertex[0] = i_vertex1_index;
605
606                 if (!wv1.getVertex(i_x_coord, i_y_coord, i_vertex1_index, v1, thresh)) { // if(get_vertex(marker_info2->x_coord,marker_info2->y_coord,0,v1,thresh,wv1,&wvnum1)<
607                         // 0 ) {
608                         return false;
609                 }
610                 if (!wv2.getVertex(i_x_coord, i_y_coord, v1, end_of_coord, thresh)) {// if(get_vertex(marker_info2->x_coord,marker_info2->y_coord,v1,marker_info2->coord_num-1,thresh,wv2,&wvnum2)
611                         // < 0) {
612                         return false;
613                 }
614
615                 int v2;
616                 if (wv1.number_of_vertex == 1 && wv2.number_of_vertex == 1) {// if(wvnum1 == 1 && wvnum2== 1) {
617                         o_vertex[1] = wv1.vertex[0];
618                         o_vertex[2] = v1;
619                         o_vertex[3] = wv2.vertex[0];
620                 } else if (wv1.number_of_vertex > 1 && wv2.number_of_vertex == 0) {// }else if( wvnum1 > 1 && wvnum2== 0) {
621                         // 頂点位置を、起点から対角点の間の1/2にあると予想して、検索する。
622                         v2 = (v1 - i_vertex1_index) / 2 + i_vertex1_index;
623                         if (!wv1.getVertex(i_x_coord, i_y_coord, i_vertex1_index, v2, thresh)) {
624                                 return false;
625                         }
626                         if (!wv2.getVertex(i_x_coord, i_y_coord, v2, v1, thresh)) {
627                                 return false;
628                         }
629                         if (wv1.number_of_vertex == 1 && wv2.number_of_vertex == 1) {
630                                 o_vertex[1] = wv1.vertex[0];
631                                 o_vertex[2] = wv2.vertex[0];
632                                 o_vertex[3] = v1;
633                         } else {
634                                 return false;
635                         }
636                 } else if (wv1.number_of_vertex == 0 && wv2.number_of_vertex > 1) {
637                         // v2 = (v1-i_vertex1_index+ end_of_coord-i_vertex1_index) / 2+i_vertex1_index;
638                         v2 = (v1 + end_of_coord) / 2;
639
640                         if (!wv1.getVertex(i_x_coord, i_y_coord, v1, v2, thresh)) {
641                                 return false;
642                         }
643                         if (!wv2.getVertex(i_x_coord, i_y_coord, v2, end_of_coord, thresh)) {
644                                 return false;
645                         }
646                         if (wv1.number_of_vertex == 1 && wv2.number_of_vertex == 1) {
647                                 o_vertex[1] = v1;
648                                 o_vertex[2] = wv1.vertex[0];
649                                 o_vertex[3] = wv2.vertex[0];
650                         } else {
651                                 return false;
652                         }
653                 } else {
654                         return false;
655                 }
656                 o_vertex[4] = end_of_coord;
657                 return true;
658         }
659         /**
660          * QRコードのエッジ特徴を持つラベルであるかを調べる
661          * @param buf
662          * @param index_table
663          * @param i_label
664          * @return
665          */
666         private boolean hasQrEdgeFeature(int buf[][], int[] index_table, NyARLabelingLabel i_label)
667         {
668                 int tx, bx;
669                 int w;
670                 int i_label_id = i_label.id;
671                 int[] limage_j;
672                 final int clip_l = i_label.clip_l;
673                 final int clip_b = i_label.clip_b;
674                 final int clip_r = i_label.clip_r;
675                 final int clip_t = i_label.clip_t;
676
677                 tx = bx = 0;
678                 // 上接点(→)
679                 limage_j = buf[clip_t];
680                 for (int i = clip_l; i <= clip_r; i++) {// for( i = clip[0]; i <=clip[1]; i++, p1++ ) {
681                         w = limage_j[i];
682                         if (w > 0 && index_table[w - 1] == i_label_id) {
683                                 tx = i;
684                                 break;
685                         }
686                 }
687                 // 下接点(←)
688                 limage_j = buf[clip_b];
689                 for (int i = clip_r; i >= clip_l; i--) {// for( i = clip[0]; i <=clip[1]; i++, p1++ ) {
690                         w = limage_j[i];
691                         if (w > 0 && index_table[w - 1] == i_label_id) {
692                                 bx = i;
693                                 break;
694                         }
695                 }
696                 final int cx = (clip_l + clip_r) / 2;
697                 final int cy = (clip_t + clip_b) / 2;
698                 // 横断チェック(中心から線を引いて、101になるかしらべる)
699                 if (!checkDiagonalLine(buf, cx, cy, bx, clip_b)) {
700                         return false;
701                 }
702                 if (!checkDiagonalLine(buf, tx, clip_t, cx, cy)) {
703                         return false;
704                 }
705                 return true;
706         }
707
708         /**
709          * 対角線のパターンを調べる。
710          * 
711          * @param buf
712          * @param i_px1
713          * @param i_py1
714          * @param i_px2
715          * @param i_py2
716          * @return
717          */
718         private boolean checkDiagonalLine(int[][] buf, int i_px1, int i_py1, int i_px2, int i_py2)
719         {
720                 int sub_y = i_py2 - i_py1;
721                 int sub_x = i_px2 - i_px1;
722                 // 黒
723                 int i = 0;
724                 for (; i < sub_y; i++) {
725                         int yp = i_py1 + i;
726                         int xp = i_px1 + i * sub_x / sub_y;
727                         if (buf[yp][xp] == 0 && buf[yp][xp-1] == 0 && buf[yp][xp+1] == 0) {
728                                 break;
729                         }
730
731                 }
732                 if (i == sub_y) {
733                         return false;
734                 }
735                 // 白
736                 for (; i < sub_y; i++) {
737                         int yp = i_py1 + i;
738                         int xp = i_px1 + i * sub_x / sub_y;
739                         if (buf[yp][xp] != 0 && buf[yp][xp-1] != 0 && buf[yp][xp+1] != 0) {
740                                 break;
741                         }
742
743                 }
744                 if (i == sub_y) {
745                         return false;
746                 }
747                 // 黒
748                 for (; i < sub_y; i++) {
749                         int yp = i_py1 + i;
750                         int xp = i_px1 + i * sub_x / sub_y;
751                         if (buf[yp][xp] == 0 && buf[yp][xp-1] == 0 && buf[yp][xp+1] == 0) {
752                                 break;
753                         }
754
755                 }
756                 if (i != sub_y) {
757                         return false;
758                 }
759                 // 端まで到達したらOK
760                 return true;
761         }
762
763 }
764
765
766 public class CopyOfLabelingCamera extends Frame implements JmfCaptureListener
767 {
768         private final String camera_file = "../Data/camera_para.dat";
769
770         private JmfNyARRaster_RGB _raster;
771
772         private JmfCameraCapture capture;
773         private NyARParam ap;
774         public CopyOfLabelingCamera() throws NyARException, NyARException
775         {
776                 setBounds(0, 0, 640 + 64, 720 + 64);
777                 // キャプチャの準備
778                 capture = new JmfCameraCapture(320, 240, 30f, JmfCameraCapture.PIXEL_FORMAT_RGB);
779                 capture.setCaptureListener(this);
780
781                 // キャプチャイメージ用のラスタを準備
782                 this._raster = new JmfNyARRaster_RGB(320, 240);
783                 
784                 // AR用カメラパラメタファイルをロード
785                 ap = new NyARParam();
786                 ap.loadARParamFromFile(camera_file);
787                 ap.changeScreenSize(320, 240);          
788                 
789                 
790         }
791
792         // そのラベルが特徴点候補か返す。
793
794         private NyARBinRaster _binraster1 = new NyARBinRaster(320, 240);
795
796         private NyARGlayscaleRaster _gsraster1 = new NyARGlayscaleRaster(320, 240);
797
798         private NyARLabelingImage _limage = new NyARLabelingImage(320, 240);
799
800         private LabelingBufferdImage _bimg = new LabelingBufferdImage(320, 240);
801
802         private NyARRasterFilter_ARToolkitThreshold filter_gs2bin;
803
804         public void onUpdateBuffer(Buffer i_buffer)
805         {
806                 NyARRasterFilter_AreaAverage gs2bin=new NyARRasterFilter_AreaAverage();
807
808                 try {
809                         // キャプチャしたバッファをラスタにセット
810                         _raster.setBuffer(i_buffer);
811
812                         Graphics g = getGraphics();
813                         // キャプチャ画像
814                         BufferToImage b2i = new BufferToImage((VideoFormat) i_buffer.getFormat());
815                         Image img = b2i.createImage(i_buffer);
816                         this.getGraphics().drawImage(img, 32, 32, this);
817
818                         // 画像1
819                         INyARRasterFilter_RgbToGs filter_rgb2gs = new NyARRasterFilter_RgbAve();
820                         filter_rgb2gs.doFilter(_raster, _gsraster1);
821                         this._bimg.drawImage(this._gsraster1);
822                         this.getGraphics().drawImage(this._bimg, 32 + 320, 32, 320 + 320 + 32, 240 + 32, 0, 240, 320, 0, this);
823                         
824
825                         // 画像2
826                         gs2bin.doFilter(_gsraster1, _binraster1);
827                         this._bimg.drawImage(_binraster1);
828                         this.getGraphics().drawImage(this._bimg, 32, 32 + 240, 320 + 32, 240 + 32 + 240, 0, 240, 320, 0, this);
829
830                         // 画像3
831                         NyARLabelingImage limage = new NyARLabelingImage(320, 240);
832                         NyARLabeling_ARToolKit labeling = new NyARLabeling_ARToolKit();
833                         labeling.attachDestination(limage);
834                         labeling.labeling(_binraster1);
835                         this._bimg.drawImage(this._gsraster1);
836                         NyARLabelingLabel[] labels = (NyARLabelingLabel[]) limage.getLabelStack().getArray();
837
838                         NyARSquareStack stack = new NyARSquareStack(100);
839                         NyARQRCodeDetector detect = new NyARQRCodeDetector(ap.getDistortionFactor(), new NyARIntSize(320,240));
840                         detect.bimg=this._bimg;
841
842                         detect.detectMarker(_binraster1, stack);
843                         for (int i = 0; i < stack.getLength(); i++) {
844                                 NyARSquare[] square_ptr = (NyARSquare[]) stack.getArray();
845                                 int[] xp=new int[4]; 
846                                 int[] yp=new int[4]; 
847                                 for(int i2=0;i2<4;i2++){
848                                         xp[i2]=square_ptr[i].imvertex[i2].x;
849                                         yp[i2]=square_ptr[i].imvertex[i2].y;
850                                 }
851                                 this._bimg.getGraphics().setColor(Color.RED);
852                                 this._bimg.getGraphics().drawPolygon(xp, yp,2);
853                         }
854                         this.getGraphics().drawImage(this._bimg, 32 + 320, 32 + 240, 320 + 32 + 320, 240 + 32 + 240, 0, 240, 320, 0, this);
855
856                         // 画像3
857                         // threshold.debugDrawHistgramMap(_workraster, _workraster2);
858                         // this._bimg2.setImage(this._workraster2);
859                         // this.getGraphics().drawImage(this._bimg2, 32+320, 32+240,320+32+320,240+32+240,0,240,320,0, this);
860
861                         // 画像4
862                         // NyARRasterThresholdAnalyzer_SlidePTile threshold=new NyARRasterThresholdAnalyzer_SlidePTile(15);
863                         // threshold.analyzeRaster(_gsraster1);
864                         // filter_gs2bin=new NyARRasterFilter_AreaAverage();
865                         // filter_gs2bin.doFilter(_gsraster1, _binraster1);
866                         // this._bimg.drawImage(_binraster1);
867
868                         // NyARRasterDetector_QrCodeEdge detector=new NyARRasterDetector_QrCodeEdge(10000);
869                         // detector.analyzeRaster(_binraster1);
870
871                         // this._bimg.overlayData(detector.geResult());
872
873                         // this.getGraphics().drawImage(this._bimg, 32, 32+480,320+32,480+32+240,0,240,320,0, this);
874                         // 画像5
875
876                         /*
877                          * threshold2.debugDrawHistgramMap(_workraster, _workraster2); this._bimg2.drawImage(this._workraster2); this.getGraphics().drawImage(this._bimg2,
878                          * 32+320, 32+480,320+32+320,480+32+240,0,240,320,0, this);
879                          */
880
881                         // this.getGraphics().drawImage(this._bimg, 32, 32, this);
882
883                 } catch (Exception e) {
884                         e.printStackTrace();
885                 }
886
887         }
888
889         private INyARLabeling labelingFactory(int i_idx)
890         {
891                 // switch(i_idx){
892                 // case 0:{NyARLabeling_ARToolKit l=new NyARLabeling_ARToolKit();l.setThresh(4);return l;}
893                 // case 1:{return new NyLineLabeling();}
894                 // }
895                 return null;
896
897         }
898
899         private void startCapture()
900         {
901                 try {
902                         capture.start();
903                 } catch (Exception e) {
904                         e.printStackTrace();
905                 }
906         }
907
908         public static void main(String[] args)
909         {
910                 try {
911                         CopyOfLabelingCamera mainwin = new CopyOfLabelingCamera();
912                         mainwin.setVisible(true);
913                         mainwin.startCapture();
914                 } catch (Exception e) {
915                         e.printStackTrace();
916                 }
917
918         }
919
920 }