/** * 輪郭線抽出関数の実体です。 * * @param i_raster * @param i_l * @param i_t * @param i_r * @param i_b * @param i_th * @param i_entry_x * @param i_entry_y * @param o_coord * @return * @throws NyARException */ private boolean impl_getContour( INyARRaster i_raster, int i_l, int i_t, int i_r, int i_b, int i_th, int i_entry_x, int i_entry_y, NyARIntCoordinates o_coord) throws NyARException { assert (i_t <= i_entry_x); NyARIntPoint2d[] coord = o_coord.items; final int[] xdir = _getContour_xdir; // static int xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1}; final int[] ydir = _getContour_ydir; // static int ydir[8] = {-1,-1, 0, 1, 1, 1, 0,-1}; final int[] buf = (int[]) i_raster.getBuffer(); final int width = i_raster.getWidth(); // クリップ領域の上端に接しているポイントを得る。 int max_coord = o_coord.items.length; int coord_num = 1; coord[0].x = i_entry_x; coord[0].y = i_entry_y; int dir = 5; int c = i_entry_x; int r = i_entry_y; for (; ; ) { dir = (dir + 5) % 8; // dirの正規化 // ここは頑張ればもっと最適化できると思うよ。 // 4隅以外の境界接地の場合に、境界チェックを省略するとかね。 if (c > i_l && c < i_r && r > i_t && r < i_b) { for (; ; ) { // gotoのエミュレート用のfor文 // 境界に接していないとき(暗点判定) if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th) { break; } dir++; if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th) { break; } dir++; if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th) { break; } dir++; if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th) { break; } dir++; if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th) { break; } dir++; if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th) { break; } dir++; if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th) { break; } dir++; if (buf[(r + ydir[dir]) * width + (c + xdir[dir])] <= i_th) { break; } // 8方向全て調べたけどラベルが無いよ? throw new NyARException(); } } else { // 境界に接しているとき int i; for (i = 0; i < 8; i++) { final int x = c + xdir[dir]; final int y = r + ydir[dir]; // 境界チェック if (x >= i_l && x <= i_r && y >= i_t && y <= i_b) { if (buf[(y) * width + (x)] <= 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の正規化 int i; for (i = 0; i < 8; i++) { final int x = c + xdir[dir]; final int y = r + ydir[dir]; // 境界チェック if (x >= i_l && x <= i_r && y >= i_t && y <= i_b) { if (buf[(y) * width + (x)] <= 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; }
public boolean 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) throws NyARException { assert (i_t <= i_entry_x); INyARGsPixelDriver reader = this._ref_raster.getGsPixelDriver(); final int[] xdir = _getContour_xdir; // static int xdir[8] = { 0, 1, 1, 1, 0,-1,-1,-1}; final 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++) { final int x = c + xdir[dir]; final 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++) { final int x = c + xdir[dir]; final 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; }