// エラー処理は省略しているので注意して下さい。 #include <stdio.h> #include "oal_aloc.h" #include "fie.h" /* 入力画像に映る目立った形状から2値化済みリージョン画像を生成するサンプルコード このサンプルコードは入力画像に映っている目立った物体の輪郭を構成する点群をエッジ検出で獲得したのち 得られた点を繋げてリージョンにして出力します。 また目立った形状をリージョンとしているのでマスクとして活用することができます。 例えば生成後の画像に対して膨張処理を行った場合、他処理を行う際に処理範囲を限定して高速化したり 収縮処理を行うことで輪郭より内側の部分を消したりすることができます。 詳しくはfnFIE_fpm_feature_mask(),fnFIE_refilter_edge_by_mask(),fnFIE_img_meanpixel() などに記載されているサンプルコード等をご確認ください。 */ FHANDLE fnSMP_img_to_region(FHANDLE himg, DPNT_T point) { FHANDLE hreg = NULL; //リージョン用のハンドル F_EDGE_SOBEL_PARAMS params; //エッジ検出用パラメータ UINT feat_mode = F_EDGE_FEAT_DIRECT; //エッジ検出時の勾配方向、強度データ保持の指定に関するパラメータ INT border_mode = F_BORDER_NONE; //エッジ検出時のボーダー処理の種類選択に関するパラメータ DPNT_T offset = { 0,0 } ; //エッジ検出時のオフセット量 F_DEDGE* edges = NULL; //エッジ点配列の作業用ポインタ INT edge_num = 0; //検出されたエッジ点の個数 INT index[1] = { 0 }; //処理対象エッジ点クラスタのインデックス配列 DOUBLE angle_range = 0.8 * PI; //クラスタリング時の探索角度範囲 単位: radian INT distance_range = 2; //クラスタリング時の探索距離範囲 単位: pixel INT min_clust_elem = 2; //クラスタに属するエッジ点個数の最小値 INT max_clust_elem = -1; //クラスタに属するエッジ点個数の最大値 F_EDGE_CLUST* edge_clust = NULL; //抽出した曲線の配列 INT clust_num = 0; //抽出した曲線の個数 F_DEDGE* dst_edges = NULL; //出力エッジ点 配列 INT dst_edge_num = 0; //出力エッジ点の個数 PNT_T* out_point = NULL; //出力座標点列 INT num_dst = 0; //出力座標点列のサイズ DOUBLE threshold = 10; //折れ線閾値 PNT_T* point_cloud1 = NULL; //F_DEDGE to PNT_T変換用配列 DPNT_T* point_cloud2 = NULL; //PNT_T to DPNT_T変換用配列 INT i = 0; INT c_num = 0; INT result; //パラメータの設定 params.mag_threshold = 30; // 強度しきい値 params.nms_length = 1; // 非極大抑制のフィルタ片幅 //ソーベルフィルタを利用した2次元エッジ検出 fnFIE_edge_sobel_subpix(himg, NULL, ¶ms, feat_mode, border_mode, offset, &edges, &edge_num); //エッジ点の連結により物体の輪郭を構成する曲線を作成 fnFIE_edge_connecting2(edges, edge_num, angle_range, distance_range, min_clust_elem, max_clust_elem, &edge_clust, &clust_num); //連結した曲線の数だけ繰り返す for (c_num = 0; c_num < clust_num; c_num++) { //曲線を構成するエッジ点群を抽出して使わないエッジ点を排除 index[0] = c_num; fnFIE_refilter_edge_by_clust(edges, edge_num, edge_clust, clust_num, index, 1, &dst_edges, &dst_edge_num); //出力エッジ点の個数xPNT_Tサイズのメモリを確保 point_cloud1 = fnOAL_malloc(dst_edge_num * (sizeof(PNT_T))); out_point = fnOAL_malloc(dst_edge_num * (sizeof(PNT_T))); //座標の値をDOUBLEからINTに変換するため出力エッジ点群をPNT_T配列にコピー(四捨五入) for (i = 0; i < dst_edge_num; i++) { point_cloud1[i].x = fnFIE_d4i5(dst_edges[i].x); point_cloud1[i].y = fnFIE_d4i5(dst_edges[i].y); } //点列の折れ線化で更に余計なエッジ点を取り除く。輪郭の頂点になる点を取得。 fnFIE_cg_vectorize2d_dp(point_cloud1, dst_edge_num, out_point, NULL, &num_dst, threshold); //出力座標点列の個数xDPNT_Tサイズのメモリを確保 point_cloud2 = fnOAL_malloc(num_dst * (sizeof(DPNT_T))); //座標の値をINTからDOUBLEに変換するため出力座標点列をDPNT_T配列にコピー for (i = 0; i < num_dst; i++) { point_cloud2[i].x = (DOUBLE)out_point[i].x; point_cloud2[i].y = (DOUBLE)out_point[i].y; } //多角形リージョンを作成 hreg = fnFIE_create_region_polygon(point_cloud2, num_dst); //リージョンに指定座標が含まれているかを判別 fnFIE_region_includes_xy(hreg, point.x, point.y, &result); //メモリの開放 fnOAL_free(dst_edges); dst_edges = NULL; fnOAL_free(point_cloud1); point_cloud1 = NULL; fnOAL_free(out_point); out_point = NULL; fnOAL_free(point_cloud2); point_cloud2 = NULL; if (result == 0) { fnFIE_free_object(hreg); hreg = NULL; }//指定座標がリージョン外の場合 else break; // 指定座標がリージョン内の場合 } //メモリの開放 fnOAL_free(dst_edges); fnOAL_free(point_cloud1); fnOAL_free(out_point); fnOAL_free(point_cloud2); fnOAL_free(edges); fnFIE_free_edge_clust(edge_clust, clust_num); return hreg; } INT main() { FHANDLE himg = NULL; //入力画像用のハンドル FHANDLE hreg = NULL; //リージョン画像用のハンドル FHANDLE hresult = NULL; //結果画像用のハンドル DPNT_T point = { 155.0,253.0 }; //取得したいリージョンが含む座標 PNT_T offset = { 0,0 }; //リージョン描画用原点 INT width, height; //入力画像サイズ fnFIE_setup(); //画像読み込み fnFIE_load_bmp("gray_05.bmp", &himg, F_COLOR_IMG_TYPE_UC8); //入力画像のサイズ取得 fnFIE_img_get_params(himg, NULL, NULL, NULL, &width, &height); //出力結果画像のメモリ確保及び白での塗りつぶし hresult = fnFIE_img_root_alloc(F_IMG_BIN, 1, width, height); fnFIE_img_clear(hresult, 1); //リージョン取得 hreg = fnSMP_img_to_region(himg, point); //リージョンを黒で書き込み fnFIE_region_decode(hreg, hresult, offset, 0); //結果を保存 fnFIE_save_bmp("result.bmp", hresult); //メモリの開放 fnFIE_free_object(himg); fnFIE_free_object(hreg); fnFIE_free_object(hresult); fnFIE_teardown(); return 0; }