リージョン処理 応用例
[サンプルコード一覧]


" 指定した点を囲む輪郭を元にリージョンを生成"

// エラー処理は省略しているので注意して下さい。
#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, &params, 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;
}



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