public void build(INyARGrayscaleRaster i_raster) { Debug.Assert(i_raster.getSize().isEqualSize(this.mPyramid[0].getSize())); Debug.Assert(this.mPyramid.Length == mNumOctaves * mNumScalesPerOctave); // First octave apply_filter(mPyramid[0], i_raster); apply_filter(mPyramid[1], mPyramid[0]); apply_filter_twice(mPyramid[2], mPyramid[1]); // Remaining octaves for (int i = 1; i < mNumOctaves; i++) { // Downsample downsample_bilinear( (double[])mPyramid[i * mNumScalesPerOctave].getBuffer(), (double[])mPyramid[i * mNumScalesPerOctave - 1].getBuffer(), mPyramid[i * mNumScalesPerOctave - 1].getWidth(), mPyramid[i * mNumScalesPerOctave - 1].getHeight()); // Apply binomial filters apply_filter(mPyramid[i * mNumScalesPerOctave + 1], mPyramid[i * mNumScalesPerOctave]); apply_filter_twice(mPyramid[i * mNumScalesPerOctave + 2], mPyramid[i * mNumScalesPerOctave + 1]); } return; }
public override void doFilter(int i_l, int i_t, int i_w, int i_h, int i_th, INyARGrayscaleRaster i_gsraster) { Debug.Assert(i_gsraster.isEqualBufferType(NyARBufferType.INT1D_BIN_8)); INyARRgbPixelDriver input = this._raster.getRgbPixelDriver(); int[] output = (int[])i_gsraster.getBuffer(); int th = i_th * 3; NyARIntSize s = i_gsraster.getSize(); int skip_dst = (s.w - i_w); int skip_src = skip_dst; //左上から1行づつ走査していく int pt_dst = (i_t * s.w + i_l); int[] rgb = this.__rgb; for (int y = 0; y <i_h; y++) { int x; for (x = 0; x < i_w; x++) { input.getPixel(x + i_l, y + i_t, rgb); output[pt_dst++] = (rgb[0] + rgb[1] + rgb[2]) <= th ? 0 : 1; } //スキップ pt_dst += skip_dst; } return; }
public override void doFilter(int i_l, int i_t, int i_w, int i_h, int i_th, INyARGrayscaleRaster i_gsraster) { Debug.Assert(i_gsraster.isEqualBufferType(NyARBufferType.INT1D_BIN_8)); INyARRgbPixelDriver input = this._raster.getRgbPixelDriver(); int[] output = (int[])i_gsraster.getBuffer(); int th = i_th * 3; NyARIntSize s = i_gsraster.getSize(); int skip_dst = (s.w - i_w); int skip_src = skip_dst; //左上から1行づつ走査していく int pt_dst = (i_t * s.w + i_l); int[] rgb = this.__rgb; for (int y = 0; y < i_h; y++) { int x; for (x = 0; x < i_w; x++) { input.getPixel(x + i_l, y + i_t, rgb); output[pt_dst++] = (rgb[0] + rgb[1] + rgb[2]) <= th ? 0 : 1; } //スキップ pt_dst += skip_dst; } return; }
/** * この関数は、ラスタの指定点を基点に、輪郭線を抽出します。 * 開始点は、輪郭の一部である必要があります。 * 通常は、ラべリングの結果の上辺クリップとX軸エントリポイントを開始点として入力します。 * @param i_raster * 輪郭線を抽出するラスタを指定します。 * @param i_th * 輪郭とみなす暗点の敷居値を指定します。 * @param i_entry_x * 輪郭抽出の開始点です。 * @param i_entry_y * 輪郭抽出の開始点です。 * @param o_coord * 輪郭点を格納する配列を指定します。i_array_sizeよりも大きなサイズの配列が必要です。 * @return * 輪郭の抽出に成功するとtrueを返します。輪郭抽出に十分なバッファが無いと、falseになります。 * @ */ public bool getContour(INyARGrayscaleRaster i_raster, int i_th, int i_entry_x, int i_entry_y, NyARIntCoordinates o_coord) { NyARIntSize s = i_raster.getSize(); //ラスタドライバの切り替え if (i_raster != this._ref_last_input_raster) { this._imdriver = (IRasterDriver)i_raster.createInterface(typeof(IRasterDriver)); this._ref_last_input_raster = i_raster; } return(this._imdriver.getContour(0, 0, s.w - 1, s.h - 1, i_entry_x, i_entry_y, i_th, o_coord)); }
public void copyTo(int i_left, int i_top, int i_skip, INyARGrayscaleRaster o_output) { Debug.Assert(this._raster.getSize().isInnerSize(i_left + o_output.getWidth() * i_skip, i_top + o_output.getHeight() * i_skip)); int[] input = (int[])this._raster.getBuffer(); switch (o_output.getBufferType()) { case NyARBufferType.INT1D_GRAY_8: int[] output = (int[])o_output.getBuffer(); NyARIntSize dest_size = o_output.getSize(); NyARIntSize src_size = this._raster.getSize(); int skip_src_y = (src_size.w - dest_size.w * i_skip) + src_size.w * (i_skip - 1); int pix_count = dest_size.w; int pix_mod_part = pix_count - (pix_count % 8); // 左上から1行づつ走査していく int pt_dst = 0; int pt_src = (i_top * src_size.w + i_left); for (int y = dest_size.h - 1; y >= 0; y -= 1) { int x; for (x = pix_count - 1; x >= pix_mod_part; x--) { output[pt_dst++] = input[pt_src]; pt_src += i_skip; } for (; x >= 0; x -= 8) { output[pt_dst++] = input[pt_src]; pt_src += i_skip; output[pt_dst++] = input[pt_src]; pt_src += i_skip; output[pt_dst++] = input[pt_src]; pt_src += i_skip; output[pt_dst++] = input[pt_src]; pt_src += i_skip; output[pt_dst++] = input[pt_src]; pt_src += i_skip; output[pt_dst++] = input[pt_src]; pt_src += i_skip; output[pt_dst++] = input[pt_src]; pt_src += i_skip; output[pt_dst++] = input[pt_src]; pt_src += i_skip; } // スキップ pt_src += skip_src_y; } return; default: throw new NyARException(); } }
public void copyTo(int i_left, int i_top, int i_skip, INyARGrayscaleRaster o_output) { Debug.Assert(this._raster.getSize().isInnerSize(i_left + o_output.getWidth() * i_skip, i_top + o_output.getHeight() * i_skip)); int[] input = (int[])this._raster.getBuffer(); switch (o_output.getBufferType()) { case NyARBufferType.INT1D_GRAY_8: int[] output = (int[])o_output.getBuffer(); NyARIntSize dest_size = o_output.getSize(); NyARIntSize src_size = this._raster.getSize(); int skip_src_y = (src_size.w - dest_size.w * i_skip) + src_size.w * (i_skip - 1); int pix_count = dest_size.w; int pix_mod_part = pix_count - (pix_count % 8); // 左上から1行づつ走査していく int pt_dst = 0; int pt_src = (i_top * src_size.w + i_left); for (int y = dest_size.h - 1; y >= 0; y -= 1) { int x; for (x = pix_count - 1; x >= pix_mod_part; x--) { output[pt_dst++] = input[pt_src]; pt_src += i_skip; } for (; x >= 0; x -= 8) { output[pt_dst++] = input[pt_src]; pt_src += i_skip; output[pt_dst++] = input[pt_src]; pt_src += i_skip; output[pt_dst++] = input[pt_src]; pt_src += i_skip; output[pt_dst++] = input[pt_src]; pt_src += i_skip; output[pt_dst++] = input[pt_src]; pt_src += i_skip; output[pt_dst++] = input[pt_src]; pt_src += i_skip; output[pt_dst++] = input[pt_src]; pt_src += i_skip; output[pt_dst++] = input[pt_src]; pt_src += i_skip; } // スキップ pt_src += skip_src_y; } return; default: throw new NyARException(); } }
public override void doFilter(int i_l, int i_t, int i_w, int i_h, int i_th, INyARGrayscaleRaster i_gsraster) { Debug.Assert(i_gsraster.isEqualBufferType(NyARBufferType.INT1D_BIN_8)); short[] input = (short[])this._raster.getBuffer(); int[] output = (int[])i_gsraster.getBuffer(); int th = i_th * 3; NyARIntSize s = i_gsraster.getSize(); int skip_dst = (s.w - i_w); int skip_src = skip_dst; int pix_count = i_w; int pix_mod_part = pix_count - (pix_count % 8); //左上から1行づつ走査していく int pt_dst = (i_t * s.w + i_l); int pt_src = pt_dst; for (int y = i_h - 1; y >= 0; y -= 1) { int x, v; for (x = pix_count - 1; x >= pix_mod_part; x--) { v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; } for (; x >= 0; x -= 8) { v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; } //スキップ pt_src += skip_src; pt_dst += skip_dst; } return; }
/** * この関数は、ラスタの指定点を基点に、輪郭線を抽出します。 * 開始点は、輪郭の一部である必要があります。 * 通常は、ラべリングの結果の上辺クリップとX軸エントリポイントを開始点として入力します。 * @param i_raster * 輪郭線を抽出するラスタを指定します。 * @param i_th * 輪郭とみなす暗点の敷居値を指定します。 * @param i_entry_x * 輪郭抽出の開始点です。 * @param i_entry_y * 輪郭抽出の開始点です。 * @param o_coord * 輪郭点を格納する配列を指定します。i_array_sizeよりも大きなサイズの配列が必要です。 * @return * 輪郭の抽出に成功するとtrueを返します。輪郭抽出に十分なバッファが無いと、falseになります。 * @ */ public bool getContour(INyARGrayscaleRaster i_raster, int i_th, int i_entry_x, int i_entry_y, NyARIntCoordinates o_coord) { NyARIntSize s = i_raster.getSize(); //ラスタドライバの切り替え if (i_raster != this._ref_last_input_raster) { this._imdriver = (IRasterDriver)i_raster.createInterface(typeof(IRasterDriver)); this._ref_last_input_raster = i_raster; } return this._imdriver.getContour(0, 0, s.w - 1, s.h - 1, i_entry_x, i_entry_y, i_th, o_coord); }
public override void doFilter(int i_l, int i_t, int i_w, int i_h, int i_th, INyARGrayscaleRaster i_gsraster) { Debug.Assert(i_gsraster.isEqualBufferType(NyARBufferType.INT1D_BIN_8)); short[] input = (short[])this._raster.getBuffer(); int[] output = (int[])i_gsraster.getBuffer(); int th = i_th * 3; NyARIntSize s = i_gsraster.getSize(); int skip_dst = (s.w - i_w); int skip_src = skip_dst; int pix_count = i_w; int pix_mod_part = pix_count - (pix_count % 8); //左上から1行づつ走査していく int pt_dst = (i_t * s.w + i_l); int pt_src = pt_dst; for (int y = i_h - 1; y >= 0; y -= 1) { int x, v; for (x = pix_count - 1; x >= pix_mod_part; x--) { v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; } for (; x >= 0; x -= 8) { v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; v = (int)input[pt_src++]; output[pt_dst++] = (((v & 0xf800) >> 8) + ((v & 0x07e0) >> 3) + ((v & 0x001f) << 3)) <= th ? 0 : 1; } //スキップ pt_src += skip_src; pt_dst += skip_dst; } return; }
/** * この関数は、ラスタを敷居値i_thで2値化して、ラベリングします。 * 検出したラベルは、自己コールバック関数{@link #onLabelFound}で通知します。 * @param i_bin_raster * 入力画像。対応する形式は、クラスの説明を参照してください。 * @param i_th * 敷居値を指定します。2値画像の場合は、0を指定してください。 * @ */ public virtual bool labeling(INyARGrayscaleRaster i_raster, int i_th) { NyARIntSize size = i_raster.getSize(); return(this.imple_labeling(i_raster, i_th, 0, 0, size.w, size.h)); }
/** * この関数はマーカパターンから、敷居値を決定します。 * @param i_reader * ラスタリーダオブジェクト * @param i_raster_size * ラスのタのサイズ * @param o_threshold * 敷居値を受け取るオブジェクト * @ */ public void detectThresholdValue(INyARGrayscaleRaster i_raster, TThreshold o_threshold) { int[] th_pixels = this._th_pixels; NyARIntSize size = i_raster.getSize(); //左上のピックアップ領域からピクセルを得る(00-24) rectPixels(i_raster, THRESHOLD_SAMPLE_LT, THRESHOLD_SAMPLE_LT, THRESHOLD_STEP, THRESHOLD_STEP, THRESHOLD_PIXEL, THRESHOLD_PIXEL, 0, th_pixels); //左下のピックアップ領域からピクセルを得る(25-49) rectPixels(i_raster, THRESHOLD_SAMPLE_LT, THRESHOLD_SAMPLE_RB, THRESHOLD_STEP, THRESHOLD_STEP, THRESHOLD_PIXEL, THRESHOLD_PIXEL, THRESHOLD_SAMPLE, th_pixels); //右上のピックアップ領域からピクセルを得る(50-74) rectPixels(i_raster, THRESHOLD_SAMPLE_RB, THRESHOLD_SAMPLE_LT, THRESHOLD_STEP, THRESHOLD_STEP, THRESHOLD_PIXEL, THRESHOLD_PIXEL, THRESHOLD_SAMPLE * 2, th_pixels); //右下のピックアップ領域からピクセルを得る(75-99) rectPixels(i_raster, THRESHOLD_SAMPLE_RB, THRESHOLD_SAMPLE_RB, THRESHOLD_STEP, THRESHOLD_STEP, THRESHOLD_PIXEL, THRESHOLD_PIXEL, THRESHOLD_SAMPLE * 3, th_pixels); THighAndLow hl = this.__detectThresholdValue_hl; //Ptailで求めたピクセル平均 getPtailHighAndLow(th_pixels, hl); //閾値中心 int th = (hl.h + hl.l) / 2; //ヒステリシス(差分の20%) int th_sub = (hl.h - hl.l) / 5; o_threshold.th = th; o_threshold.th_h = th + th_sub; //ヒステリシス付き閾値 o_threshold.th_l = th - th_sub; //ヒステリシス付き閾値 //エッジを計算(明点重心) int lt_x, lt_y, lb_x, lb_y, rt_x, rt_y, rb_x, rb_y; NyARIntPoint2d tpt = this.__detectThresholdValue_tpt; //LT if (getHighPixelCenter(0, th_pixels, THRESHOLD_PIXEL, THRESHOLD_PIXEL, th, tpt)) { lt_x = tpt.x * THRESHOLD_STEP; lt_y = tpt.y * THRESHOLD_STEP; } else { lt_x = 11; lt_y = 11; } //LB if (getHighPixelCenter(THRESHOLD_SAMPLE * 1, th_pixels, THRESHOLD_PIXEL, THRESHOLD_PIXEL, th, tpt)) { lb_x = tpt.x * THRESHOLD_STEP; lb_y = tpt.y * THRESHOLD_STEP; } else { lb_x = 11; lb_y = -1; } //RT if (getHighPixelCenter(THRESHOLD_SAMPLE * 2, th_pixels, THRESHOLD_PIXEL, THRESHOLD_PIXEL, th, tpt)) { rt_x = tpt.x * THRESHOLD_STEP; rt_y = tpt.y * THRESHOLD_STEP; } else { rt_x = -1; rt_y = 11; } //RB if (getHighPixelCenter(THRESHOLD_SAMPLE * 3, th_pixels, THRESHOLD_PIXEL, THRESHOLD_PIXEL, th, tpt)) { rb_x = tpt.x * THRESHOLD_STEP; rb_y = tpt.y * THRESHOLD_STEP; } else { rb_x = -1; rb_y = -1; } //トラッキング開始位置の決定 o_threshold.lt_x = (lt_x + lb_x) / 2 + THRESHOLD_SAMPLE_LT - 1; o_threshold.rb_x = (rt_x + rb_x) / 2 + THRESHOLD_SAMPLE_RB + 1; o_threshold.lt_y = (lt_y + rt_y) / 2 + THRESHOLD_SAMPLE_LT - 1; o_threshold.rb_y = (lb_y + rb_y) / 2 + THRESHOLD_SAMPLE_RB + 1; return; }
/** * この関数は、マーカ画像の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(INyARGrayscaleRaster i_raster, 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; } NyARIntSize raster_size = i_raster.getSize(); int raster_width = raster_size.w; int raster_height = 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_raster.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)); }