📄 labelingcamera.java
字号:
/* このソースは実験用のソースです。 * 動いたり動かなかったりします。 * */package jp.nyatla.nyartoolkit.dev;import javax.media.*;import javax.media.util.BufferToImage;import javax.media.format.*;import jp.nyatla.nyartoolkit.NyARException;import jp.nyatla.nyartoolkit.jmf.utils.*;import jp.nyatla.nyartoolkit.core.*;import java.awt.*;import jp.nyatla.nyartoolkit.core.INyARSquareDetector;import jp.nyatla.nyartoolkit.core.labeling.*;import jp.nyatla.nyartoolkit.core.match.*;import jp.nyatla.nyartoolkit.core.param.*;import jp.nyatla.nyartoolkit.core.pca2d.INyARPca2d;import jp.nyatla.nyartoolkit.core.pca2d.NyARPca2d_MatrixPCA_O2;import jp.nyatla.nyartoolkit.core.pickup.*;import jp.nyatla.nyartoolkit.core.raster.*;import jp.nyatla.nyartoolkit.core.raster.rgb.INyARRgbRaster;import jp.nyatla.nyartoolkit.core.rasterfilter.*;import jp.nyatla.nyartoolkit.core2.rasteranalyzer.*;import jp.nyatla.nyartoolkit.core2.rasteranalyzer.threshold.*;import jp.nyatla.nyartoolkit.core2.rasterfilter.gs2bin.*;import jp.nyatla.nyartoolkit.core2.rasterfilter.rgb2gs.NyARRasterFilter_RgbAve;import jp.nyatla.utils.NyObjectStack;import jp.nyatla.utils.j2se.LabelingBufferdImage;import jp.nyatla.nyartoolkit.core.rasterfilter.rgb2bin.*;import jp.nyatla.nyartoolkit.core.transmat.*;import jp.nyatla.nyartoolkit.core.types.*;import jp.nyatla.nyartoolkit.core.types.matrix.NyARDoubleMatrix22;///**// * QRコードのシンボルを結びつける偉いクラス// *// *///class NyQrCodeSymbolBinder//{// LabelingBufferdImage bimg;// // NyARIntPoint[][] _sqare;// /**// * 最小の三角形を構成する頂点セットを得る// * @param i_s0// * @param i_s1// * @param i_s2// * @param o_vertex// */// public static void getMinimumTriangleVertex(NyARSquare[] i_sqare,int[] o_vertex_id)// {// //辺の長さが最小になる頂点の組合せを探す// int d;// int x,y;// int dmax=0x7fffffff;// final NyARIntPoint[] vertex0=i_sqare[0].imvertex;// final NyARIntPoint[] vertex1=i_sqare[1].imvertex;// final NyARIntPoint[] vertex2=i_sqare[2].imvertex;// for(int i=0;i<4;i++)// {// for(int i2=0;i2<4;i2++)// {// for(int i3=0;i3<4;i3++){// x=vertex0[i].x-vertex2[i3].x;// y=vertex0[i].y-vertex2[i3].y;// d=x*x+y*y;// x=vertex1[i2].x-vertex2[i3].x;// y=vertex1[i2].y-vertex2[i3].y;// d+=x*x+y*y;// x=vertex1[i2].x-vertex0[i].x;// y=vertex1[i2].y-vertex0[i].y;// d+=x*x+y*y;// if(d<dmax){// dmax=d;// o_vertex_id[0]=i; // o_vertex_id[1]=i2;// o_vertex_id[2]=i3;// }// }// }// }// return;// }// /**// * 2矩形の頂点距離が最低の組合せを探す// * @param i_sqare// * @param o_vertex_id// */// public static void getMinimumLineVertex(NyARIntPoint[] i_sqare0,NyARIntPoint[] i_sqare1,int[] o_vertex_id)// {// //辺の長さが最小になる頂点の組合せを探す// int d;// int x,y;// int dmax=0x7fffffff;// for(int i=0;i<4;i++)// {// for(int i2=0;i2<4;i2++)// {// x=i_sqare1[i2].x-i_sqare0[i].x;// y=i_sqare1[i2].y-i_sqare0[i].y;// d=x*x+y*y;// if(d<dmax){// dmax=d;// o_vertex_id[0]=i; // o_vertex_id[1]=i2;// }// }// }// return;// } // // /**// * キーシンボルのインデックスを得る// * @param i_sqare// * @param i_vertex_id// * 最小三角形の頂点IDセット// * @return// */// public static int getKeySymble(NyARSquare[] i_sqare,int[] i_vertex_id)// {// //シンボルグループの重心を計算// int cx,cy;// cx=cy=0;// for(int i=0;i<3;i++)// {// final NyARIntPoint[] sq_ptr=i_sqare[i].imvertex;// cx+=sq_ptr[0].x; // cx+=sq_ptr[1].x; // cx+=sq_ptr[2].x; // cx+=sq_ptr[3].x; // cy+=sq_ptr[0].y; // cy+=sq_ptr[1].y; // cy+=sq_ptr[2].y; // cy+=sq_ptr[3].y; // }// cx/=12;// cy/=12; // //前段で探した頂点候補のうち、最も重心に近いものが中心シンボルの内対角点// int key_symble_idx=0;// int x=i_sqare[0].imvertex[i_vertex_id[0]].x-cx;// int y=i_sqare[0].imvertex[i_vertex_id[0]].y-cy;// int dmax=x*x+y*y;// for(int i=1;i<3;i++){// x=i_sqare[i].imvertex[i_vertex_id[i]].x-cx;// y=i_sqare[i].imvertex[i_vertex_id[i]].y-cy;// final int d=x*x+y*y;// if(d<dmax){// dmax=d;// key_symble_idx=i;// }// }// return key_symble_idx;// }// public void bindSquare(NyARSquare i_sq1,int i_lv1,NyARSquare i_sq2,int i_lv2)// {// NyARSquare new_square=new NyARSquare();// //4辺の式を計算// new_square.line[0].copyFrom(i_sq1.line[(i_lv1)%4]);// new_square.line[1].copyFrom(i_sq1.line[(i_lv1+3)%4]);// new_square.line[2].copyFrom(i_sq2.line[(i_lv2)%4]);// new_square.line[3].copyFrom(i_sq2.line[(i_lv2+3)%4]);// //歪み無しの座標系を計算// final NyARDoublePoint2d[] l_sqvertex = new_square.sqvertex;// final NyARLinear[] l_line = new_square.line; // for (int i = 0; i < 4; i++) {// final NyARLinear l_line_i = l_line[i];// final NyARLinear l_line_2 = l_line[(i + 3) % 4];// final double w1 = l_line_2.run * l_line_i.rise - l_line_i.run * l_line_2.rise;// if (w1 == 0.0) {// return;// }// l_sqvertex[i].x = (l_line_2.rise * l_line_i.intercept - l_line_i.rise * l_line_2.intercept) / w1;// l_sqvertex[i].y = (l_line_i.run * l_line_2.intercept - l_line_2.run * l_line_i.intercept) / w1;//// // 頂点インデクスから頂点座標を得て保存//// l_imvertex[i].x = i_xcoord[i_mkvertex[i]];//// l_imvertex[i].y = i_ycoord[i_mkvertex[i]];// }// Graphics g=this.bimg.getGraphics();// g.setColor(Color.red);// int[] x=new int[4];// int[] y=new int[4];// for(int i=0;i<4;i++){// x[i]=(int)l_sqvertex[i].x;// y[i]=(int)l_sqvertex[i].y;// }// g.drawPolygon(x,y,4);// //基準点はVertexをそのまま採用// //2個の想定点は座標を逆変換して設定// }// /**// *// * @param i_sq// * @param o_sq// * @return// */// public boolean margeEdge(NyARSquare[] i_sq,NyARSquare o_sq)// {// int[] minimum_triangle_vertex=new int[3];// int[] minimum_line_vertex=new int[2];//// //辺の長さが最小になる頂点の組合せを探す// getMinimumTriangleVertex(i_sq,minimum_triangle_vertex);// // //キーシンボルのインデクス番号を得る// int key_simble_idx=getKeySymble(i_sq,minimum_triangle_vertex);// // //エッジシンボルのインデックス番号を決める// int symbol_e1_idx=(key_simble_idx+1)%3;// int symbol_e2_idx=(key_simble_idx+2)%3;// // //エッジシンボル間で最短距離を取る頂点ペアを取る// //(角度を低くするとエラーが出やすい。対角線との類似性を確認する方法のほうがいい。多分)// getMinimumLineVertex(i_sq[symbol_e1_idx].imvertex,i_sq[symbol_e2_idx].imvertex,minimum_line_vertex);// // //内対角を外対角に変換// int lv1=(minimum_line_vertex[0]+2)%4;// int lv2=(minimum_line_vertex[1]+2)%4;// int kv =(minimum_triangle_vertex[key_simble_idx]+2)%4;// //矩形のバインド// bindSquare(i_sq[symbol_e1_idx],lv1,i_sq[symbol_e2_idx],lv2);// // // Graphics g=this.bimg.getGraphics();// //内対角に緑の点を打つ// g.setColor(Color.green);// g.fillRect(i_sq[symbol_e1_idx].imvertex[lv1].x-2,i_sq[symbol_e1_idx].imvertex[lv1].y-2,4,4);// g.fillRect(i_sq[symbol_e2_idx].imvertex[lv2].x-2,i_sq[symbol_e2_idx].imvertex[lv2].y-2,4,4);//// 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);// // // //中央の中心エッジから最も遠い点が// //両端のエッジも探す// // // ////// this.bimg.getGraphics().fillRect(i_sq[edge1_id][vid1_id].x,i_sq[edge1_id][vid1_id].y,5,5);// // for (int i = 0; i <3; i++) {// int[] xp=new int[4]; // int[] yp=new int[4]; // for(int i2=0;i2<4;i2++){// xp[i2]=i_sq[i].imvertex[i2].x;// yp[i2]=i_sq[i].imvertex[i2].y;// }// this.bimg.getGraphics().setColor(Color.RED);// this.bimg.getGraphics().drawPolygon(xp, yp,4);// } // // // return false;// // // // //// // } // // // // //}/** * 矩形座標をPCAではなく、頂点座標そのものからSquare位置を計算するクラス * */class NyARQRCodeDetector implements INyARSquareDetector{ LabelingBufferdImage bimg; private static final double VERTEX_FACTOR = 2.0;// 線検出のファクタ private static final int AR_AREA_MAX = 100000;// #define AR_AREA_MAX 100000 private static final int AR_AREA_MIN = 70;// #define AR_AREA_MIN 70 private final int _width; private final int _height; private final NyARLabeling_ARToolKit _labeling; private final NyARLabelingImage _limage; private final NyARCameraDistortionFactor _dist_factor_ref; /** * 最大i_squre_max個のマーカーを検出するクラスを作成する。 * * @param i_param */ public NyARQRCodeDetector(NyARCameraDistortionFactor i_dist_factor_ref, NyARIntSize i_size) throws NyARException { this._width = i_size.w; this._height = i_size.h; this._dist_factor_ref = i_dist_factor_ref; this._labeling = new NyARLabeling_ARToolKit(); this._limage = new NyARLabelingImage(this._width, this._height); this._labeling.attachDestination(this._limage); // 輪郭の最大長は画面に映りうる最大の長方形サイズ。 int number_of_coord = (this._width + this._height) * 2; // 輪郭バッファは頂点変換をするので、輪郭バッファの2倍取る。 this._max_coord = number_of_coord; this._xcoord = new int[number_of_coord * 2]; this._ycoord = new int[number_of_coord * 2]; } private final int _max_coord; private final int[] _xcoord; private final int[] _ycoord; private void normalizeCoord(int[] i_coord_x, int[] i_coord_y, int i_index, int i_coord_num) { // vertex1を境界にして、後方に配列を連結 System.arraycopy(i_coord_x, 1, i_coord_x, i_coord_num, i_index); System.arraycopy(i_coord_y, 1, i_coord_y, i_coord_num, i_index); } private final int[] __detectMarker_mkvertex = new int[5]; /** * ARMarkerInfo2 *arDetectMarker2( ARInt16 *limage, int label_num, int *label_ref,int *warea, double *wpos, int *wclip,int area_max, int area_min, double * factor, int *marker_num ) 関数の代替品 ラベリング情報からマーカー一覧を作成してo_marker_listを更新します。 関数はo_marker_listに重なりを除外したマーカーリストを作成します。 * * @param i_raster * 解析する2値ラスタイメージを指定します。 * @param o_square_stack * 抽出した正方形候補を格納するリスト * @throws NyARException */ public final void detectMarker(NyARBinRaster i_raster, NyARSquareStack o_square_stack) throws NyARException { final INyARLabeling labeling_proc = this._labeling; final NyARLabelingImage limage = this._limage; // 初期化 // マーカーホルダをリセット o_square_stack.clear(); // ラベリング labeling_proc.labeling(i_raster); // ラベル数が0ならここまで final int label_num = limage.getLabelStack().getLength(); if (label_num < 1) { return; } final NyARLabelingLabelStack stack = limage.getLabelStack(); final NyARLabelingLabel[] labels = (NyARLabelingLabel[]) stack.getArray(); // ラベルを大きい順に整列 stack.sortByArea(); // デカいラベルを読み飛ばし int i; for (i = 0; i < label_num; i++) { // 検査対象内のラベルサイズになるまで無視 if (labels[i].area <= AR_AREA_MAX) { break; } } final int xsize = this._width; final int ysize = this._height; final int[] xcoord = this._xcoord; final int[] ycoord = this._ycoord; final int coord_max = this._max_coord; final int[] mkvertex = this.__detectMarker_mkvertex; final int[][] buf = (int[][]) limage.getBufferReader().getBuffer(); final int[] indextable = limage.getIndexArray(); int coord_num; int label_area; NyARLabelingLabel label_pt; NyARSquareStack wk_stack=new NyARSquareStack(100); for (; i < label_num; i++) { label_pt = labels[i]; label_area = label_pt.area; // 検査対象サイズよりも小さくなったら終了 if (label_area < AR_AREA_MIN) { break; } // クリップ領域が画面の枠に接していれば除外 if (label_pt.clip_l == 1 || label_pt.clip_r == xsize - 2) {// if(wclip[i*4+0] == 1 || wclip[i*4+1] ==xsize-2){ continue; } if (label_pt.clip_t == 1 || label_pt.clip_b == ysize - 2) {// if( wclip[i*4+2] == 1 || wclip[i*4+3] ==ysize-2){ continue; } // 特徴点候補であるかを確認する。 if (!hasQrEdgeFeature(buf, indextable, label_pt)) { continue; } // 輪郭を取得 coord_num = limage.getContour(i, coord_max, xcoord, ycoord); if (coord_num == coord_max) { // 輪郭が大きすぎる。 continue; } // 頂点候補のインデクスを取得 final int vertex1 = scanVertex(xcoord, ycoord, coord_num); // 頂点候補(vertex1)を先頭に並べなおした配列を作成する。 normalizeCoord(xcoord, ycoord, vertex1, coord_num); // 頂点情報を取得 if (!getSquareVertex(xcoord, ycoord, vertex1, coord_num, label_area, mkvertex)) { continue; } NyARSquare square=(NyARSquare)wk_stack.prePush(); if(!getSquareLine(mkvertex,xcoord,ycoord,square)){ wk_stack.pop(); continue; } } bindQrcodeEdge(wk_stack); //エッジ同士の相関関係をしらべる。 return; } /** * * @param i_sq * @param o_sq * @return */ public boolean margeEdge(NyARSquare[] i_sq,NyARSquare o_sq) { NyQrCodeSymbolBinder binder=new NyQrCodeSymbolBinder(); binder.bimg=this.bimg; binder.(i_sq, o_sq); return false; } /** * QRコードのエッジペアを作る * @param i_square_stack */ public void bindQrcodeEdge(NyARSquareStack i_square_stack) { NyARSquare sq_ptr1,sq_ptr2,sq_ptr3; int number_of_edge=i_square_stack.getLength(); if(number_of_edge<3){ return; } NyARSquare[] sa=(NyARSquare[])i_square_stack.getArray(); for(int i=0;i<number_of_edge;i++) { for(int i2=i+1;i2<number_of_edge;i2++) { sq_ptr2=sa[i2]; for(int i3=i2+1;i3<number_of_edge;i3++){ sq_ptr3=sa[i3]; //3個のエッジの関連性を確認する。 margeEdge(sa,null);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -