/** * コンストラクタです。 * 入力画像のサイズを指定して、インスタンスを生成します。 * @param i_size * 入力画像のサイズ */ public NyARSquareContourDetector_Rle(NyARIntSize i_size) { this.setupImageDriver(i_size); //ラベリングのサイズを指定したいときはsetAreaRangeを使ってね。 this._coord = new NyARIntCoordinates((i_size.w + i_size.h) * 2); return; }
/** * コンストラクタです。 * @param i_width * このラスタの幅 * @param i_height * このラスタの高さ * @ */ public NyARColorPatt_PseudoAffine(int i_width, int i_height) { this._size = new NyARIntSize(i_width, i_height); this._patdata = new int[i_height * i_width]; this._pixelreader = NyARRgbPixelDriverFactory.createDriver(this); //疑似アフィン変換のパラメタマトリクスを計算します。 //長方形から計算すると、有効要素がm00,m01,m02,m03,m10,m11,m20,m23,m30になります。 NyARDoubleMatrix44 mat = this._invmat; mat.m00 = 0; mat.m01 = 0; mat.m02 = 0; mat.m03 = 1.0; mat.m10 = 0; mat.m11 = i_width - 1; mat.m12 = 0; mat.m13 = 1.0; mat.m20 = (i_width - 1) * (i_height - 1); mat.m21 = i_width - 1; mat.m22 = i_height - 1; mat.m23 = 1.0; mat.m30 = 0; mat.m31 = 0; mat.m32 = i_height - 1; mat.m33 = 1.0; mat.inverse(mat); return; }
/** * コンストラクタです。 * 解像度を指定して、インスタンスを生成します。 * @param i_width * ラスタのサイズ * @param i_height * ラスタのサイズ * @ */ public NyARColorPatt_Base(int i_width, int i_height) { //入力制限 Debug.Assert(i_width <= 64 && i_height <= 64); this._size = new NyARIntSize(i_width, i_height); this._patdata = new int[i_height * i_width]; this._pixelreader = NyARRgbPixelDriverFactory.createDriver(this); return; }
/** * このクラスの初期化シーケンスです。コンストラクタから呼び出します。初期化に失敗すると、例外を発生します。 * @param i_size * ラスタサイズ * @param i_raster_type * バッファ形式 * @param i_is_alloc * バッファ参照方法値 * @ */ protected virtual void initInstance(NyARIntSize i_size, int i_raster_type, bool i_is_alloc) { switch (i_raster_type) { case NyARBufferType.INT1D_GRAY_8: this._buf = i_is_alloc ? new int[i_size.w * i_size.h] : null; break; default: throw new NyARException(); } this._is_attached_buffer = i_is_alloc; //ピクセルドライバの生成 this._pixdrv = NyARGsPixelDriverFactory.createDriver(this); }
/** * コンストラクタです。 * メンバ変数を初期化して、インスタンスを生成します。 * @param i_width * ラスタの幅に設定する値 * @param i_height * ラスタの高さに設定する値 * @param i_buffer_type * バッファタイプ値に設定する値 */ protected NyARRaster_BasicClass(int i_width, int i_height, int i_buffer_type) { this._size = new NyARIntSize(i_width, i_height); this._buffer_type = i_buffer_type; }
public void doFilter(INyARGrayscaleRaster i_output) { Debug.Assert(i_output.isEqualBufferType(NyARBufferType.INT1D_GRAY_8)); NyARIntSize size = this._raster.getSize(); int[] in_ptr = (int[])this._raster.getBuffer(); switch (this._raster.getBufferType()) { case NyARBufferType.INT1D_GRAY_8: int[] out_ptr = (int[])i_output.getBuffer(); int width = size.w; int idx = 0; int idx2 = width; int fx, fy; int mod_p = (width - 2) - (width - 2) % 8; for (int y = size.h - 2; y >= 0; y--) { int p00 = in_ptr[idx++]; int p10 = in_ptr[idx2++]; int p01, p11; int x = width - 2; for (; x >= mod_p; x--) { p01 = in_ptr[idx++]; p11 = in_ptr[idx2++]; fx = p11 - p00; fy = p10 - p01; out_ptr[idx - 2] = ((fx < 0 ? -fx : fx) + (fy < 0 ? -fy : fy)) >> 1; p00 = p01; p10 = p11; } for (; x >= 0; x -= 4) { p01 = in_ptr[idx++]; p11 = in_ptr[idx2++]; fx = p11 - p00; fy = p10 - p01; out_ptr[idx - 2] = ((fx < 0 ? -fx : fx) + (fy < 0 ? -fy : fy)) >> 1; p00 = p01; p10 = p11; p01 = in_ptr[idx++]; p11 = in_ptr[idx2++]; fx = p11 - p00; fy = p10 - p01; out_ptr[idx - 2] = ((fx < 0 ? -fx : fx) + (fy < 0 ? -fy : fy)) >> 1; p00 = p01; p10 = p11; p01 = in_ptr[idx++]; p11 = in_ptr[idx2++]; fx = p11 - p00; fy = p10 - p01; out_ptr[idx - 2] = ((fx < 0 ? -fx : fx) + (fy < 0 ? -fy : fy)) >> 1; p00 = p01; p10 = p11; p01 = in_ptr[idx++]; p11 = in_ptr[idx2++]; fx = p11 - p00; fy = p10 - p01; out_ptr[idx - 2] = ((fx < 0 ? -fx : fx) + (fy < 0 ? -fy : fy)) >> 1; p00 = p01; p10 = p11; } out_ptr[idx - 1] = 0; } for (int x = width - 1; x >= 0; x--) { out_ptr[idx++] = 0; } return; default: //ANY未対応 throw new NyARException(); } }
/** * この関数は、ARToolKitスタイルのProjectionMatrixから、 CameraFrustamを計算します。 * @param i_promat * @param i_size * スクリーンサイズを指定します。 * @param i_scale * {@link #toCameraFrustumRH(NyARParam i_arparam,double i_scale,double i_near,double i_far,double[] o_gl_projection)}を参照。 * @param i_near * {@link #toCameraFrustumRH(NyARParam i_arparam,double i_scale,double i_near,double i_far,double[] o_gl_projection)}を参照。 * @param i_far * {@link #toCameraFrustumRH(NyARParam i_arparam,double i_scale,double i_near,double i_far,double[] o_gl_projection)}を参照。 * @param o_gl_projection * {@link #toCameraFrustumRH(NyARParam i_arparam,double i_scale,double i_near,double i_far,double[] o_gl_projection)}を参照。 */ public static void ToCameraFrustumRH(NyARPerspectiveProjectionMatrix i_promat, NyARIntSize i_size, double i_scale, double i_near, double i_far, ref Matrix4x4 o_mat) { NyARDoubleMatrix44 m = new NyARDoubleMatrix44(); i_promat.makeCameraFrustumRH(i_size.w, i_size.h, i_near * i_scale, i_far * i_scale, m); o_mat.m00 = (float)m.m00; o_mat.m01 = (float)m.m01; o_mat.m02 = (float)m.m02; o_mat.m03 = (float)m.m03; o_mat.m10 = (float)m.m10; o_mat.m11 = (float)m.m11; o_mat.m12 = (float)m.m12; o_mat.m13 = (float)m.m13; o_mat.m20 = (float)m.m20; o_mat.m21 = (float)m.m21; o_mat.m22 = (float)m.m22; o_mat.m23 = (float)m.m23; o_mat.m30 = (float)m.m30; o_mat.m31 = (float)m.m31; o_mat.m32 = (float)m.m32; o_mat.m33 = (float)m.m33; return; }
/** * コンストラクタです。 * 画像のサイズパラメータとバッファ形式を指定して、インスタンスを生成します。 * @param i_width * ラスタのサイズ * @param i_height * ラスタのサイズ * @param i_raster_type * ラスタのバッファ形式。 * {@link NyARBufferType}に定義された定数値を指定してください。指定できる値は、以下の通りです。 * <ul> * <li>{@link NyARBufferType#INT1D_GRAY_8} * <ul> * @param i_is_alloc * バッファを外部参照にするかのフラグ値。 * trueなら内部バッファ、falseなら外部バッファを使用します。 * falseの場合、初期のバッファはnullになります。インスタンスを生成したのちに、{@link #wrapBuffer}を使って割り当ててください。 * @ */ public NyARGrayscaleRaster(int i_width, int i_height, int i_raster_type, bool i_is_alloc) { this._size = new NyARIntSize(i_width, i_height); this._buffer_type = i_raster_type; initInstance(this._size, i_raster_type, i_is_alloc); }
/** * この関数は、マーカ画像のi_y1行目とi_y2行目を平均して、タイミングパターンの周波数を得ます。 * L=暗点、H=明点、LHL=1周期として、たとえばLHLHLの場合は2を返します。LHLHやHLHL等の始端と終端のレベルが異なるパターンを * 検出した場合、関数は失敗します。 * @param i_y1 * ライン1のインデクス * @param i_th_h * 明点の敷居値 * @param i_th_l * 暗点の敷居値 * @param o_edge_index * 検出したエッジ位置(H->L,L->H)のインデクスを受け取る配列。 * [FRQ_POINTS]以上の配列を指定すること。 * @return * 周波数の値。失敗すると-1 * @ */ public int getRowFrequency(INyARGsPixelDriver i_reader, NyARIntSize i_raster_size, int i_y1, int i_th_h, int i_th_l, int[] o_edge_index) { //3,4,5,6,7,8,9,10 int[] freq_count_table = this._freq_count_table; //0,2,4,6,8,10,12,14,16,18,20の要素を持つ配列 int[] freq_table = this._freq_table; //初期化 double[] cpara = this._cparam; int[] ref_x = this._ref_x; int[] ref_y = this._ref_y; int[] pixcel_temp = this._pixcel_temp; for (int i = 0; i < 10; i++) { freq_count_table[i] = 0; } for (int i = 0; i < 110; i++) { freq_table[i] = 0; } int raster_width = i_raster_size.w; int raster_height = i_raster_size.h; double cpara_0 = cpara[0]; double cpara_3 = cpara[3]; double cpara_6 = cpara[6]; //10-20ピクセル目からタイミングパターンを検出 for (int i = 0; i < FREQ_SAMPLE_NUM; i++) { //2行分のピクセルインデックスを計算 double cy0 = 1 + i_y1 + i; double cpy0_12 = cpara[1] * cy0 + cpara[2]; double cpy0_45 = cpara[4] * cy0 + cpara[5]; double cpy0_7 = cpara[7] * cy0 + 1.0; int pt = 0; for (int i2 = 0; i2 < FRQ_POINTS; i2++) { double cx0 = 1 + i2 * FRQ_STEP + FRQ_EDGE; double d = (cpara_6 * cx0) + cpy0_7; int x = (int)((cpara_0 * cx0 + cpy0_12) / d); int y = (int)((cpara_3 * cx0 + cpy0_45) / d); if (x < 0 || y < 0 || x >= raster_width || y >= raster_height) { return -1; } ref_x[pt] = x; ref_y[pt] = y; pt++; } //ピクセルを取得(入力画像を多様化するならここから先を調整すること) i_reader.getPixelSet(ref_x, ref_y, FRQ_POINTS, pixcel_temp, 0); //o_edge_indexを一時的に破壊して調査する int freq_t = getFreqInfo(pixcel_temp, i_th_h, i_th_l, o_edge_index); //周期は3-10であること if (freq_t < MIN_FREQ || freq_t > MAX_FREQ) { continue; } //周期は等間隔であること if (!checkFreqWidth(o_edge_index, freq_t)) { continue; } //検出カウンタを追加 freq_count_table[freq_t]++; int table_st = (freq_t - 1) * freq_t; for (int i2 = 0; i2 < freq_t * 2; i2++) { freq_table[table_st + i2] += o_edge_index[i2]; } } return getMaxFreq(freq_count_table, freq_table, o_edge_index); }
public RleDetector(NyARSingleDetectMarker i_parent, NyARIntSize i_size) : base(i_size) { this._parent = i_parent; }
public void doFilter(INyARRaster i_input, INyARRaster i_output,NyARIntSize i_size) { Debug.Assert(i_input.isEqualBufferType(NyARBufferType.INT1D_GRAY_8)); Debug.Assert(i_output.isEqualBufferType(NyARBufferType.INT1D_GRAY_8)); int[] in_ptr =(int[])i_input.getBuffer(); int[] out_ptr=(int[])i_output.getBuffer(); int width=i_size.w; int idx=0; int idx2=width; int fx,fy; int mod_p=(width-2)-(width-2)%4; for(int y=i_size.h-2;y>=0;y--){ int p00=in_ptr[idx++]; int p10=in_ptr[idx2++]; int p01,p11; int x=width-2; for(;x>=mod_p;x--){ p01=in_ptr[idx++];p11=in_ptr[idx2++]; fx=p11-p00;fy=p10-p01; // out_ptr[idx-2]=255-(((fx<0?-fx:fx)+(fy<0?-fy:fy))>>1); fx=(fx*fx+fy*fy)>>SH;out_ptr[idx-2]=(fx>255?0:255-fx); p00=p01; p10=p11; } for(;x>=0;x-=4){ p01=in_ptr[idx++];p11=in_ptr[idx2++]; fx=p11-p00; fy=p10-p01; // out_ptr[idx-2]=255-(((fx<0?-fx:fx)+(fy<0?-fy:fy))>>1); fx=(fx*fx+fy*fy)>>SH;out_ptr[idx-2]=(fx>255?0:255-fx); p00=p01;p10=p11; p01=in_ptr[idx++];p11=in_ptr[idx2++]; fx=p11-p00; fy=p10-p01; // out_ptr[idx-2]=255-(((fx<0?-fx:fx)+(fy<0?-fy:fy))>>1); fx=(fx*fx+fy*fy)>>SH;out_ptr[idx-2]=(fx>255?0:255-fx); p00=p01;p10=p11; p01=in_ptr[idx++];p11=in_ptr[idx2++]; fx=p11-p00; fy=p10-p01; // out_ptr[idx-2]=255-(((fx<0?-fx:fx)+(fy<0?-fy:fy))>>1); fx=(fx*fx+fy*fy)>>SH;out_ptr[idx-2]=(fx>255?0:255-fx); p00=p01;p10=p11; p01=in_ptr[idx++];p11=in_ptr[idx2++]; fx=p11-p00; fy=p10-p01; // out_ptr[idx-2]=255-(((fx<0?-fx:fx)+(fy<0?-fy:fy))>>1); fx=(fx*fx+fy*fy)>>SH;out_ptr[idx-2]=(fx>255?0:255-fx); p00=p01;p10=p11; } out_ptr[idx-1]=255; } for(int x=width-1;x>=0;x--){ out_ptr[idx++]=255; } return; }
public NyARParam(NyARIntSize i_screen_size, NyARPerspectiveProjectionMatrix i_projection_mat, INyARCameraDistortionFactor i_dist_factor) { this._screen_size = new NyARIntSize(i_screen_size); this._dist = i_dist_factor; this._projection_matrix = i_projection_mat; }
/** * ストリームから読み出したデータでインスタンスを初期化します。 * @param i_stream * @throws NyARException */ public ParamLoader(StreamReader i_stream) { //読み出し ByteBufferedInputStream bis = new ByteBufferedInputStream(i_stream, 512); int s = bis.readToBuffer(512); bis.order(ByteBufferedInputStream.ENDIAN_BIG); //読み出したサイズでバージョンを決定 int[] version_table = { 136, 144, 152, 176 }; int version = -1; for (int i = 0; i < version_table.Length; i++) { if (s % version_table[i] == 0) { version = i + 1; break; } } //一致しなければ無し if (version == -1) { throw new NyARException(); } //size this.size = new NyARIntSize(); this.size.setValue(bis.getInt(), bis.getInt()); //projection matrix this.pmat = new NyARPerspectiveProjectionMatrix(); double[] pjv = new double[16]; for (int i = 0; i < 12; i++) { pjv[i] = bis.getDouble(); } pjv[12] = pjv[13] = pjv[14] = 0; pjv[15] = 1; this.pmat.setValue(pjv); //dist factor double[] df; switch (version) { case 1: //Version1 df = new double[NyARCameraDistortionFactorV2.NUM_OF_FACTOR]; this.dist_factor = new NyARCameraDistortionFactorV2(); break; case 4: //Version4 df = new double[NyARCameraDistortionFactorV4.NUM_OF_FACTOR]; this.dist_factor = new NyARCameraDistortionFactorV4(); break; default: throw new NyARException(); } for (int i = 0; i < df.Length; i++) { df[i] = bis.getDouble(); } this.dist_factor.setValue(df); }
public void changeScreenSize(NyARIntSize i_size) { this.changeScreenSize(i_size.w, i_size.w); return; }
public NyARParam(NyARIntSize i_screen_size,NyARPerspectiveProjectionMatrix i_projection_mat,INyARCameraDistortionFactor i_dist_factor) { this._screen_size=new NyARIntSize(i_screen_size); this._dist=i_dist_factor; this._projection_matrix=i_projection_mat; }
/** * ストリームから読み出したデータでインスタンスを初期化します。 * @param i_stream * @throws NyARException */ public ParamLoader(StreamReader i_stream) { //読み出し ByteBufferedInputStream bis=new ByteBufferedInputStream(i_stream,512); int s=bis.readToBuffer(512); bis.order(ByteBufferedInputStream.ENDIAN_BIG); //読み出したサイズでバージョンを決定 int[] version_table={136,144,152,176}; int version=-1; for(int i=0;i<version_table.Length;i++){ if(s%version_table[i]==0){ version=i+1; break; } } //一致しなければ無し if(version==-1){ throw new NyARException(); } //size this.size=new NyARIntSize(); this.size.setValue(bis.getInt(),bis.getInt()); //projection matrix this.pmat=new NyARPerspectiveProjectionMatrix(); double[] pjv=new double[16]; for(int i=0;i<12;i++){ pjv[i]=bis.getDouble(); } pjv[12]=pjv[13]=pjv[14]=0; pjv[15]=1; this.pmat.setValue(pjv); //dist factor double[] df; switch(version) { case 1://Version1 df=new double[NyARCameraDistortionFactorV2.NUM_OF_FACTOR]; this.dist_factor=new NyARCameraDistortionFactorV2(); break; case 4://Version4 df=new double[NyARCameraDistortionFactorV4.NUM_OF_FACTOR]; this.dist_factor=new NyARCameraDistortionFactorV4(); break; default: throw new NyARException(); } for(int i=0;i<df.Length;i++){ df[i]=bis.getDouble(); } this.dist_factor.setValue(df); }
private void initInstance(int i_width, int i_height, int i_point_per_pix) { Debug.Assert(i_width > 2 && i_height > 2); this._sample_per_pixel = i_point_per_pix; this._size = new NyARIntSize(i_width, i_height); this._patdata = new int[i_height * i_width]; this._pixelreader = NyARRgbPixelDriverFactory.createDriver(this); return; }
public void doFilter(INyARRaster i_input, INyARRaster i_output, NyARIntSize i_size) { throw new NyARException(); }
public double makeColorData(int[] o_out) { //i_buffer[XRGB]→差分[R,G,B]変換 int i; int rgb; //<PV/> //<平均値計算(FORの1/8展開)> int ave; //<PV/> int[] buf = (int[])(this._ref_raster.getBuffer()); NyARIntSize size = this._ref_raster.getSize(); int number_of_pix = size.w * size.h; int optimize_mod = number_of_pix - (number_of_pix % 8); ave = 0; for (i = number_of_pix - 1; i >= optimize_mod; i--) { rgb = buf[i]; ave += ((rgb >> 16) & 0xff) + ((rgb >> 8) & 0xff) + (rgb & 0xff); } for (; i >= 0;) { rgb = buf[i]; ave += ((rgb >> 16) & 0xff) + ((rgb >> 8) & 0xff) + (rgb & 0xff); i--; rgb = buf[i]; ave += ((rgb >> 16) & 0xff) + ((rgb >> 8) & 0xff) + (rgb & 0xff); i--; rgb = buf[i]; ave += ((rgb >> 16) & 0xff) + ((rgb >> 8) & 0xff) + (rgb & 0xff); i--; rgb = buf[i]; ave += ((rgb >> 16) & 0xff) + ((rgb >> 8) & 0xff) + (rgb & 0xff); i--; rgb = buf[i]; ave += ((rgb >> 16) & 0xff) + ((rgb >> 8) & 0xff) + (rgb & 0xff); i--; rgb = buf[i]; ave += ((rgb >> 16) & 0xff) + ((rgb >> 8) & 0xff) + (rgb & 0xff); i--; rgb = buf[i]; ave += ((rgb >> 16) & 0xff) + ((rgb >> 8) & 0xff) + (rgb & 0xff); i--; rgb = buf[i]; ave += ((rgb >> 16) & 0xff) + ((rgb >> 8) & 0xff) + (rgb & 0xff); i--; } //<平均値計算(FORの1/8展開)/> ave = number_of_pix * 255 * 3 - ave; ave = 255 - (ave / (number_of_pix * 3));//(255-R)-ave を分解するための事前計算 int sum = 0, w_sum; int input_ptr = number_of_pix * 3 - 1; //<差分値計算(FORの1/8展開)> for (i = number_of_pix - 1; i >= optimize_mod; i--) { rgb = buf[i]; w_sum = (ave - (rgb & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //B w_sum = (ave - ((rgb >> 8) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //G w_sum = (ave - ((rgb >> 16) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //R } for (; i >= 0;) { rgb = buf[i]; i--; w_sum = (ave - (rgb & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //B w_sum = (ave - ((rgb >> 8) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //G w_sum = (ave - ((rgb >> 16) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //R rgb = buf[i]; i--; w_sum = (ave - (rgb & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //B w_sum = (ave - ((rgb >> 8) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //G w_sum = (ave - ((rgb >> 16) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //R rgb = buf[i]; i--; w_sum = (ave - (rgb & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //B w_sum = (ave - ((rgb >> 8) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //G w_sum = (ave - ((rgb >> 16) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //R rgb = buf[i]; i--; w_sum = (ave - (rgb & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //B w_sum = (ave - ((rgb >> 8) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //G w_sum = (ave - ((rgb >> 16) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //R rgb = buf[i]; i--; w_sum = (ave - (rgb & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //B w_sum = (ave - ((rgb >> 8) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //G w_sum = (ave - ((rgb >> 16) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //R rgb = buf[i]; i--; w_sum = (ave - (rgb & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //B w_sum = (ave - ((rgb >> 8) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //G w_sum = (ave - ((rgb >> 16) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //R rgb = buf[i]; i--; w_sum = (ave - (rgb & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //B w_sum = (ave - ((rgb >> 8) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //G w_sum = (ave - ((rgb >> 16) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //R rgb = buf[i]; i--; w_sum = (ave - (rgb & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //B w_sum = (ave - ((rgb >> 8) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //G w_sum = (ave - ((rgb >> 16) & 0xff)); o_out[input_ptr--] = w_sum; sum += w_sum * w_sum; //R } //<差分値計算(FORの1/8展開)/> double p = Math.Sqrt((double)sum); return(p != 0.0 ? p : 0.0000001); }
public void doFilter(INyARRaster i_input, INyARRaster i_output, NyARIntSize i_size) { Debug.Assert(i_input.isEqualBufferType(NyARBufferType.INT1D_X7H9S8V8_32)); int[] out_buf = (int[])i_output.getBuffer(); byte[] in_buf = (byte[])i_input.getBuffer(); int s; for (int i = i_size.h * i_size.w - 1; i >= 0; i--) { int r = (in_buf[i * 3 + 2] & 0xff); int g = (in_buf[i * 3 + 1] & 0xff); int b = (in_buf[i * 3 + 0] & 0xff); int cmax, cmin; //最大値と最小値を計算 if (r > g) { cmax = r; cmin = g; } else { cmax = g; cmin = r; } if (b > cmax) { cmax = b; } if (b < cmin) { cmin = b; } int h; if (cmax == 0) { s = 0; h = 0; } else { s = (cmax - cmin) * 255 / cmax; int cdes = cmax - cmin; //H成分を計算 if (cdes != 0) { if (cmax == r) { h = (g - b) * 60 / cdes; } else if (cmax == g) { h = (b - r) * 60 / cdes + 2 * 60; } else { h = (r - g) * 60 / cdes + 4 * 60; } } else { h = 0; } } if (h < 0) { h += 360; } //hsv変換(h9s8v8) out_buf[i] = (0x1ff0000 & (h << 16)) | (0x00ff00 & (s << 8)) | (cmax & 0xff); } return; }
/** * ラスタから射影変換したピクセルを得ます。 * @param i_lt_x * @param i_lt_y * @param i_step_x * @param i_step_y * @param i_width * @param i_height * @param i_out_st * 格納バッファo_pixelの先頭のインデクス。 * @param o_pixel * グレースケールのピクセルを格納するバッファ * @ */ private bool rectPixels(INyARGsPixelDriver i_reader, NyARIntSize i_raster_size, int i_lt_x, int i_lt_y, int i_step_x, int i_step_y, int i_width, int i_height, int i_out_st, int[] o_pixel) { double[] cpara = this._cparam; int[] ref_x = this._ref_x; int[] ref_y = this._ref_y; int raster_width = i_raster_size.w; int raster_height = i_raster_size.h; int out_index = i_out_st; double cpara_6 = cpara[6]; double cpara_0 = cpara[0]; double cpara_3 = cpara[3]; for (int i = 0; i < i_height; i++) { //1列分のピクセルのインデックス値を計算する。 int cy0 = 1 + i * i_step_y + i_lt_y; double cpy0_12 = cpara[1] * cy0 + cpara[2]; double cpy0_45 = cpara[4] * cy0 + cpara[5]; double cpy0_7 = cpara[7] * cy0 + 1.0; int pt = 0; for (int i2 = 0; i2 < i_width; i2++) { int cx0 = 1 + i2 * i_step_x + i_lt_x; double d = cpara_6 * cx0 + cpy0_7; int x = (int)((cpara_0 * cx0 + cpy0_12) / d); int y = (int)((cpara_3 * cx0 + cpy0_45) / d); if (x < 0 || y < 0 || x >= raster_width || y >= raster_height) { return false; } ref_x[pt] = x; ref_y[pt] = y; pt++; } //GS値を配列に取得 i_reader.getPixelSet(ref_x, ref_y, i_width, o_pixel, out_index); out_index += i_width; } return true; }
/** * 画像処理オブジェクトの切り替え関数。切り替える場合は、この関数を上書きすること。 * @param i_size * @ */ protected void setupImageDriver(NyARIntSize i_size) { //特性確認 Debug.Assert(NyARLabeling_Rle._sf_label_array_safe_reference); this._labeling = new Labeling(i_size.w, i_size.h); this._cpickup = new NyARContourPickup(); }
/** * この関数は、遠近法のパラメータを計算して、返却します。 * @param i_size * 変換先の矩形のサイズを指定します。 * @param i_vertex * 変換元の頂点を指定します。要素数は4でなければなりません。 * @param o_param * 射影変換パラメータの出力インスタンスを指定します。要素数は8でなければなりません。 * @return * 成功するとtrueを返します。 * @ */ public bool getParam(NyARIntSize i_size, NyARIntPoint2d[] i_vertex, double[] o_param) { Debug.Assert(i_vertex.Length == 4); return(this.getParam(i_size.w, i_size.h, i_vertex[0].x, i_vertex[0].y, i_vertex[1].x, i_vertex[1].y, i_vertex[2].x, i_vertex[2].y, i_vertex[3].x, i_vertex[3].y, o_param)); }
public void convertRect(int l, int t, int w, int h, INyARGrayscaleRaster o_raster) { NyARIntSize size = this._ref_raster.getSize(); int bp = (l + t * size.w) * 3; int b = t + h; int row_padding_dst = (size.w - w); int row_padding_src = row_padding_dst * 3; int pix_count = w; int pix_mod_part = pix_count - (pix_count % 8); int dst_ptr = t * size.w + l; byte[] in_buf = (byte[])this._ref_raster.getBuffer(); switch (o_raster.getBufferType()) { case NyARBufferType.INT1D_GRAY_8: int[] out_buf = (int[])o_raster.getBuffer(); for (int y = t; y < b; y++) { int x = 0; for (x = pix_count - 1; x >= pix_mod_part; x--) { out_buf[dst_ptr++] = ((in_buf[bp] & 0xff) + (in_buf[bp + 1] & 0xff) + (in_buf[bp + 2] & 0xff)) / 3; bp += 3; } for (; x >= 0; x -= 8) { out_buf[dst_ptr++] = ((in_buf[bp] & 0xff) + (in_buf[bp + 1] & 0xff) + (in_buf[bp + 2] & 0xff)) / 3; bp += 3; out_buf[dst_ptr++] = ((in_buf[bp] & 0xff) + (in_buf[bp + 1] & 0xff) + (in_buf[bp + 2] & 0xff)) / 3; bp += 3; out_buf[dst_ptr++] = ((in_buf[bp] & 0xff) + (in_buf[bp + 1] & 0xff) + (in_buf[bp + 2] & 0xff)) / 3; bp += 3; out_buf[dst_ptr++] = ((in_buf[bp] & 0xff) + (in_buf[bp + 1] & 0xff) + (in_buf[bp + 2] & 0xff)) / 3; bp += 3; out_buf[dst_ptr++] = ((in_buf[bp] & 0xff) + (in_buf[bp + 1] & 0xff) + (in_buf[bp + 2] & 0xff)) / 3; bp += 3; out_buf[dst_ptr++] = ((in_buf[bp] & 0xff) + (in_buf[bp + 1] & 0xff) + (in_buf[bp + 2] & 0xff)) / 3; bp += 3; out_buf[dst_ptr++] = ((in_buf[bp] & 0xff) + (in_buf[bp + 1] & 0xff) + (in_buf[bp + 2] & 0xff)) / 3; bp += 3; out_buf[dst_ptr++] = ((in_buf[bp] & 0xff) + (in_buf[bp + 1] & 0xff) + (in_buf[bp + 2] & 0xff)) / 3; bp += 3; } bp += row_padding_src; dst_ptr += row_padding_dst; } return; default: INyARGsPixelDriver out_drv = o_raster.getGsPixelDriver(); for (int y = t; y < b; y++) { for (int x = 0; x < pix_count; x++) { out_drv.setPixel(x, y, ((in_buf[bp] & 0xff) + (in_buf[bp + 1] & 0xff) + (in_buf[bp + 2] & 0xff)) / 3); bp += 3; } bp += row_padding_src; } return; } }
/* * この関数は、インスタンスの初期化シーケンスを実装します。 * コンストラクタから呼び出します。 * @param i_size * ラスタのサイズ * @param i_buf_type * バッファ形式定数 * @param i_is_alloc * 内部バッファ/外部バッファのフラグ * @return * 初期化に成功するとtrue * @ */ protected override void initInstance(NyARIntSize i_size, int i_buf_type, bool i_is_alloc) { switch (i_buf_type) { case NyARBufferType.INT1D_BIN_8: this._buf = i_is_alloc ? new int[i_size.w * i_size.h] : null; break; default: base.initInstance(i_size, i_buf_type, i_is_alloc); return; } this._pixdrv = NyARGsPixelDriverFactory.createDriver(this); this._is_attached_buffer = i_is_alloc; return; }
/** * コンストラクタです。 * 差分画像のサイズを指定して、インスタンスを生成します。 * @param i_width * 差分画像のサイズ * @param i_height * 差分画像のサイズ */ public NyARMatchPattDeviationColorData(int i_width, int i_height) { this._size = new NyARIntSize(i_width, i_height); this._data = new int[this._size.w * this._size.h * 3]; return; }
/** * Readerとbufferを初期化する関数です。コンストラクタから呼び出します。 * 継承クラスでこの関数を拡張することで、対応するバッファタイプの種類を増やせます。 * @param i_size * ラスタのサイズ * @param i_raster_type * バッファタイプ * @param i_is_alloc * 外部参照/内部バッファのフラグ * @return * 初期化が成功すると、trueです。 * @ */ protected virtual void InitInstance(NyARIntSize i_size, int i_raster_type, bool i_is_alloc) { //バッファの構築 switch (i_raster_type) { case NyARBufferType.INT1D_X8R8G8B8_32: this._buf = i_is_alloc ? new int[i_size.w * i_size.h] : null; break; case NyARBufferType.BYTE1D_B8G8R8X8_32: case NyARBufferType.BYTE1D_X8R8G8B8_32: this._buf = i_is_alloc ? new byte[i_size.w * i_size.h * 4] : null; break; case NyARBufferType.BYTE1D_R8G8B8_24: case NyARBufferType.BYTE1D_B8G8R8_24: this._buf = i_is_alloc ? new byte[i_size.w * i_size.h * 3] : null; break; case NyARBufferType.WORD1D_R5G6B5_16LE: this._buf = i_is_alloc ? new short[i_size.w * i_size.h] : null; break; default: throw new NyARException(); } //readerの構築 this._rgb_pixel_driver = NyARRgbPixelDriverFactory.createDriver(this); this._is_attached_buffer = i_is_alloc; return; }
/** * この関数は、遠近法のパラメータを計算して、返却します。 * @param i_size * 変換先の矩形のサイズを指定します。 * @param i_vertex * 変換元の頂点を指定します。要素数は4でなければなりません。 * @param o_param * 射影変換パラメータの出力インスタンスを指定します。要素数は8でなければなりません。 * @return * 成功するとtrueを返します。 * @ */ public bool getParam(NyARIntSize i_size, NyARDoublePoint2d[] i_vertex, double[] o_param) { return(this.getParam(i_size.w, i_size.h, i_vertex[0].x, i_vertex[0].y, i_vertex[1].x, i_vertex[1].y, i_vertex[2].x, i_vertex[2].y, i_vertex[3].x, i_vertex[3].y, o_param)); }
public void convert(INyARGrayscaleRaster i_raster) { NyARIntSize s = this._ref_raster.getSize(); this.convertRect(0, 0, s.w, s.h, i_raster); }
/** * コンストラクタです。 * @param i_width * ラスタの幅に設定する値 * @param i_height * ラスタの高さに設定する値 * @param i_buffer_type * バッファタイプ値に設定する値 */ protected NyARRgbRaster_BasicClass(int i_width, int i_height, int i_buffer_type) { this._size = new NyARIntSize(i_width, i_height); this._buffer_type = i_buffer_type; }
/** * この関数は、マーカパターンからデータを読み取ります。 * @param i_reader * ラスタリーダ * @param i_raster_size * ラスタのサイズ * @param o_bitbuffer * データビットの出力先 * @return * 成功するとtrue * @throws NyARException */ public bool readDataBits(INyARGsPixelDriver i_reader, NyARIntSize i_raster_size, MarkerPattDecoder o_bitbuffer) { int raster_width = i_raster_size.w; int raster_height = i_raster_size.h; double[] index_x = this.__readDataBits_index_bit_x; double[] index_y = this.__readDataBits_index_bit_y; //読み出し位置を取得 detectDataBitsIndex(index_x, index_y); int resolution = 3; double[] cpara = this._cparam; int[] ref_x = this._ref_x; int[] ref_y = this._ref_y; int[] pixcel_temp = this._pixcel_temp; double cpara_0 = cpara[0]; double cpara_1 = cpara[1]; double cpara_3 = cpara[3]; double cpara_6 = cpara[6]; int p = 0; for (int i = 0; i < resolution; i++) { //1列分のピクセルのインデックス値を計算する。 double cy0 = 1 + index_y[i * 2 + 0]; double cy1 = 1 + index_y[i * 2 + 1]; double cpy0_12 = cpara_1 * cy0 + cpara[2]; double cpy0_45 = cpara[4] * cy0 + cpara[5]; double cpy0_7 = cpara[7] * cy0 + 1.0; double cpy1_12 = cpara_1 * cy1 + cpara[2]; double cpy1_45 = cpara[4] * cy1 + cpara[5]; double cpy1_7 = cpara[7] * cy1 + 1.0; int pt = 0; for (int i2 = 0; i2 < resolution; i2++) { int xx, yy; double d; double cx0 = 1 + index_x[i2 * 2 + 0]; double cx1 = 1 + index_x[i2 * 2 + 1]; double cp6_0 = cpara_6 * cx0; double cpx0_0 = cpara_0 * cx0; double cpx3_0 = cpara_3 * cx0; double cp6_1 = cpara_6 * cx1; double cpx0_1 = cpara_0 * cx1; double cpx3_1 = cpara_3 * cx1; d = cp6_0 + cpy0_7; ref_x[pt] = xx = (int)((cpx0_0 + cpy0_12) / d); ref_y[pt] = yy = (int)((cpx3_0 + cpy0_45) / d); if (xx < 0 || xx >= raster_width || yy < 0 || yy >= raster_height) { ref_x[pt] = xx < 0 ? 0 : (xx >= raster_width ? raster_width - 1 : xx); ref_y[pt] = yy < 0 ? 0 : (yy >= raster_height ? raster_height - 1 : yy); } pt++; d = cp6_0 + cpy1_7; ref_x[pt] = xx = (int)((cpx0_0 + cpy1_12) / d); ref_y[pt] = yy = (int)((cpx3_0 + cpy1_45) / d); if (xx < 0 || xx >= raster_width || yy < 0 || yy >= raster_height) { ref_x[pt] = xx < 0 ? 0 : (xx >= raster_width ? raster_width - 1 : xx); ref_y[pt] = yy < 0 ? 0 : (yy >= raster_height ? raster_height - 1 : yy); } pt++; d = cp6_1 + cpy0_7; ref_x[pt] = xx = (int)((cpx0_1 + cpy0_12) / d); ref_y[pt] = yy = (int)((cpx3_1 + cpy0_45) / d); if (xx < 0 || xx >= raster_width || yy < 0 || yy >= raster_height) { ref_x[pt] = xx < 0 ? 0 : (xx >= raster_width ? raster_width - 1 : xx); ref_y[pt] = yy < 0 ? 0 : (yy >= raster_height ? raster_height - 1 : yy); } pt++; d = cp6_1 + cpy1_7; ref_x[pt] = xx = (int)((cpx0_1 + cpy1_12) / d); ref_y[pt] = yy = (int)((cpx3_1 + cpy1_45) / d); if (xx < 0 || xx >= raster_width || yy < 0 || yy >= raster_height) { ref_x[pt] = xx < 0 ? 0 : (xx >= raster_width ? raster_width - 1 : xx); ref_y[pt] = yy < 0 ? 0 : (yy >= raster_height ? raster_height - 1 : yy); } pt++; } //1行分のピクセルを取得(場合によっては専用アクセサを書いた方がいい) i_reader.getPixelSet(ref_x, ref_y, resolution * 4, pixcel_temp, 0); //グレースケールにしながら、line→mapへの転写 for (int i2 = 0; i2 < resolution; i2++) { int index = i2 * 4; o_bitbuffer.setBit(p, (pixcel_temp[index + 0] + pixcel_temp[index + 1] + pixcel_temp[index + 2] + pixcel_temp[index + 3]) / 4); p++; } } return true; }
/** * コンストラクタです。 * 画像のサイズパラメータとバッファ参照方式を指定して、インスタンスを生成します。 * バッファの形式は、{@link NyARBufferType#INT1D_GRAY_8}です。 * @param i_width * ラスタのサイズ * @param i_height * ラスタのサイズ * @param i_is_alloc * バッファを外部参照にするかのフラグ値。 * trueなら内部バッファ、falseなら外部バッファを使用します。 * falseの場合、初期のバッファはnullになります。インスタンスを生成したのちに、{@link #wrapBuffer}を使って割り当ててください。 * @ */ public NyARGrayscaleRaster(int i_width, int i_height, bool i_is_alloc) { this._size = new NyARIntSize(i_width, i_height); this._buffer_type = NyARBufferType.INT1D_GRAY_8; initInstance(this._size, NyARBufferType.INT1D_GRAY_8, i_is_alloc); }
/** * Readerとbufferを初期化する関数です。コンストラクタから呼び出します。 * 継承クラスでこの関数を拡張することで、対応するバッファタイプの種類を増やせます。 * @param i_size * ラスタのサイズ * @param i_raster_type * バッファタイプ * @param i_is_alloc * 外部参照/内部バッファのフラグ * @return * 初期化が成功すると、trueです。 * @ */ protected override void InitInstance(NyARIntSize i_size, int i_raster_type, bool i_is_alloc) { //バッファの構築 switch (i_raster_type) { case NyARBufferType.OBJECT_CS_Unity: this._buf = i_is_alloc ? new Color32[i_size.w * i_size.h] : null; this._rgb_pixel_driver = new NyARRgbPixelDriver_CsUnity(); this._rgb_pixel_driver.switchRaster(this); this._is_attached_buffer = i_is_alloc; break; default: base.InitInstance(i_size, i_raster_type, i_is_alloc); return; } //readerの構築 return; }
public void switchRaster(INyARRgbRaster i_raster) { this._ref_buf = (Color32[])(((NyARUnityRaster)i_raster).getBuffer()); this._ref_size = i_raster.getSize(); }
/** * 画像ドライバに依存するインスタンスの生成。 * 継承クラスで上書きする。 * @param s * @ */ protected void InitResource(NyARIntSize s) { this._gs_raster = new NyARGrayscaleRaster(s.w, s.h, NyARBufferType.INT1D_GRAY_8, true); }
/** * 共通初期化関数。 * @param i_param * @param i_drv_factory * ラスタドライバのファクトリ。 * @param i_gs_type * @param i_rgb_type * @return * @ */ private void InitInstance(NyARIntSize i_size) { //リソースの生成 this.InitResource(i_size); this._gs_hist = new NyARHistogram(256); this._src_ts = 0; this._gs_id_ts = 0; this._gs_hist_ts = 0; }
private int detectDataBitsIndex(INyARGsPixelDriver i_reader, NyARIntSize i_raster_size, PerspectivePixelReader.TThreshold i_th, double[] o_index_row, double[] o_index_col) { //周波数を測定 int[] freq_index1 = this.__detectDataBitsIndex_freq_index1; int[] freq_index2 = this.__detectDataBitsIndex_freq_index2; int frq_t = getRowFrequency(i_reader, i_raster_size, i_th.lt_y, i_th.th_h, i_th.th_l, freq_index1); int frq_b = getRowFrequency(i_reader, i_raster_size, i_th.rb_y, i_th.th_h, i_th.th_l, freq_index2); //周波数はまとも? if ((frq_t < 0 && frq_b < 0) || frq_t == frq_b) { return -1; } //タイミングパターンからインデクスを作成 int freq_h, freq_v; int[] index; if (frq_t > frq_b) { freq_h = frq_t; index = freq_index1; } else { freq_h = frq_b; index = freq_index2; } for (int i = 0; i < freq_h + freq_h - 1; i++) { o_index_row[i * 2] = ((index[i + 1] - index[i]) * 2 / 5 + index[i]) + FRQ_EDGE; o_index_row[i * 2 + 1] = ((index[i + 1] - index[i]) * 3 / 5 + index[i]) + FRQ_EDGE; } int frq_l = getColFrequency(i_reader, i_raster_size, i_th.lt_x, i_th.th_h, i_th.th_l, freq_index1); int frq_r = getColFrequency(i_reader, i_raster_size, i_th.rb_x, i_th.th_h, i_th.th_l, freq_index2); //周波数はまとも? if ((frq_l < 0 && frq_r < 0) || frq_l == frq_r) { return -1; } //タイミングパターンからインデクスを作成 if (frq_l > frq_r) { freq_v = frq_l; index = freq_index1; } else { freq_v = frq_r; index = freq_index2; } //同じ周期? if (freq_v != freq_h) { return -1; } for (int i = 0; i < freq_v + freq_v - 1; i++) { int w = index[i]; int w2 = index[i + 1] - w; o_index_col[i * 2] = ((w2) * 2 / 5 + w) + FRQ_EDGE; o_index_col[i * 2 + 1] = ((w2) * 3 / 5 + w) + FRQ_EDGE; } //Lv4以上は無理 if (freq_v > MAX_FREQ) { return -1; } return freq_v; }
public NyARSensor(NyARIntSize i_size) { this.InitInstance(i_size); this._hist_drv = (INyARHistogramFromRaster)this._gs_raster.createInterface(typeof(INyARHistogramFromRaster)); }
/** * この関数は、マーカ画像のi_x1列目とi_x2列目を平均して、タイミングパターンの周波数を得ます。 * L=暗点、H=明点、LHL=1周期として、たとえばLHLHLの場合は2を返します。LHLHやHLHL等の始端と終端のレベルが異なるパターンを * 検出した場合、関数は失敗します。 * @param i_x1 * ライン1のインデクス * @param i_th_h * 明点の敷居値 * @param i_th_l * 暗点の敷居値 * @param o_edge_index * 検出したエッジ位置(H->L,L->H)のインデクスを受け取る配列。 * [FRQ_POINTS]以上の配列を指定すること。 * @return * 周波数の値。失敗すると-1 * @ */ public int getColFrequency(INyARGsPixelDriver i_reader, NyARIntSize i_raster_size, int i_x1, int i_th_h, int i_th_l, int[] o_edge_index) { double[] cpara = this._cparam; int[] ref_x = this._ref_x; int[] ref_y = this._ref_y; int[] pixcel_temp = this._pixcel_temp; //0,2,4,6,8,10,12,14,16,18,20=(11*20)/2=110 //初期化 int[] freq_count_table = this._freq_count_table; for (int i = 0; i < 10; i++) { freq_count_table[i] = 0; } int[] freq_table = this._freq_table; for (int i = 0; i < 110; i++) { freq_table[i] = 0; } int raster_width = i_raster_size.w; int raster_height = i_raster_size.h; double cpara7 = cpara[7]; double cpara4 = cpara[4]; double cpara1 = cpara[1]; //基準点から4ピクセルを参照パターンとして抽出 for (int i = 0; i < FREQ_SAMPLE_NUM; i++) { int cx0 = 1 + i + i_x1; double cp6_0 = cpara[6] * cx0; double cpx0_0 = cpara[0] * cx0 + cpara[2]; double cpx3_0 = cpara[3] * cx0 + cpara[5]; int pt = 0; for (int i2 = 0; i2 < FRQ_POINTS; i2++) { int cy = 1 + i2 * FRQ_STEP + FRQ_EDGE; double d = cp6_0 + cpara7 * cy + 1.0; int x = (int)((cpx0_0 + cpara1 * cy) / d); int y = (int)((cpx3_0 + cpara4 * cy) / d); if (x < 0 || y < 0 || x >= raster_width || y >= raster_height) { return -1; } ref_x[pt] = x; ref_y[pt] = y; pt++; } //ピクセルを取得(入力画像を多様化するならここを調整すること) i_reader.getPixelSet(ref_x, ref_y, FRQ_POINTS, pixcel_temp, 0); int freq_t = getFreqInfo(pixcel_temp, i_th_h, i_th_l, o_edge_index); //周期は3-10であること if (freq_t < MIN_FREQ || freq_t > MAX_FREQ) { continue; } //周期は等間隔であること if (!checkFreqWidth(o_edge_index, freq_t)) { continue; } //検出カウンタを追加 freq_count_table[freq_t]++; int table_st = (freq_t - 1) * freq_t; for (int i2 = 0; i2 < freq_t * 2; i2++) { freq_table[table_st + i2] += o_edge_index[i2]; } } return getMaxFreq(freq_count_table, freq_table, o_edge_index); }
/** * この関数は、マーカパターンからデータを読み取ります。 * @param i_reader * ラスタリーダ * @param i_raster_size * ラスタのサイズ * @param i_th * 敷居値情報 * @param o_bitbuffer * データビットの出力先 * @return * 成功するとtrue * @ */ public bool readDataBits(INyARGsPixelDriver i_reader, NyARIntSize i_raster_size, PerspectivePixelReader.TThreshold i_th, MarkerPattEncoder o_bitbuffer) { int raster_width = i_raster_size.w; int raster_height = i_raster_size.h; double[] index_x = this.__readDataBits_index_bit_x; double[] index_y = this.__readDataBits_index_bit_y; //読み出し位置を取得 int size = detectDataBitsIndex(i_reader, i_raster_size, i_th, index_x, index_y); int resolution = size + size - 1; if (size < 0) { return false; } if (!o_bitbuffer.initEncoder(size - 1)) { return false; } double[] cpara = this._cparam; int[] ref_x = this._ref_x; int[] ref_y = this._ref_y; int[] pixcel_temp = this._pixcel_temp; double cpara_0 = cpara[0]; double cpara_1 = cpara[1]; double cpara_3 = cpara[3]; double cpara_6 = cpara[6]; int th = i_th.th; int p = 0; for (int i = 0; i < resolution; i++) { //1列分のピクセルのインデックス値を計算する。 double cy0 = 1 + index_y[i * 2 + 0]; double cy1 = 1 + index_y[i * 2 + 1]; double cpy0_12 = cpara_1 * cy0 + cpara[2]; double cpy0_45 = cpara[4] * cy0 + cpara[5]; double cpy0_7 = cpara[7] * cy0 + 1.0; double cpy1_12 = cpara_1 * cy1 + cpara[2]; double cpy1_45 = cpara[4] * cy1 + cpara[5]; double cpy1_7 = cpara[7] * cy1 + 1.0; int pt = 0; for (int i2 = 0; i2 < resolution; i2++) { int xx, yy; double d; double cx0 = 1 + index_x[i2 * 2 + 0]; double cx1 = 1 + index_x[i2 * 2 + 1]; double cp6_0 = cpara_6 * cx0; double cpx0_0 = cpara_0 * cx0; double cpx3_0 = cpara_3 * cx0; double cp6_1 = cpara_6 * cx1; double cpx0_1 = cpara_0 * cx1; double cpx3_1 = cpara_3 * cx1; d = cp6_0 + cpy0_7; ref_x[pt] = xx = (int)((cpx0_0 + cpy0_12) / d); ref_y[pt] = yy = (int)((cpx3_0 + cpy0_45) / d); if (xx < 0 || xx >= raster_width || yy < 0 || yy >= raster_height) { ref_x[pt] = xx < 0 ? 0 : (xx >= raster_width ? raster_width - 1 : xx); ref_y[pt] = yy < 0 ? 0 : (yy >= raster_height ? raster_height - 1 : yy); } pt++; d = cp6_0 + cpy1_7; ref_x[pt] = xx = (int)((cpx0_0 + cpy1_12) / d); ref_y[pt] = yy = (int)((cpx3_0 + cpy1_45) / d); if (xx < 0 || xx >= raster_width || yy < 0 || yy >= raster_height) { ref_x[pt] = xx < 0 ? 0 : (xx >= raster_width ? raster_width - 1 : xx); ref_y[pt] = yy < 0 ? 0 : (yy >= raster_height ? raster_height - 1 : yy); } pt++; d = cp6_1 + cpy0_7; ref_x[pt] = xx = (int)((cpx0_1 + cpy0_12) / d); ref_y[pt] = yy = (int)((cpx3_1 + cpy0_45) / d); if (xx < 0 || xx >= raster_width || yy < 0 || yy >= raster_height) { ref_x[pt] = xx < 0 ? 0 : (xx >= raster_width ? raster_width - 1 : xx); ref_y[pt] = yy < 0 ? 0 : (yy >= raster_height ? raster_height - 1 : yy); } pt++; d = cp6_1 + cpy1_7; ref_x[pt] = xx = (int)((cpx0_1 + cpy1_12) / d); ref_y[pt] = yy = (int)((cpx3_1 + cpy1_45) / d); if (xx < 0 || xx >= raster_width || yy < 0 || yy >= raster_height) { ref_x[pt] = xx < 0 ? 0 : (xx >= raster_width ? raster_width - 1 : xx); ref_y[pt] = yy < 0 ? 0 : (yy >= raster_height ? raster_height - 1 : yy); } pt++; } //1行分のピクセルを取得(場合によっては専用アクセサを書いた方がいい) i_reader.getPixelSet(ref_x, ref_y, resolution * 4, pixcel_temp, 0); //グレースケールにしながら、line→mapへの転写 for (int i2 = 0; i2 < resolution; i2++) { int index = i2 * 4; int pixel = (pixcel_temp[index + 0] + pixcel_temp[index + 1] + pixcel_temp[index + 2] + pixcel_temp[index + 3]) / 4; // +pixcel_temp[index+4]+pixcel_temp[index+5]+ // pixcel_temp[index+6]+pixcel_temp[index+7]+pixcel_temp[index+8]+ // pixcel_temp[index+9]+pixcel_temp[index+10]+pixcel_temp[index+11])/(4*3); //暗点を1、明点を0で表現します。 o_bitbuffer.setBitByBitIndex(p, pixel > th ? 0 : 1); p++; } } return true; }
/** * この関数は、ラスタをラべリングします。 * 結果は、o_destinationに出力します。 * <p>メモ - * この関数の元になるARToolKitの関数は、static ARInt16 *labeling2( ARUint8 *image, int thresh,int *label_num, int **area, double **pos, int **clip,int **label_ref, int LorR )です。 * </p> * @param i_raster * 入力元の二値ラスタオブジェクトです。画素形式は、{@link NyARBufferType#INT1D_BIN_8}である必要があります。 * @param o_destination * ラべリング画像の出力先オブジェクトです。i_rasterと同じサイズである必要があります。 * @ */ public int labeling(NyARBinRaster i_raster, NyARLabelingImage o_destination) { Debug.Assert(i_raster.getBufferType() == NyARBufferType.INT1D_BIN_8); int label_img_ptr1, label_pixel; int i, j; int n, k; /* work */ // サイズチェック NyARIntSize in_size = i_raster.getSize(); Debug.Assert(o_destination.getSize().isEqualSize(in_size)); int lxsize = in_size.w; // lxsize = arUtil_c.arImXsize; int lysize = in_size.h; // lysize = arUtil_c.arImYsize; int[] label_img = (int[])o_destination.getBuffer(); // 枠作成はインスタンスを作った直後にやってしまう。 // ラベリング情報のリセット(ラベリングインデックスを使用) o_destination.reset(true); int[] label_idxtbl = o_destination.getIndexArray(); int[] raster_buf = (int[])i_raster.getBuffer(); int[] work2_pt; int wk_max = 0; int pixel_index; int[][] work2 = this._work_holder.work2; // [1,1](ptr0)と、[0,1](ptr1)のインデクス値を計算する。 for (j = 1; j < lysize - 1; j++) { // for (int j = 1; j < lysize - 1;j++, pnt += poff*2, pnt2 += 2) { pixel_index = j * lxsize + 1; label_img_ptr1 = pixel_index - lxsize; // label_img_pt1 = label_img[j - 1]; for (i = 1; i < lxsize - 1; i++, pixel_index++, label_img_ptr1++) { // for(int i = 1; i < lxsize-1;i++, pnt+=poff, pnt2++) { // RGBの合計値が閾値より小さいかな? if (raster_buf[pixel_index] != 0) { label_img[pixel_index] = 0;// label_img_pt0[i] = 0;// *pnt2 = 0; } else { // pnt1 = ShortPointer.wrap(pnt2, -lxsize);//pnt1 =&(pnt2[-lxsize]); if (label_img[label_img_ptr1] > 0) { // if (label_img_pt1[i] > 0) {// if( *pnt1 > 0 ) { label_pixel = label_img[label_img_ptr1]; // label_pixel = label_img_pt1[i];// *pnt2 = *pnt1; work2_pt = work2[label_pixel - 1]; work2_pt[0]++; // work2[((*pnt2)-1)*7+0] ++; work2_pt[1] += i; // work2[((*pnt2)-1)*7+1] += i; work2_pt[2] += j; // work2[((*pnt2)-1)*7+2] += j; work2_pt[6] = j; // work2[((*pnt2)-1)*7+6] = j; } else if (label_img[label_img_ptr1 + 1] > 0) { // } else if (label_img_pt1[i + 1] > 0) {// }else if(*(pnt1+1) > 0 ) { if (label_img[label_img_ptr1 - 1] > 0) { // if (label_img_pt1[i - 1] > 0) {// if( *(pnt1-1) > 0 ) { label_pixel = label_idxtbl[label_img[label_img_ptr1 + 1] - 1]; // m = label_idxtbl[label_img_pt1[i + 1] - 1];// m // =work[*(pnt1+1)-1]; n = label_idxtbl[label_img[label_img_ptr1 - 1] - 1]; // n = label_idxtbl[label_img_pt1[i - 1] - 1];// n =work[*(pnt1-1)-1]; if (label_pixel > n) { // wk=IntPointer.wrap(work, 0);//wk = &(work[0]); for (k = 0; k < wk_max; k++) { if (label_idxtbl[k] == label_pixel) { // if( *wk == m ) label_idxtbl[k] = n; // *wk = n; } } label_pixel = n;// *pnt2 = n; } else if (label_pixel < n) { // wk=IntPointer.wrap(work,0);//wk = &(work[0]); for (k = 0; k < wk_max; k++) { if (label_idxtbl[k] == n) { // if( *wk == n ){ label_idxtbl[k] = label_pixel; // *wk = m; } } } work2_pt = work2[label_pixel - 1]; work2_pt[0]++; work2_pt[1] += i; work2_pt[2] += j; work2_pt[6] = j; } else if ((label_img[pixel_index - 1]) > 0) { // } else if ((label_img_pt0[i - 1]) > 0) {// }else if(*(pnt2-1) > 0) { label_pixel = label_idxtbl[label_img[label_img_ptr1 + 1] - 1]; // m = label_idxtbl[label_img_pt1[i + 1] - 1];// m =work[*(pnt1+1)-1]; n = label_idxtbl[label_img[pixel_index - 1] - 1]; // n = label_idxtbl[label_img_pt0[i - 1] - 1];// n =work[*(pnt2-1)-1]; if (label_pixel > n) { for (k = 0; k < wk_max; k++) { if (label_idxtbl[k] == label_pixel) { // if( *wk == m ){ label_idxtbl[k] = n; // *wk = n; } } label_pixel = n;// *pnt2 = n; } else if (label_pixel < n) { for (k = 0; k < wk_max; k++) { if (label_idxtbl[k] == n) { // if( *wk == n ){ label_idxtbl[k] = label_pixel; // *wk = m; } } } work2_pt = work2[label_pixel - 1]; work2_pt[0]++; // work2[((*pnt2)-1)*7+0] ++; work2_pt[1] += i; // work2[((*pnt2)-1)*7+1] += i; work2_pt[2] += j; // work2[((*pnt2)-1)*7+2] += j; } else { label_pixel = label_img[label_img_ptr1 + 1];// label_pixel = label_img_pt1[i + 1];// *pnt2 = // *(pnt1+1); work2_pt = work2[label_pixel - 1]; work2_pt[0]++; // work2[((*pnt2)-1)*7+0] ++; work2_pt[1] += i; // work2[((*pnt2)-1)*7+1] += i; work2_pt[2] += j; // work2[((*pnt2)-1)*7+2] += j; if (work2_pt[3] > i) { // if(work2[((*pnt2)-1)*7+3] > i ){ work2_pt[3] = i; // work2[((*pnt2)-1)*7+3] = i; } work2_pt[6] = j; // work2[((*pnt2)-1)*7+6] = j; } } else if ((label_img[label_img_ptr1 - 1]) > 0) { // } else if ((label_img_pt1[i - 1]) > 0) {// }else if( // *(pnt1-1) > 0 ) { label_pixel = label_img[label_img_ptr1 - 1]; // label_pixel = label_img_pt1[i - 1];// *pnt2 = // *(pnt1-1); work2_pt = work2[label_pixel - 1]; work2_pt[0]++; // work2[((*pnt2)-1)*7+0] ++; work2_pt[1] += i; // work2[((*pnt2)-1)*7+1] += i; work2_pt[2] += j; // work2[((*pnt2)-1)*7+2] += j; if (work2_pt[4] < i) { // if( work2[((*pnt2)-1)*7+4] <i ){ work2_pt[4] = i; // work2[((*pnt2)-1)*7+4] = i; } work2_pt[6] = j; // work2[((*pnt2)-1)*7+6] = j; } else if (label_img[pixel_index - 1] > 0) { // } else if (label_img_pt0[i - 1] > 0) {// }else if(*(pnt2-1) > 0) { label_pixel = label_img[pixel_index - 1]; // label_pixel = label_img_pt0[i - 1];// *pnt2 =*(pnt2-1); work2_pt = work2[label_pixel - 1]; work2_pt[0]++; // work2[((*pnt2)-1)*7+0] ++; work2_pt[1] += i; // work2[((*pnt2)-1)*7+1] += i; work2_pt[2] += j; // work2[((*pnt2)-1)*7+2] += j; if (work2_pt[4] < i) { // if( work2[((*pnt2)-1)*7+4] <i ){ work2_pt[4] = i; // work2[((*pnt2)-1)*7+4] = i; } } else { // 現在地までの領域を予約 this._work_holder.reserv(wk_max); wk_max++; label_idxtbl[wk_max - 1] = wk_max; label_pixel = wk_max;// work[wk_max-1] = *pnt2 = wk_max; work2_pt = work2[wk_max - 1]; work2_pt[0] = 1; work2_pt[1] = i; work2_pt[2] = j; work2_pt[3] = i; work2_pt[4] = i; work2_pt[5] = j; work2_pt[6] = j; } label_img[pixel_index] = label_pixel;// label_img_pt0[i] = label_pixel; } } } // インデックステーブルとラベル数の計算 int wlabel_num = 1;// *label_num = *wlabel_num = j - 1; for (i = 0; i < wk_max; i++) { // for(int i = 1; i <= wk_max; i++,wk++) { label_idxtbl[i] = (label_idxtbl[i] == i + 1) ? wlabel_num++ : label_idxtbl[label_idxtbl[i] - 1]; // *wk=(*wk==i)?j++:work[(*wk)-1]; } wlabel_num -= 1; // *label_num = *wlabel_num = j - 1; if (wlabel_num == 0) { // if( *label_num == 0 ) { // 発見数0 o_destination.getLabelStack().clear(); return(0); } // ラベル情報の保存等 NyARLabelingLabelStack label_list = o_destination.getLabelStack(); // ラベルバッファを予約 label_list.init(wlabel_num); // エリアと重心、クリップ領域を計算 NyARLabelingLabel label_pt; NyARLabelingLabel[] labels = label_list.getArray(); for (i = 0; i < wlabel_num; i++) { label_pt = labels[i]; label_pt.id = (short)(i + 1); label_pt.area = 0; label_pt.pos_x = label_pt.pos_y = 0; label_pt.clip_l = lxsize; // wclip[i*4+0] = lxsize; label_pt.clip_t = lysize; // wclip[i*4+2] = lysize; label_pt.clip_r = label_pt.clip_b = 0; // wclip[i*4+3] = 0; } for (i = 0; i < wk_max; i++) { label_pt = labels[label_idxtbl[i] - 1]; work2_pt = work2[i]; label_pt.area += work2_pt[0]; label_pt.pos_x += work2_pt[1]; label_pt.pos_y += work2_pt[2]; if (label_pt.clip_l > work2_pt[3]) { label_pt.clip_l = work2_pt[3]; } if (label_pt.clip_r < work2_pt[4]) { label_pt.clip_r = work2_pt[4]; } if (label_pt.clip_t > work2_pt[5]) { label_pt.clip_t = work2_pt[5]; } if (label_pt.clip_b < work2_pt[6]) { label_pt.clip_b = work2_pt[6]; } } for (i = 0; i < wlabel_num; i++) {// for(int i = 0; i < *label_num; i++ ) { label_pt = labels[i]; label_pt.pos_x /= label_pt.area; label_pt.pos_y /= label_pt.area; } return(wlabel_num); }