/* マジックワンド風のリージョン取得を行うサンプルコードです。 指定した座標の色に近い連続領域をリージョンとして取得します。 */ #include "fie.h" #include "oal_aloc.h" //----------------------------------------------------------------- // 関数プロトタイプ FHANDLE fnSMP_magic_wand( FHANDLE hsrc, PNT_T point, DOUBLE band, INT *exerr ); //----------------------------------------------------------------- // 実装 /* マジックワンド風リージョン取得 入力画像の指定した座標の画素値に近い画素の連続領域を、リージョンとして取得します。 指定座標の画素値を取得し、その画素値と指定したバンド幅に基づいて設定した閾値で二値化 処理を行います。そして得た二値画像に対してブローブ解析を行い、指定座標を含むブローブ をリージョンに変換します。閾値設定と二値化処理の説明は下記を参照してください。 引数: [in] hsrc 入力画像 (type: uc8, s16, us16, double, rgbq) rgbq型の場合、チャネル数1でなければならない [in] point 指定座標(入力画像に含まれる座標でなければならない) [in] band バンド幅(非負の値でなければならない) [out] *exerr エラーコード。エラーコードを受け取る必要のない場合は、NULLを指 定します。エラーコードの内容は以下の通りです。 F_ERR_NONE 正常終了 F_ERR_NO_LICENCE ライセンスエラー、または未初期化エラー F_ERR_INVALID_IMAGE 入力画像が不正 F_ERR_INVALID_PARAM パラメータが不正 F_ERR_NOMEMORY メモリ確保失敗 戻り値: 正常に終了した場合は、リージョンオブジェクトハンドルを返します。何らかのエラーが 発生し、処理が終了した場合はNULLを返します。exerrパラメータにエラーコード受け 取り先変数のポインタが渡された場合には、正常、異常のどちらの場合もそこにエラーコ ードを代入して返します。リージョンが不要になったら、fnFIE_free_object()で解 放してください。 二値化閾値の設定: 座標(x, y)、チャネルchにおける入力画像の画素値をS(x,y,ch)とします。このとき、 二値化閾値の上下限thigh(ch), tlow(ch)をそれぞれ thigh(ch) = S(point.x, point.y, ch) + band tlow(ch) = S(point.x, point.y, ch) - band とします。またrgbq型は1チャネル画像ですが、3チャネルの画像として閾値を設定します。 二値化処理: 入力画像のチャネル数がchsであるとき、二値化画像の座標(x, y)における画素値D(x, y)は tlow(0) <= S(x, y, 0) <= thigh(0) && tlow(1) <= S(x, y, 1) <= thigh(1) : && tlow(chs-1) <= S(x, y, chs-1) <= thigh(chs-1) を満たすときD(x, y)=1、満たさないときD(x, y)=0となります。 */ FHANDLE fnSMP_magic_wand( FHANDLE hsrc, PNT_T point, DOUBLE band, INT *exerr ) { INT ret = F_ERR_UNKNOWN; INT channels, type, width, height; INT ch_cur; UINT blobno; DOUBLE *dens = NULL, *tlow = NULL, *thigh = NULL; PNT_T offset; FHANDLE hbin = NULL; FHANDLE hblob = NULL; FHANDLE hreg = NULL; F_MEASURE_PARAMS params; // ブローブ解析の設定 offset.x = 0; offset.y = 0; params.max_runs = 0; params.max_blobs = 0; params.max_rows = 0; params.color_mode = F_MEASURE_WHITEFG_BLACKBG; params.neighborhood = 4; params.precalc_features = 0; params.keep_results_after_overflow = FALSE; //************************ // パラメータチェック ret = fnFIE_img_get_params( hsrc, &channels, &type, NULL, &width, &height ); if ( ret != F_ERR_NONE ) goto EXIT; // fnFIE_band_threshold_ch()に対応する画像型か ret = F_ERR_INVALID_IMAGE; if ( type != F_IMG_UC8 && type != F_IMG_S16 && type != F_IMG_US16 && type != F_IMG_DOUBLE && type != F_IMG_RGBQUAD ) goto EXIT; // rgbq型はチャネル数1でなければならない if ( type == F_IMG_RGBQUAD && channels != 1 ) goto EXIT; // 指定座標が画像に含まれるか ret = F_ERR_INVALID_PARAM; if ( point.x < 0 || width - 1 < point.x || point.y < 0 || height - 1 < point.y ) goto EXIT; // 閾値の上下限が逆転しないか // なお、閾値が画像型の表現可能な値の範囲を超えたときの処理は、fnFIE_band_threshold_ch()側で行われる if ( band < 0 ) goto EXIT; //************************ // 入力画像がrgbq型のとき、fnFIE_img_get_subdens()および // fnFIE_band_threshold_ch()ではチャネル数3分の配列を要求される if ( type == F_IMG_RGBQUAD ) channels = 3; ret = F_ERR_NOMEMORY; dens = (DOUBLE*)fnOAL_calloc( channels, sizeof( DOUBLE ) ); if ( dens == NULL ) goto EXIT; tlow = (DOUBLE*)fnOAL_calloc( channels, sizeof( DOUBLE ) ); if ( tlow == NULL ) goto EXIT; thigh = (DOUBLE*)fnOAL_calloc( channels, sizeof( DOUBLE ) ); if ( thigh == NULL ) goto EXIT; hbin = fnFIE_img_root_alloc( F_IMG_BIN, 1, width, height ); if ( hbin == NULL ) goto EXIT; // 濃度値は最近傍法で取得 ret = fnFIE_img_get_subdens( hsrc, (DOUBLE)point.x, (DOUBLE)point.y, F_SAMPLING_NN, dens ); if ( ret != F_ERR_NONE ) goto EXIT; // 閾値の設定はチャネルごとに行う for ( ch_cur = 0; ch_cur < channels; ch_cur++ ) { tlow[ch_cur] = dens[ch_cur] - band; thigh[ch_cur] = dens[ch_cur] + band; } // back_clear=TRUE: 閾値の指定範囲外になる画素は0クリア ret = fnFIE_band_threshold_ch( hsrc, hbin, tlow, thigh, TRUE ); if ( ret != F_ERR_NONE ) goto EXIT; hblob = fnFIE_measure_execute( hbin, offset, ¶ms, &ret ); if ( ret != F_ERR_NONE ) goto EXIT; ret = fnFIE_measure_get_blobno_on_xy( hblob, point.x, point.y, &blobno ); if ( ret != F_ERR_NONE ) goto EXIT; hreg = fnFIE_measure_get_region( hblob, blobno, &ret ); if ( ret != F_ERR_NONE ) goto EXIT; ret = F_ERR_NONE; EXIT: fnOAL_free( tlow ); fnOAL_free( thigh ); fnOAL_free( dens ); fnFIE_free_object( hbin ); fnFIE_free_object( hblob ); if ( exerr != NULL ) *exerr = ret; return hreg; } //----------------------------------------------------------------- // 実行サンプル static INT execute() { INT ret = F_ERR_UNKNOWN; DOUBLE band; FHANDLE hsrc = NULL; FHANDLE hreg = NULL; FHANDLE hresult = NULL; PNT_T point; PNT_T offset; // マジックワンド用パラメータ // 指定座標 point.x = 130; point.y = 60; // バンド幅 band = 30; // 画像読込 // 適宜目的の画像に置き換えてください ret = fnFIE_load_bmp( "src.bmp", &hsrc, F_COLOR_IMG_TYPE_UC8 ); if ( ret != F_ERR_NONE ) goto EXIT; // メインサンプル実行 hreg = fnSMP_magic_wand( hsrc, point, band, &ret ); if ( ret != F_ERR_NONE ) goto EXIT; // 取得したリージョンを画像に変換して確認 ret = F_ERR_NOMEMORY; hresult = fnFIE_img_root_alloc( F_IMG_UC8, 1, fnFIE_img_get_width( hsrc ), fnFIE_img_get_height( hsrc ) ); if ( hresult == NULL ) goto EXIT; ret = fnFIE_img_clear( hresult, 0 ); if ( ret != F_ERR_NONE ) goto EXIT; offset.x = 0; offset.y = 0; ret = fnFIE_region_decode( hreg, hresult, offset, 255 ); if ( ret != F_ERR_NONE ) goto EXIT; ret = fnFIE_save_bmp( "region.bmp", hresult ); if ( ret != F_ERR_NONE ) goto EXIT; EXIT: fnFIE_free_object( hsrc ); fnFIE_free_object( hreg ); fnFIE_free_object( hresult ); return ret; } INT main() { INT ret = F_ERR_UNKNOWN; // FIEライブラリの使用前に必ずコールする必要があります。 fnFIE_setup(); ret = execute(); // 終了処理 fnFIE_teardown(); return ret; }