/** * i_raster上にあるi_vertexの頂点で定義される四角形のパターンから、一致するID値を特定します。 * @param i_vertex * 4頂点の座標 * @param i_raster * @param o_result * @return * @throws NyARException */ public bool identifyId(NyARDoublePoint2d[] i_vertex, INyARRgbRaster i_raster, IdentifyIdResult o_result) { if (this._last_laster != i_raster) { this._gs_pix_reader = NyARGsPixelDriverFactory.createDriver(i_raster); this._last_laster = i_raster; } if (!this._id_pickup.pickFromRaster(this._gs_pix_reader, i_vertex, this._temp_nyid_info, this._temp_nyid_param)) { return(false); } if (!this._rb.Encode(this._temp_nyid_info, this._rb_dest)) { return(false); } //SerialID引きする。 SerialTable.SerialTableRow d = this._table.getItembySerialId(this._rb_dest.marker_id); if (d == null) { return(false); } //戻り値を設定 o_result.marker_width = d.marker_width; o_result.id = this._rb_dest.marker_id; o_result.artk_direction = this._temp_nyid_param.direction; o_result.name = d.name; return(true); }
/** * この関数は、ラスタドライバから画像を読み出します。 * @param i_pix_drv * @param i_size * @param i_vertex * @param o_data * @param o_param * @return * @throws NyARException */ public bool getARPlayCardId(INyARGsPixelDriver i_pix_drv, NyARIntPoint2d[] i_vertex, PsArIdParam i_result) { if (!this._perspective_reader.setSourceSquare(i_vertex)) { return false; } return this._pickFromRaster(i_pix_drv, i_result); }
/** * この関数は、ラスタドライバから画像を読み出します。 * @param i_pix_drv * @param i_size * @param i_vertex * @param o_data * @param o_param * @return * @throws NyARException */ public bool getARPlayCardId(INyARGsPixelDriver i_pix_drv, NyARDoublePoint2d[] i_vertex, PsArIdParam i_result) { if (!this._perspective_reader.setSourceSquare(i_vertex)) { return(false); } return(this._pickFromRaster(i_pix_drv, i_result)); }
/** * この関数は、ラスタドライバから画像を読み出します。 * @param i_pix_drv * @param i_size * @param i_vertex * @param o_data * @param o_param * @return * @ */ public bool pickFromRaster(INyARGsPixelDriver i_pix_drv, NyARIntPoint2d[] i_vertex, NyIdMarkerPattern o_data, NyIdMarkerParam o_param) { if (!this._perspective_reader.setSourceSquare(i_vertex)) { return false; } return this._pickFromRaster(i_pix_drv, o_data, o_param); }
/** * この関数は、ラスタドライバから画像を読み出します。 * @param i_pix_drv * @param i_size * @param i_vertex * @param o_data * @param o_param * @return * @ */ public bool pickFromRaster(INyARGsPixelDriver i_pix_drv, NyARDoublePoint2d[] i_vertex, NyIdMarkerPattern o_data, NyIdMarkerParam o_param) { if (!this._perspective_reader.setSourceSquare(i_vertex)) { return(false); } return(this._pickFromRaster(i_pix_drv, o_data, o_param)); }
/** * i_imageから、idマーカを読みだします。 * o_dataにはマーカデータ、o_paramにはマーカのパラメータを返却します。 * @param image * @param i_vertex * @param o_data * @param o_param * @return * @throws NyARException */ private bool _pickFromRaster(INyARGsPixelDriver i_pix_drv, PsArIdParam i_result) { if (!this._perspective_reader.readDataBits(i_pix_drv, i_pix_drv.getSize(), this._decoder)) { return(false); } //敷居値検索 return(this._decoder.decodePatt(i_result)); }
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); int b = t + h; int row_padding_dst = (size.w - w); int row_padding_src = row_padding_dst; int pix_count = w; int pix_mod_part = pix_count - (pix_count % 8); int src_ptr = t * size.w + l; int[] in_buf = (int[])this._ref_raster.getBuffer(); switch (o_raster.getBufferType()) { case NyARBufferType.INT1D_GRAY_8: int v; 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--) { v = in_buf[src_ptr++]; out_buf[bp++] = (((v >> 16) & 0xff) + ((v >> 8) & 0xff) + (v & 0xff)) >> 2; } for (; x >= 0; x -= 8) { v = in_buf[src_ptr++]; out_buf[bp++] = (((v >> 16) & 0xff) + ((v >> 8) & 0xff) + (v & 0xff)) / 3; v = in_buf[src_ptr++]; out_buf[bp++] = (((v >> 16) & 0xff) + ((v >> 8) & 0xff) + (v & 0xff)) / 3; v = in_buf[src_ptr++]; out_buf[bp++] = (((v >> 16) & 0xff) + ((v >> 8) & 0xff) + (v & 0xff)) / 3; v = in_buf[src_ptr++]; out_buf[bp++] = (((v >> 16) & 0xff) + ((v >> 8) & 0xff) + (v & 0xff)) / 3; v = in_buf[src_ptr++]; out_buf[bp++] = (((v >> 16) & 0xff) + ((v >> 8) & 0xff) + (v & 0xff)) / 3; v = in_buf[src_ptr++]; out_buf[bp++] = (((v >> 16) & 0xff) + ((v >> 8) & 0xff) + (v & 0xff)) / 3; v = in_buf[src_ptr++]; out_buf[bp++] = (((v >> 16) & 0xff) + ((v >> 8) & 0xff) + (v & 0xff)) / 3; v = in_buf[src_ptr++]; out_buf[bp++] = (((v >> 16) & 0xff) + ((v >> 8) & 0xff) + (v & 0xff)) / 3; } bp += row_padding_dst; src_ptr += row_padding_src; } return; default: INyARGsPixelDriver out_drv = o_raster.getGsPixelDriver(); for (int y = t; y < b; y++) { for (int x = 0; x < pix_count; x++) { v = in_buf[src_ptr++]; out_drv.setPixel(x, y, (((v >> 16) & 0xff) + ((v >> 8) & 0xff) + (v & 0xff)) / 3); } } return; } }
public void doFilter(INyARGrayscaleRaster i_output) { INyARGsPixelDriver ind = this._raster.getGsPixelDriver(); INyARGsPixelDriver outd = i_output.getGsPixelDriver(); NyARIntSize s = this._raster.getSize(); for (int y = s.h - 1; y >= 0; y--) { for (int x = s.w - 1; x >= 0; x--) { outd.setPixel(x, y, 255 - ind.getPixel(x, y)); } } }
/** * このクラスの初期化シーケンスです。コンストラクタから呼び出します。初期化に失敗すると、例外を発生します。 * @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); }
public void createHistogram(int i_l, int i_t, int i_w, int i_h, int i_skip, NyARHistogram o_histogram) { o_histogram.reset(); int[] data_ptr = o_histogram.data; INyARGsPixelDriver drv = this._gsr.getGsPixelDriver(); int pix_count = i_w; int pix_mod_part = pix_count - (pix_count % 8); //左上から1行づつ走査していく for (int y = i_h - 1; y >= 0; y -= i_skip) { for (int x = pix_count - 1; x >= pix_mod_part; x--) { data_ptr[drv.getPixel(x, y)]++; } } o_histogram.total_of_data = i_w * i_h / i_skip; 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); }
public void convertRect(int l, int t, int w, int h, INyARGrayscaleRaster o_raster) { int[] wk = this._wk; int b = t + h; int pix_count = w; switch (o_raster.getBufferType()) { default: INyARGsPixelDriver out_drv = o_raster.getGsPixelDriver(); INyARRgbPixelDriver in_drv = this._ref_raster.getRgbPixelDriver(); for (int y = t; y < b; y++) { for (int x = pix_count - 1; x >= 0; x--) { in_drv.getPixel(x, y, wk); out_drv.setPixel(x, y, (306 * (wk[2] & 0xff) + 601 * (wk[1] & 0xff) + 117 * (wk[0] & 0xff)) >> 10); } } return; } }
/** * i_imageから、idマーカを読みだします。 * o_dataにはマーカデータ、o_paramにはマーカのパラメータを返却します。 * @param image * @param i_vertex * @param o_data * @param o_param * @return * @ */ private bool _pickFromRaster(INyARGsPixelDriver i_pix_drv, NyIdMarkerPattern o_data, NyIdMarkerParam o_param) { PerspectivePixelReader.TThreshold th = this.__pickFromRaster_th; MarkerPattEncoder encoder = this.__pickFromRaster_encoder; //マーカパラメータを取得 this._perspective_reader.detectThresholdValue(i_pix_drv, th); if (!this._perspective_reader.readDataBits(i_pix_drv, i_pix_drv.getSize(), th, encoder)) { return(false); } int d = encoder.encode(o_data); if (d < 0) { return(false); } o_param.direction = d; o_param.threshold = th.th; return(true); }
/** * この関数は、マーカ画像の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); }
/** * この関数はマーカパターンから、敷居値を決定します。 * @param i_reader * ラスタリーダオブジェクト * @param i_raster_size * ラスのタのサイズ * @param o_threshold * 敷居値を受け取るオブジェクト * @ */ public void detectThresholdValue(INyARGsPixelDriver i_reader, TThreshold o_threshold) { int[] th_pixels = this._th_pixels; NyARIntSize size = i_reader.getSize(); //左上のピックアップ領域からピクセルを得る(00-24) rectPixels(i_reader, size, THRESHOLD_SAMPLE_LT, THRESHOLD_SAMPLE_LT, THRESHOLD_STEP, THRESHOLD_STEP, THRESHOLD_PIXEL, THRESHOLD_PIXEL, 0, th_pixels); //左下のピックアップ領域からピクセルを得る(25-49) rectPixels(i_reader, size, THRESHOLD_SAMPLE_LT, THRESHOLD_SAMPLE_RB, THRESHOLD_STEP, THRESHOLD_STEP, THRESHOLD_PIXEL, THRESHOLD_PIXEL, THRESHOLD_SAMPLE, th_pixels); //右上のピックアップ領域からピクセルを得る(50-74) rectPixels(i_reader, size, THRESHOLD_SAMPLE_RB, THRESHOLD_SAMPLE_LT, THRESHOLD_STEP, THRESHOLD_STEP, THRESHOLD_PIXEL, THRESHOLD_PIXEL, THRESHOLD_SAMPLE * 2, th_pixels); //右下のピックアップ領域からピクセルを得る(75-99) rectPixels(i_reader, size, 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_imageから、idマーカを読みだします。 * o_dataにはマーカデータ、o_paramにはマーカのパラメータを返却します。 * @param image * @param i_vertex * @param o_data * @param o_param * @return * @ */ private bool _pickFromRaster(INyARGsPixelDriver i_pix_drv, NyIdMarkerPattern o_data, NyIdMarkerParam o_param) { PerspectivePixelReader.TThreshold th = this.__pickFromRaster_th; MarkerPattEncoder encoder = this.__pickFromRaster_encoder; //マーカパラメータを取得 this._perspective_reader.detectThresholdValue(i_pix_drv, th); if (!this._perspective_reader.readDataBits(i_pix_drv, i_pix_drv.getSize(), th, encoder)) { return false; } int d = encoder.encode(o_data); if (d < 0) { return false; } o_param.direction = d; o_param.threshold = th.th; return true; }
/** * この関数は、マーカ画像の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)); }
/** * この関数は、マーカパターンからデータを読み取ります。 * @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; }
/** * i_imageから、idマーカを読みだします。 * o_dataにはマーカデータ、o_paramにはマーカのパラメータを返却します。 * @param image * @param i_vertex * @param o_data * @param o_param * @return * @throws NyARException */ private bool _pickFromRaster(INyARGsPixelDriver i_pix_drv, PsArIdParam i_result) { if (!this._perspective_reader.readDataBits(i_pix_drv, i_pix_drv.getSize(), this._decoder)) { return false; } //敷居値検索 return this._decoder.decodePatt(i_result); }
public void convertRect(int l, int t, int w, int h, INyARGrayscaleRaster o_raster) { Color32[] c = (Color32[])(this._ref_raster.getBuffer()); NyARIntSize size = this._ref_raster.getSize(); int src = (l + t * size.w) * 4; int b = t + h; int row_padding_dst = (size.w - w); int row_padding_src = row_padding_dst * 4; int pix_count = w; int pix_mod_part = pix_count - (pix_count % 8); // in_buf = (byte[])this._ref_raster.getBuffer(); switch (o_raster.getBufferType()) { case NyARBufferType.INT1D_GRAY_8: int[] out_buf = (int[])o_raster.getBuffer(); int dst_ptr; if (this._is_inverse) { dst_ptr = (h - 1 - t) * size.w + l; row_padding_dst -= size.w * 2; } else { dst_ptr = t * size.w + l; } for (int y = t; y < b; y++) { int x = 0; Color32 p; for (x = pix_count - 1; x >= pix_mod_part; x--) { p = c[src++]; out_buf[dst_ptr++] = (p.r + p.g + p.b) / 3; } for (; x >= 0; x -= 8) { p = c[src++]; out_buf[dst_ptr++] = (p.r + p.g + p.b) / 3; p = c[src++]; out_buf[dst_ptr++] = (p.r + p.g + p.b) / 3; p = c[src++]; out_buf[dst_ptr++] = (p.r + p.g + p.b) / 3; p = c[src++]; out_buf[dst_ptr++] = (p.r + p.g + p.b) / 3; p = c[src++]; out_buf[dst_ptr++] = (p.r + p.g + p.b) / 3; p = c[src++]; out_buf[dst_ptr++] = (p.r + p.g + p.b) / 3; p = c[src++]; out_buf[dst_ptr++] = (p.r + p.g + p.b) / 3; p = c[src++]; out_buf[dst_ptr++] = (p.r + p.g + p.b) / 3; } dst_ptr += row_padding_dst; src += row_padding_src; } return; default: INyARGsPixelDriver out_drv = o_raster.getGsPixelDriver(); for (int y = t; y < b; y++) { for (int x = 0; x < pix_count; x++) { Color32 p = c[src++]; out_drv.setPixel(x, y, (p.r + p.g + p.b) / 3); } src += row_padding_src; } return; } }
public NyARRlePixelDriver_GSReader(INyARGrayscaleRaster i_raster) { this._ref_driver = i_raster.getGsPixelDriver(); }
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; }
/** * この関数は、マーカ画像の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_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_reader * ラスタリーダオブジェクト * @param i_raster_size * ラスのタのサイズ * @param o_threshold * 敷居値を受け取るオブジェクト * @ */ public void detectThresholdValue(INyARGsPixelDriver i_reader, TThreshold o_threshold) { int[] th_pixels = this._th_pixels; NyARIntSize size = i_reader.getSize(); //左上のピックアップ領域からピクセルを得る(00-24) rectPixels(i_reader, size, THRESHOLD_SAMPLE_LT, THRESHOLD_SAMPLE_LT, THRESHOLD_STEP, THRESHOLD_STEP, THRESHOLD_PIXEL, THRESHOLD_PIXEL, 0, th_pixels); //左下のピックアップ領域からピクセルを得る(25-49) rectPixels(i_reader, size, THRESHOLD_SAMPLE_LT, THRESHOLD_SAMPLE_RB, THRESHOLD_STEP, THRESHOLD_STEP, THRESHOLD_PIXEL, THRESHOLD_PIXEL, THRESHOLD_SAMPLE, th_pixels); //右上のピックアップ領域からピクセルを得る(50-74) rectPixels(i_reader, size, THRESHOLD_SAMPLE_RB, THRESHOLD_SAMPLE_LT, THRESHOLD_STEP, THRESHOLD_STEP, THRESHOLD_PIXEL, THRESHOLD_PIXEL, THRESHOLD_SAMPLE * 2, th_pixels); //右下のピックアップ領域からピクセルを得る(75-99) rectPixels(i_reader, size, 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_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); }
public void convertRect(int l, int t, int w, int h, INyARGrayscaleRaster o_raster) { byte[] work = this._work; BitmapData bm = this._ref_raster.lockBitmap(); NyARIntSize size = this._ref_raster.getSize(); int bp = (l + t * size.w) * 4 + (int)bm.Scan0; int b = t + h; int row_padding_dst = (size.w - w); int row_padding_src = row_padding_dst * 4; int pix_count = w; int pix_mod_part = pix_count - (pix_count % 8); int dst_ptr = t * size.w + l; // 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--) { int p = Marshal.ReadInt32((IntPtr)bp); out_buf[dst_ptr++] = (((p >> 16) & 0xff) + ((p >> 8) & 0xff) + (p & 0xff)) / 3; bp += 4; } for (; x >= 0; x -= 8) { Marshal.Copy((IntPtr)bp, work, 0, 32); out_buf[dst_ptr++] = (work[0] + work[1] + work[2]) / 3; out_buf[dst_ptr++] = (work[4] + work[5] + work[6]) / 3; out_buf[dst_ptr++] = (work[8] + work[9] + work[10]) / 3; out_buf[dst_ptr++] = (work[12] + work[13] + work[14]) / 3; out_buf[dst_ptr++] = (work[16] + work[17] + work[18]) / 3; out_buf[dst_ptr++] = (work[20] + work[21] + work[22]) / 3; out_buf[dst_ptr++] = (work[24] + work[25] + work[26]) / 3; out_buf[dst_ptr++] = (work[28] + work[29] + work[30]) / 3; bp += 32; } bp += row_padding_src; dst_ptr += row_padding_dst; } this._ref_raster.unlockBitmap(); return; default: INyARGsPixelDriver out_drv = o_raster.getGsPixelDriver(); for (int y = t; y < b; y++) { for (int x = 0; x < pix_count; x++) { int p = Marshal.ReadInt32((IntPtr)bp); out_drv.setPixel(x, y, (((p >> 16) & 0xff) + ((p >> 8) & 0xff) + (p & 0xff)) / 3); bp += 4; } bp += row_padding_src; } this._ref_raster.unlockBitmap(); return; } }
/** * この関数は、マーカパターンからデータを読み取ります。 * @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; }
/** * この関数は、マーカパターンからデータを読み取ります。 * @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); }
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); }
/** * この関数は、マーカパターンからデータを読み取ります。 * @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); }
public override bool getContour(int i_l, int i_t, int i_r, int i_b, int i_entry_x, int i_entry_y, int i_th, NyARIntCoordinates o_coord) { Debug.Assert(i_t <= i_entry_x); INyARGsPixelDriver reader = this._ref_raster.getGsPixelDriver(); int[] xdir = _getContour_xdir; // static int xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1}; int[] ydir = _getContour_ydir; // static int ydir[8] = {-1,-1, 0, 1, 1, 1, 0,-1}; //クリップ領域の上端に接しているポイントを得る。 NyARIntPoint2d[] coord = o_coord.items; int max_coord = o_coord.items.Length; coord[0].x = i_entry_x; coord[0].y = i_entry_y; int coord_num = 1; int dir = 5; int c = i_entry_x; int r = i_entry_y; for (; ;) { dir = (dir + 5) % 8;//dirの正規化 //境界に接しているとき int i; for (i = 0; i < 8; i++) { int x = c + xdir[dir]; int y = r + ydir[dir]; //境界チェック if (x >= i_l && x <= i_r && y >= i_t && y <= i_b) { if (reader.getPixel(x, y) <= i_th) { break; } } dir++;//倍長テーブルを参照するので問題なし } if (i == 8) { //8方向全て調べたけどラベルが無いよ? throw new NyARException();// return(-1); } // xcoordとycoordをc,rにも保存 c = c + xdir[dir]; r = r + ydir[dir]; coord[coord_num].x = c; coord[coord_num].y = r; //終了条件判定 if (c == i_entry_x && r == i_entry_y) { //開始点と同じピクセルに到達したら、終点の可能性がある。 coord_num++; //末端のチェック if (coord_num == max_coord) { //輪郭bufが末端に達した return(false); } //末端候補の次のピクセルを調べる dir = (dir + 5) % 8;//dirの正規化 for (i = 0; i < 8; i++) { int x = c + xdir[dir]; int y = r + ydir[dir]; //境界チェック if (x >= i_l && x <= i_r && y >= i_t && y <= i_b) { if (reader.getPixel(x, y) <= i_th) { break; } } dir++;//倍長テーブルを参照するので問題なし } if (i == 8) { //8方向全て調べたけどラベルが無いよ? throw new NyARException(); } //得たピクセルが、[1]と同じならば、末端である。 c = c + xdir[dir]; r = r + ydir[dir]; if (coord[1].x == c && coord[1].y == r) { //終点に達している。 o_coord.length = coord_num; break; } else { //終点ではない。 coord[coord_num].x = c; coord[coord_num].y = r; } } coord_num++; //末端のチェック if (coord_num == max_coord) { //輪郭が末端に達した return(false); } } return(true); }