データ構造 | |
struct | F_EDGE_CLUST |
エッジ点クラスタ構造体 [詳細] | |
関数 | |
INT FVALGAPI | fnFIE_edge_connecting (const F_DEDGE *pedges, INT edge_num, DOUBLE weight, DOUBLE threshold1, DOUBLE threshold2, INT area_size, INT area_overlap, INT min_clust_elem, INT mode, F_EDGE_CLUST **ppedge_clust, INT *pclust_num) |
[非推奨]エッジ点の連結 | |
INT FVALGAPI | fnFIE_free_edge_clust (F_EDGE_CLUST *pedge_clust, INT clust_num) |
エッジ点クラスタ配列の解放 | |
INT FVALGAPI | fnFIE_edge_connecting2 (const F_DEDGE *pedges, INT edge_num, DOUBLE angle_range, INT distance_range, INT min_clust_elem, INT max_clust_elem, F_EDGE_CLUST **ppedge_clust, INT *pclust_num) |
エッジ点の連結 | |
INT FVALGAPI | fnFIE_refilter_edge_by_mask (const F_DEDGE *src_edges, INT src_edge_num, FHANDLE hmask, INT mask_mode, F_DEDGE **dst_edges, INT *dst_edge_num) |
マスクによる エッジ点群のフィルタリング | |
INT FVALGAPI | fnFIE_refilter_edge_by_clust (const F_DEDGE *src_edges, INT src_edge_num, const F_EDGE_CLUST *edge_clust, INT edge_clust_num, const INT *clust_idx, INT clust_idx_num, F_DEDGE **dst_edges, INT *dst_edge_num) |
クラスタ情報による エッジ点群のフィルタリング |
INT FVALGAPI fnFIE_edge_connecting | ( | const F_DEDGE * | pedges, | |
INT | edge_num, | |||
DOUBLE | weight, | |||
DOUBLE | threshold1, | |||
DOUBLE | threshold2, | |||
INT | area_size, | |||
INT | area_overlap, | |||
INT | min_clust_elem, | |||
INT | mode, | |||
F_EDGE_CLUST ** | ppedge_clust, | |||
INT * | pclust_num | |||
) |
[非推奨]エッジ点の連結
本関数を応用することで、以下のような処理を構築することができます。 なお以下に示す処理は、一例となります。
ここで、 は点i、j のユークリッド距離、
は点i、j それぞれのエッジ勾配方向のなす角となります。 なお
は、勾配方向のなす角の単位を、入力点群時点のラジアンから度へ変換された後に計算に用いられます。 つまり、 0 <=
<= 180(単位:度)の範囲となります。 また、 weight はエッジ勾配方向の重みとなります。
ここで得られた評価値 と 2つのしきい値 threshold1 、 threshold2 を比較することで、 連結、後述する再連結処理が実行されます。
パラメータ名 | 推奨値 |
---|---|
weight | 0.07 |
threshold1 | 2.0 |
threshold2 | 4.0 |
area_size | 10 |
area_overlap | 3 |
min_clust_elem | 3 |
[in] | pedges | エッジ点の配列(座標、勾配方向(rad)) |
[in] | edge_num | エッジ点の個数( 2 <= edge_num ) |
[in] | weight | エッジ勾配方向の重み weight エッジ勾配方向のなす角の重み)( 0 <= weight <= 1 ) |
[in] | threshold1 | 評価しきい値1:連結用( 0 < threshold1 ) |
[in] | threshold2 | 評価しきい値2:再連結用( threshold1 < threshold2 ) |
[in] | area_size | 正方連結用局所領域のサイズ(画素: 3 <= area_size <= 20 ) |
[in] | area_overlap | 連結用局所領域の重なり(画素: area_overlap <= area_size / 2 ) |
[in] | min_clust_elem | クラスタに属するエッジ点の個数の最小値( 2 <= min_clust_elem ) |
[in] | mode | 再連結処理(0:無効、0以外:有効) |
[out] | *ppedge_clust | 抽出した曲線の情報(クラスタ)の配列(初期値は NULL を指定) |
[out] | pclust_num | 抽出した曲線の個数(初期値は0を指定) |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_PARAM | パラメータ異常 | |
F_ERR_NOMEMORY | メモリ不足 | |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
// エラー処理は省略しているので注意して下さい。 #include "fie.h" #include "oal_aloc.h" VOID edge_connecting() { // 入力画像 FHANDLE himg = NULL; // 出力エッジ画像 FHANDLE hdst = NULL; //入力画像の幅と高さ INT width, height; // 2次元エッジ抽出用 F_DEDGE *pedges = NULL; INT edge_num = 0; F_EDGE_CORR_PARAMS params; DPNT_T offset; // エッジ点群連結用 F_EDGE_CLUST *pclust = NULL; INT clust_num = 0; DOUBLE weight, threshold1, threshold2; INT area_size, area_overlap, min_clust_elem, mode; // 連結して生成された曲線描画用 DOUBLE color[12][3] = { { 0.0, 0.0, 255.0 }, { 0.0, 0.0, 128.0 }, { 0.0, 255.0, 0.0 }, { 255.0, 255.0, 0.0 }, { 255.0, 165.0, 0.0 }, { 255.0, 0.0, 0.0 }, { 255.0, 192.0, 203.0 }, { 176.0, 48.0, 96.0 }, { 0.0, 255.0, 255.0 }, { 160.0, 32.0, 240.0 }, { 255.0, 0.0, 255.0 }, { 0.0, 100.0, 0.0 }, }; INT i, j; // 入力画像の読み込み // 適当な画像を読み込んでください fnFIE_load_png( "sample1.png", &himg, F_COLOR_IMG_TYPE_UC8 ); //入力画像の幅と高さを取得 width = fnFIE_img_get_width( himg ); height = fnFIE_img_get_height( himg ); // 入力画像を3チャネル化した出力画像を確保 hdst = fnFIE_img_root_alloc( F_IMG_UC8, 3, width, height ); fnFIE_img_clear( hdst, 0 ); // 2次元エッジ抽出(相関エッジ)用パラメータの設定 params.width = 5; params.height = 5; params.sigmoid_k = 1.0; params.var_threshold = 25.0; params.mag_threshold = 160; params.nms_length = 6; offset.x = offset.y = 0.0; // 2次元エッジ抽出(相関エッジ) fnFIE_edge_corr_subpix( himg, NULL, ¶ms, F_EDGE_FEAT_DIRECT, F_BORDER_CONTINUOUS, offset, &pedges, &edge_num ); // エッジ点群の連結用パラメータの設定 weight = 0.07; threshold1 = 2.0; threshold2 = 4.0; area_size = 10; area_overlap = 3; min_clust_elem = 3; mode = 1; // エッジ点群の連結 fnFIE_edge_connecting( pedges, edge_num, weight, threshold1, threshold2, area_size, area_overlap, min_clust_elem, mode, &pclust, &clust_num ); // 連結された曲線を色を変えて出力画像上に描画する for( i = 0; i < clust_num; i++ ){ for( j = 0; j < ( pclust[i].num - 1); j++ ){ DPNT_T start, end; start.x = pedges[pclust[i].pindex[j]].x; start.y = pedges[pclust[i].pindex[j]].y; end.x = pedges[pclust[i].pindex[j + 1]].x; end.y = pedges[pclust[i].pindex[j + 1]].y; // 点と点の間は線分で描画する fnFIE_draw_line_seg( hdst, color[i%12], start, end ); } } // メモリの解放 fnFIE_free_edge_clust( pclust, clust_num ); fnOAL_free( pedges ); fnFIE_free_object( himg ); fnFIE_free_object( hdst ); } INT main() { // FIEライブラリの使用前に必ずコールする必要があります。 fnFIE_setup(); edge_connecting(); // 終了処理 fnFIE_teardown(); return 0; }
INT FVALGAPI fnFIE_free_edge_clust | ( | F_EDGE_CLUST * | pedge_clust, | |
INT | clust_num | |||
) |
エッジ点クラスタ配列の解放
エッジ点クラスタ構造体配列を解放します。
[in] | pedge_clust | エッジ点クラスタ配列 |
[in] | clust_num | エッジ点クラスタ配列 要素数 ( clust_num >= 0 ) |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_PARAM | パラメータ以上 | |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
INT FVALGAPI fnFIE_edge_connecting2 | ( | const F_DEDGE * | pedges, | |
INT | edge_num, | |||
DOUBLE | angle_range, | |||
INT | distance_range, | |||
INT | min_clust_elem, | |||
INT | max_clust_elem, | |||
F_EDGE_CLUST ** | ppedge_clust, | |||
INT * | pclust_num | |||
) |
エッジ点の連結
入力されたエッジ点群を連結し、複数の曲線( クラスタ ) を抽出します。
エッジ点の勾配方向に垂直な方向を そのエッジ点の連結方向とし、 各エッジ点が連結方向に向かって連結先となるエッジ点を見つけ連結を行っていくことにより 1 つの曲線を抽出していきます。 勾配方向についての詳細は 総合ドキュメントのエッジ角度 をご参照ください。
この時、連結先となるエッジ点は 注目エッジ点の連結方向とパラメータで指定された 探索角度範囲( angle_range )、 探索距離範囲( distance_range) から 下図 のように規定される探索範囲内で見つけられます。
探索角度範囲と探索距離範囲を調整することにより、結果として得られるクラスタの連結状態を調整することができます。
探索範囲内のエッジ点については、 注目エッジ点と距離が近いものほど、また探索角度範囲の中心に近いものほど連結先として選ばれやすくなります。
従って下図では C のエッジ位置より B のエッジ位置が、また B のエッジ位置より A のエッジ位置が連結先エッジ点として選ばれやすくなります。
パラメータ名 | 推奨値 |
---|---|
angle_range | ![]() |
distance_range | 5 |
min_clust_elem | 3 |
max_clust_elem | -1 |
[in] | pedges | エッジ点の配列 |
[in] | edge_num | エッジ点の個数 ( 2 ≦ edge_num ) |
[in] | angle_range | 探索角度範囲 ( 単位: radian , 0 < angle_range ≦ ![]() |
[in] | distance_range | 探索距離範囲 ( 単位: pixel , 0 < distance_range ) |
[in] | min_clust_elem | クラスタに属するエッジ点個数の最小値 ( 2 ≦ min_clust_elem ) |
[in] | max_clust_elem | クラスタに属するエッジ点個数の最大値 ( min_clust_elem ≦ max_clust_elem ,ただし max_clust_elem < 0 とした場合は無制限 ) |
[out] | ppedge_clust | 抽出した曲線の情報 ( クラスタ ) の配列 ( 初期値は NULL を指定 ) |
[out] | pclust_num | 抽出した曲線の個数 |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_PARAM | パラメータ異常 | |
F_ERR_NOMEMORY | メモリ不足 | |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
INT FVALGAPI fnFIE_refilter_edge_by_mask | ( | const F_DEDGE * | src_edges, | |
INT | src_edge_num, | |||
FHANDLE | hmask, | |||
INT | mask_mode, | |||
F_DEDGE ** | dst_edges, | |||
INT * | dst_edge_num | |||
) |
マスクによる エッジ点群のフィルタリング
入力されたエッジ点群に対して、指定した マスク によるフィルタリングを行い 出力エッジ点群 にコピーし返します。
マスクにはリージョンオブジェクト、または 2値 画像オブジェクトを使用することができます。
リージョンオブジェクトをマスクとして指定した場合、リージョンに含まれる座標を有効座標、リージョンに含まれない座標を 無効座標として扱います。
画像オブジェクトをマスクとして指定した場合、画素値が1の座標を有効座標、画素値が0の座標 及び 画像範囲外の座標を 無効座標として扱います。
マスクモード 0 | マスクモード 1 | ||
---|---|---|---|
リージョン オブジェクト | リージョンに含まれる座標 | × | ○ |
リージョンに含まれない座標 | ○ | × | |
画像 オブジェクト | 画素値1の座標 | × | ○ |
画素値0の座標 及び画像範囲外の座標 | ○ | × |
[in] | src_edges | 入力エッジ点 配列 |
[in] | src_edge_num | 入力エッジ点の個数 ( 1 <= src_edge_num ) |
[in] | hmask | マスク
|
[in] | mask_mode | マスクモード
|
[out] | dst_edges | 出力エッジ点 配列 ( 初期値は NULL を指定 ) |
[out] | dst_edge_num | 出力エッジ点の個数 |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_PARAM | 不正なパラメータが渡された | |
F_ERR_INVALID_OBJECT | 不正なマスクが渡された | |
F_ERR_INVALID_IMAGE | マスクとして渡された画像オブジェクトが不正である | |
F_ERR_NOMEMORY | メモリ不足エラー | |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
#include "oal_aloc.h" #include "fie.h" /* このサンプルコードは入力画像内の特定部分以外をマスクによって削除します。 入力画像のエッジを取得したい特定部分を覆うようなリージョンを作成し、エッジ検出後にそのリージョンの範囲内のエッジ点のみ取得しなおします。 出力結果として、マスクなしエッジ結果画像、マスクありエッジ結果画像を示します。 */ INT fnSMP_edge_filter_by_mask() { INT ret = F_ERR_UNKNOWN; //デフォルトは不明なエラー FHANDLE hin = NULL; //処理対象画像用のハンドル FHANDLE hout = NULL; //出力画像用のハンドル FHANDLE hout2 = NULL; //出力画像用のハンドル FHANDLE hreg = NULL; //リージョン用のハンドル INT width, height; //入力画像サイズ INT channels; //入力画像のチャンネル数 DPNT_T dCenter; //楕円形リージョンの中心のX座標 DOUBLE dLong_r; //楕円形リージョンの長い半径 DOUBLE dShort_r; //楕円形リージョンの短い半径 DOUBLE dTheta; //楕円回転角(ラジアン) F_EDGE_SOBEL_PARAMS params; //エッジ検出用パラメータ UINT feat_mode; //エッジ検出用パラメータ INT e_border_mode; //エッジ検出用パラメータ DPNT_T offset; //エッジ検出用パラメータ F_DEDGE* edges = NULL; //エッジ点配列の作業用ポインタ INT edge_num = 0; //検出されたエッジ点の個数 DPNT_T pnt; //エッジ点描画用座標 DOUBLE val; //塗りつぶし用濃度値 F_DEDGE* dst_edges = NULL; //マスク処理後エッジ用ポインタ INT dst_edge_num = 0; //マスク処理後エッジ数 INT i = 0; //パラメータの設定 //出力画像のファイル名はパラメータで事前に決定できます。 //for fnFIE_load_img_file CHAR input_name[100] = "input.png"; //処理対象入力ファイル名 //for fnFIE_save_png CHAR mask_name[100] = "mask.png"; //マスク画像のファイル名 CHAR output_name[100] = "output1.png"; //マスクなしエッジ画像のファイル名 CHAR output_name2[100] = "output2.png"; //マスク処理後エッジ画像のファイル名 //for fnFIE_create_region_ellipse dCenter.x = 180; //楕円形リージョンの中心のX座標 dCenter.y = 125; //楕円形リージョンの中心のY座標 dLong_r = 60; //楕円形リージョンの長半径 dShort_r = 30; //楕円形リージョンの短半径 dTheta = 0; //楕円回転角(ラジアン) //for fnFIE_edge_sobel_subpix params.mag_threshold = 100; // 強度しきい値 params.nms_length = 1; // 非極大抑制のフィルタ片幅 feat_mode = F_EDGE_FEAT_MAG_SUM; // 勾配方向、強度データ保持の指定 e_border_mode = F_BORDER_NONE; // ボーダー処理 offset.x = offset.y = 0.0; // オフセット量 //for fnFIE_draw_point val = 255.0; //エッジ点の濃度値 // 入力画像の読み込み ret = fnFIE_load_img_file(input_name, &hin, F_COLOR_IMG_TYPE_UC8); if (ret != F_ERR_NONE) goto EXIT; //出力先の確保のため入力画像のサイズ取得 ret = fnFIE_img_get_params(hin, &channels, NULL, NULL, &width, &height); if (ret != F_ERR_NONE) goto EXIT; //入力画像はch数が1のみのものに限定 if (channels != 1) { ret = F_ERR_INVALID_IMAGE; goto EXIT; } //マスク画像のメモリ確保 hmsk = fnFIE_img_root_alloc(F_IMG_UC8, channels, width, height); if (hmsk == NULL) { ret = F_ERR_NOMEMORY; goto EXIT; } ret = fnFIE_img_clear(hmsk, 255);//白く塗りつぶす if (ret != F_ERR_NONE) goto EXIT; //出力画像のメモリ確保 hout = fnFIE_img_root_alloc(F_IMG_UC8, channels, width, height); if (hout == NULL) { ret = F_ERR_NOMEMORY; goto EXIT; } ret = fnFIE_img_clear(hout, 0);//黒く塗りつぶす if (ret != F_ERR_NONE) goto EXIT; hout2 = fnFIE_img_root_alloc(F_IMG_UC8, channels, width, height); if (hout2 == NULL) { ret = F_ERR_NOMEMORY; goto EXIT; } ret = fnFIE_img_clear(hout2, 0);//黒く塗りつぶす if (ret != F_ERR_NONE) goto EXIT; //リージョン生成 hreg = fnFIE_create_region_ellipse(dCenter, dLong_r, dShort_r, dTheta); if (hreg == NULL) { ret = F_ERR_NOMEMORY; goto EXIT; } //入力画像全体にエッジ検出を実行 ret = fnFIE_edge_sobel_subpix(hin, NULL, ¶ms, feat_mode, e_border_mode, offset, &edges, &edge_num); if (ret != F_ERR_NONE) goto EXIT; //エッジ点の描画 for (i = 0; i < edge_num; i++) { pnt.x = edges[i].x; pnt.y = edges[i].y; fnFIE_draw_point(hout, &val, pnt); } //エッジ点をリージョンの範囲内のみに限定 ret = fnFIE_refilter_edge_by_mask(edges, edge_num, hreg, 1, &dst_edges, &dst_edge_num); if (ret != F_ERR_NONE) goto EXIT; //エッジ点の描画 for (i = 0; i < dst_edge_num; i++) { pnt.x = dst_edges[i].x; pnt.y = dst_edges[i].y; fnFIE_draw_point(hout2, &val, pnt); } //結果画像の保存 ret = fnFIE_save_png(output_name, hout, -1); if (ret != F_ERR_NONE) goto EXIT; ret = fnFIE_save_png(output_name2, hout2, -1); if (ret != F_ERR_NONE) goto EXIT; EXIT: //メモリの開放 fnOAL_free(edges); fnOAL_free(dst_edges); fnFIE_free_object(hin); fnFIE_free_object(hreg); fnFIE_free_object(hmsk); fnFIE_free_object(hout); fnFIE_free_object(hout2); return ret; } INT main() { INT ret = F_ERR_UNKNOWN; //デフォルトは不明なエラー // FIEライブラリの使用前に必ずコールする必要がある fnFIE_setup(); ret = fnSMP_edge_filter_by_mask(); // 終了処理 fnFIE_teardown(); return ret; }
![]() (a) | ![]() (b) | ![]() (c) | ![]() (d) |
INT FVALGAPI fnFIE_refilter_edge_by_clust | ( | const F_DEDGE * | src_edges, | |
INT | src_edge_num, | |||
const F_EDGE_CLUST * | edge_clust, | |||
INT | edge_clust_num, | |||
const INT * | clust_idx, | |||
INT | clust_idx_num, | |||
F_DEDGE ** | dst_edges, | |||
INT * | dst_edge_num | |||
) |
クラスタ情報による エッジ点群のフィルタリング
入力されたエッジ点群の中から、指定した エッジ点クラスタ に含まれるもののみを 出力エッジ点群 にコピーし返します。
[in] | src_edges | 入力エッジ点 配列 |
[in] | src_edge_num | 入力エッジ点の個数 ( 1 <= src_edge_num ) |
[in] | edge_clust | エッジ点クラスタ配列 |
[in] | edge_clust_num | エッジ点クラスタ配列 要素数 |
[in] | clust_idx | 処理対象エッジ点クラスタのインデックス配列 ( clust_idx = NULL とした場合は全 クラスタ を処理対象とする ) |
[in] | clust_idx_num | 処理対象エッジ点クラスタのインデックス配列 要素数 |
[out] | dst_edges | 出力エッジ点 配列 ( 初期値は NULL を指定 ) |
[out] | dst_edge_num | 出力エッジ点の個数 |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_PARAM | 不正なパラメータが渡された | |
F_ERR_NOMEMORY | メモリ不足エラー | |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |