2値化 応用例
[サンプルコード一覧]


マジックワンド風リージョン取得

/*
マジックワンド風のリージョン取得を行うサンプルコードです。
指定した座標の色に近い連続領域をリージョンとして取得します。
*/

#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, &params, &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;
}


Documentation copyright © 2009-2024 FAST Corporation.
Generated on Fri Aug 9 16:38:48 2024 for FIEライブラリ by doxygen 1.5.6-FASTSP-p2