/** * ピクセル配列の上位、下位の4ピクセルのピクセル値平均を求めます。 * この関数は、(4/i_pixcel.length)の領域を占有するPtail法で双方向の閾値を求めることになります。 * @param i_pixcel * @param i_initial * @param i_out */ private void getPtailHighAndLow(int[] i_pixcel, THighAndLow i_out) { int h3, h2, h1, h0, l3, l2, l1, l0; h3 = h2 = h1 = h0 = l3 = l2 = l1 = l0 = i_pixcel[0]; for (int i = i_pixcel.Length - 1; i >= 1; i--) { int pix = i_pixcel[i]; if (h0 < pix) { if (h1 < pix) { if (h2 < pix) { if (h3 < pix) { h0 = h1; h1 = h2; h2 = h3; h3 = pix; } else { h0 = h1; h1 = h2; h2 = pix; } } else { h0 = h1; h1 = pix; } } else { h0 = pix; } } if (l0 > pix) { if (l1 > pix) { if (l2 > pix) { if (l3 > pix) { l0 = l1; l1 = l2; l2 = l3; l3 = pix; } else { l0 = l1; l1 = l2; l2 = pix; } } else { l0 = l1; l1 = pix; } } else { l0 = pix; } } } i_out.l = (l0 + l1 + l2 + l3) / 4; i_out.h = (h0 + h1 + h2 + h3) / 4; return; }
/** * 指定した場所のピクセル値を調査して、閾値を計算して返します。 * @param i_reader * @param i_x * @param i_y * @return * @throws NyARException */ public void detectThresholdValue(INyARRgbPixelReader i_reader, NyARIntSize i_raster_size, TThreshold o_threshold) { int[] th_pixels = this._th_pixels; //左上のピックアップ領域からピクセルを得る(00-24) rectPixels(i_reader, i_raster_size, THRESHOLD_SAMPLE_LT, THRESHOLD_SAMPLE_LT, THRESHOLD_STEP, THRESHOLD_STEP, THRESHOLD_PIXEL, THRESHOLD_PIXEL, 0, th_pixels); //左下のピックアップ領域からピクセルを得る(25-49) rectPixels(i_reader, i_raster_size, THRESHOLD_SAMPLE_LT, THRESHOLD_SAMPLE_RB, THRESHOLD_STEP, THRESHOLD_STEP, THRESHOLD_PIXEL, THRESHOLD_PIXEL, THRESHOLD_SAMPLE, th_pixels); //右上のピックアップ領域からピクセルを得る(50-74) rectPixels(i_reader, i_raster_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, i_raster_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; }