低レベル関数
[1次元エッジ検出]


説明

本ライブラリは、基礎となる処理をする低レベル関数と、低レベル関数を組み合わせた応用関数から構成されています。 ユーザーは、必要に応じて低レベル関数を組み合わせることで、 提供した応用関数以外の1次元エッジ検出関数を作成することができます。 以下に、低レベル関数により線分と円弧それぞれのエッジ検出を実現した例を示します。

// エラー処理は省略しているので注意してください。
#include "oal_aloc.h"
#include "fie.h"

// 低レベル関数による計測ライン(線分)上からの複数エッジ点の検出 
VOID edge1d_line()
{
    FHANDLE         himg = NULL;    // 入力画像用のハンドル
    DSGMT_T         line;           // 計測ライン(直線)設定用
    INT             length;         // 計測ラインの長さ
    DOUBLE          *pprj = NULL;   // 濃度プロファイル
    F_ARRAY_INDEX   valid_reg;      // 濃度プロファイルの有効領域の情報
    F_DEDGE         *edges = NULL;  // エッジ点配列の作業用ポインタ
    INT             edge_num;       // 検出されたエッジ点の個数

    // 入力画像の読み込み
    fnFIE_load_png( "fie_edge1d_line.png", &himg, F_COLOR_IMG_TYPE_UC8 );

    // 計測ラインを設定する
    line.st.x = 100.0;
    line.st.y = 100.0;
    line.ed.x = 400.0;
    line.ed.y = 400.0;

    // 計測ラインの長さを求める
    fnFIE_edge1d_calc_projection_line_length( line, &length );

    // 濃度プロファイル配列のメモリ確保
    pprj = (DOUBLE*)fnOAL_malloc( length * sizeof(DOUBLE) );

    // 計測ライン(線分)上の濃度投影による濃度プロファイルの作成
    fnFIE_edge1d_projection_line( himg, line, 1, pprj, length, &valid_reg );

    // エッジ保存配列のメモリ確保
    edges = (F_DEDGE*)fnOAL_malloc( valid_reg.size * sizeof( F_DEDGE ) );

    // 相関エッジフィルタによるエッジ検出
    // 始点からのオフセット量を考慮する必要がある
    // 検出するエッジの方向   :両極性
    // 濃度差しきい値        :相対しきい値
    // エッジの保存順        :強度順
    fnFIE_edge1d_detect_edges_corr( ( pprj + valid_reg.index ), valid_reg.size,
                                    F_DTC_BOTH, F_RELATIVE_THR, 50, F_MAG_SORT,
                                    edges, valid_reg.size, &edge_num );

    // エッジ座標変換
    // 入力画像での座標系に戻す
    fnFIE_edge1d_trans_coord_line( edges, edge_num, line, valid_reg.index );

    fnOAL_free( pprj );
    fnOAL_free( edges );

    fnFIE_free_object( himg );

    return;
}

// 低レベル関数による計測ライン(円弧)上からの複数エッジ点の検出 
VOID edge1d_arc()
{
    FHANDLE         himg = NULL;    // 入力画像用のハンドル
    F_ARC           arc;            // 計測ライン(円弧)設定用
    INT             length;         // 計測ラインの長さ
    DOUBLE          *pprj = NULL;   // 濃度プロファイル
    F_ARRAY_INDEX   *valid_reg;     // 濃度プロファイルの有効領域の情報(計測ラインの形状が直線とは異なり複数となる)
    INT             vreg_num;       // 有効領域情報のサイズ
    F_DEDGE         *edges = NULL;  // エッジ点配列の作業用ポインタ
    INT             edge_num;       // 検出されたエッジ点の個数
    INT             max_edge_num;   // 検出される可能性のあるエッジ点の最大値個数
    INT             i;

    // 入力画像の読み込み
    fnFIE_load_png( "fie_edge1d_arc.png", &himg, F_COLOR_IMG_TYPE_UC8 );

    // 計測ラインを設定する
    arc.x           = 287.0;
    arc.y           = 480.0;
    arc.radius      = 270.0;
    arc.start_angle = 0.0;
    arc.sweep_angle = 2.0 * PI;

    // 計測ラインの長さを求める
    fnFIE_edge1d_calc_projection_arc_length( arc, &length );

    // 濃度プロファイル配列のメモリ確保
    pprj = (DOUBLE*)fnOAL_malloc( length * sizeof(DOUBLE) );

    // 濃度プロファイルの有効領域情報用構造体のメモリ確保
    // 有効領域は最大で、濃度プロファイルの長さの半分の個数だけ生成される可能性がある
    valid_reg = (F_ARRAY_INDEX*)fnOAL_malloc( (length / 2 + 1) * sizeof(F_ARRAY_INDEX) );

    // 計測ライン(線分)上の濃度投影による濃度プロファイルの作成
    fnFIE_edge1d_projection_arc( himg, arc, 1, pprj, length, valid_reg, (length / 2 + 1), &vreg_num );

    // 有効領域の長さを求める
    max_edge_num = 0;
    for( i = 0; i < vreg_num; i++ )
        max_edge_num += valid_reg[i].size;

    // エッジ保存配列のメモリ確保
    edges = (F_DEDGE*)fnOAL_malloc( max_edge_num * sizeof( F_DEDGE ) );

    // エッジ検出
    edge_num = 0;
    for( i = 0; i < vreg_num; i++ ){
        INT edge_num_wk = 0;
    
        // DoGフィルタによりエッジ検出
        // 始点からのオフセット量を考慮する必要がある
        // 検出するエッジの方向   :暗→明のエッジ 
        // 濃度差しきい値        :絶対濃度差 
        // エッジの保存順        :始点からの位置順 
        fnFIE_edge1d_detect_edges_DoG( ( pprj + valid_reg[i].index ), valid_reg[i].size, 
                                       F_DRK_TO_BRI, F_ABSOLUTE_THR, 100, F_POS_SORT,
                                       ( edges + edge_num ), ( max_edge_num - edge_num ), &edge_num_wk );

        // エッジ座標変換
        // 入力画像での座標系に戻す
        // 始点からのオフセット量を考慮する必要がある
        fnFIE_edge1d_trans_coord_arc( (edges + edge_num), edge_num_wk, arc, valid_reg[i].index );

        edge_num += edge_num_wk;
    }

    fnOAL_free( pprj );
    fnOAL_free( edges );
    fnOAL_free( valid_reg );

    fnFIE_free_object( himg );

    return;
}


INT main()
{
    // FIEライブラリの使用前に必ずコールする必要があります。
    fnFIE_setup();

    edge1d_line();
    edge1d_arc();

    // 終了処理
    fnFIE_teardown();

    return 0;
}


関数

INT FVALGAPI fnFIE_edge1d_calc_projection_line_length (DSGMT_T line, INT *length)
 計測ライン(線分)の長さを計算
INT FVALGAPI fnFIE_edge1d_calc_projection_arc_length (F_ARC arc, INT *length)
 計測ライン(円弧)の長さを計算
INT FVALGAPI fnFIE_edge1d_projection_line (FHANDLE hsrc, DSGMT_T line, INT prj_width, DOUBLE *pprj, INT prj_len, F_ARRAY_INDEX *valid_reg)
 計測ライン(線分)上の濃度投影の作成
INT FVALGAPI fnFIE_edge1d_projection_arc (FHANDLE hsrc, F_ARC arc, INT prj_width, DOUBLE *pprj, INT prj_len, F_ARRAY_INDEX *valid_reg, INT vreg_len, INT *prj_num)
 計測ライン(円弧)上の濃度投影による濃度プロファイルの作成
INT FVALGAPI fnFIE_edge1d_detect_edges_DoG (const DOUBLE *pprj, INT prj_len, enum f_edge1d_edge_direction direct_mode, enum f_diff_type diff_type, DOUBLE diff_thr, enum f_edge1d_sort_mode sort_mode, F_DEDGE *edges, INT edge_len, INT *edge_num)
 DoGフィルタによるエッジ検出
INT FVALGAPI fnFIE_edge1d_detect_edges_corr (const DOUBLE *pprj, INT prj_len, enum f_edge1d_edge_direction direct_mode, enum f_diff_type diff_type, DOUBLE diff_thr, enum f_edge1d_sort_mode sort_mode, F_DEDGE *edges, INT edge_len, INT *edge_num)
 相関エッジフィルタによるエッジ検出
INT FVALGAPI fnFIE_edge1d_detect_edges_diff (const DOUBLE *pprj, INT prj_len, F_EDGE1D_DIFF_FILTER diff_filter, INT arnd, INT interval, enum f_edge1d_edge_direction direct_mode, enum f_diff_type diff_type, DOUBLE diff_thr, enum f_edge1d_sort_mode sort_mode, F_DEDGE *edges, INT edge_len, INT *edge_num, INT *diff, INT diff_len)
 1次微分によるエッジ検出
INT FVALGAPI fnFIE_edge1d_trans_coord_line (F_DEDGE *edges, INT edge_num, DSGMT_T line, INT offset)
 計測ライン(線分)上への座標変換
INT FVALGAPI fnFIE_edge1d_trans_coord_arc (F_DEDGE *edges, INT edge_num, F_ARC arc, INT offset)
 計測ライン(円弧)上への座標変換

関数

INT FVALGAPI fnFIE_edge1d_calc_projection_line_length ( DSGMT_T  line,
INT *  length 
)

計測ライン(線分)の長さを計算

line にて指定された直線形状の計測ライン上の濃度プロファイルを生成するために必要な長さを求めます。

本関数で取得される濃度プロファイルの長さは、濃度プロファイル内の有効領域の長さではありません。 line で指定した始点から終点までの長さとなります。

なお、濃度プロファイルの長さは以下の式で求められます。

$ length = \left(INT\right)\sqrt{\left(lind.ed.x - line.st.x\right)^2 + \left(lind.ed.y - line.st.y\right)^2} + 1 $

引数:
[in] line 計測ライン(線分)
  • st 始点
  • ed 終点
[out] length 濃度プロファイルの長さ
戻り値:
F_ERR_NONE 正常終了
F_ERR_INVALID_PARAM 不正なパラメータが渡された
  • length が NULL
F_ERR_NO_LICENCE ライセンスエラー、または未初期化エラー

INT FVALGAPI fnFIE_edge1d_calc_projection_arc_length ( F_ARC  arc,
INT *  length 
)

計測ライン(円弧)の長さを計算

arc にて指定された円弧形状の計測ライン上の濃度プロファイルを生成するために必要な長さを求めます。

本関数で取得される濃度プロファイルの長さは、濃度プロファイル内の有効領域の長さではありません。 arc で指定した円弧の長さとなります。

なお、濃度プロファイルの長さは以下の式で求めることができます。

$ length = \left(INT\right) \left( | arc.sweep\_angle | \times arc.radius \right) + 1 $

引数:
[in] arc 計測ライン(円弧)
  • x 中心x座標
  • y 中心y座標
  • radius 半径:0 < radius
  • start_angle 開始角:[0, $2\pi$]
  • sweep_angle 円弧の角度
    • 時計回り 正
    • 反時計回り 負
[out] length 濃度プロファイルの長さ
戻り値:
F_ERR_NONE 正常終了
F_ERR_INVALID_PARAM 不正なパラメータが渡された
  • length が NULL
  • arc が不正な値
F_ERR_NO_LICENCE ライセンスエラー、または未初期化エラー

INT FVALGAPI fnFIE_edge1d_projection_line ( FHANDLE  hsrc,
DSGMT_T  line,
INT  prj_width,
DOUBLE *  pprj,
INT  prj_len,
F_ARRAY_INDEX valid_reg 
)

計測ライン(線分)上の濃度投影の作成

指定した計測ライン(線分)に垂直方向に濃度投影を実行して得られた濃度プロファイルを作成します。

fie_edge1d_projection_line.png

濃度プロファイルは、計測ラインが完全に入力画像からはみ出していない限り生成されます( 濃度プロファイル )。 つまり、計測ラインの一部が入力画像に含まれている場合に生成されます。 ただし、計測ライン部分が入力画像に含まれておらず、対応する片幅領域のみが入力画像に含まれている場合は、有効領域には含まれません。 あくまで、計測ラインが基準として有効領域が設定されます。 有効領域が存在しない場合、つまり指定された line 全体が入力画像に含まれていない場合は F_ERR_INVALID_PARAM が返されます。

計測ラインが直線の場合、濃度プロファイル内の有効領域は1つとなります。 有効領域の位置は、 valid_reg として濃度プロファイルの先頭からのオフセット量と長さが取得されます。

濃度プロファイルを保存するための配列( pprj )は、本関数内部でメモリ確保しません。 fnFIE_edge1d_calc_projection_line_length() で求められる計測ラインの長さ以上のサイズの メモリを確保した配列を用意してください。 prj_lenfnFIE_edge1d_calc_projection_line_length() で取得される長さ未満の場合は、 F_ERR_INVALID_PARAM が返されます。

引数:
[in] hsrc 入力画像(type:uc8,s16,us16,double / ch:1)
[in] line 計測ライン(線分)
  • st 始点
  • ed 終点
[in] prj_width 濃度投影片幅(0以上、単位:画素)
[out] pprj 濃度プロファイル配列
[in] prj_len 濃度プロファイル配列の長さ
[out] valid_reg 濃度プロファイルの有効領域
  • index 要素番号:濃度プロファイル配列の原点からのオフセット量
  • size 長さ :有効領域の長さ
戻り値:
F_ERR_NONE 正常終了
F_ERR_INVALID_IMAGE 不正な画像が渡された
F_ERR_INVALID_PARAM 不正なパラメータが渡された
F_ERR_NO_LICENCE ライセンスエラー、または未初期化エラー

INT FVALGAPI fnFIE_edge1d_projection_arc ( FHANDLE  hsrc,
F_ARC  arc,
INT  prj_width,
DOUBLE *  pprj,
INT  prj_len,
F_ARRAY_INDEX valid_reg,
INT  vreg_len,
INT *  prj_num 
)

計測ライン(円弧)上の濃度投影による濃度プロファイルの作成

指定した計測ライン(円弧)に垂直方向に濃度投影を実行して得られた濃度プロファイルを作成します。

fie_edge1d_projection_arc.png

濃度プロファイルは、計測ラインが完全に入力画像からはみ出していない限り生成されます( 濃度プロファイル )。 つまり、計測ラインの一部が入力画像に含まれている場合に生成されます。 ただし、計測ライン部分が入力画像に含まれておらず、対応する片幅領域のみが入力画像に含まれている場合は、有効領域には含まれません。 あくまで、計測ラインが基準として有効領域が設定されます。 有効領域が存在しない場合、つまり指定された arc 全体が入力画像に含まれていない場合は F_ERR_INVALID_PARAM が返されます。

計測ラインの形状が円弧では、複数の有効領域が濃度プロファイル内に設定される可能性があります。 有効領域は最大で、「濃度プロファイルの長さ÷2」となります。 なお、濃度プロファイルの長さは、 fnFIE_edge1d_calc_projection_arc_length() により取得可能です。 有効領域の位置は、 valid_reg として濃度プロファイルの先頭からのオフセット量と長さの配列、そして prj_num として有効領域個数が取得されます。
なお、 valid_reg は本関数内部でメモリ確保しません。 メモリを確保した配列を用意してください。 vreg_len( ( INT )( fnFIE_edge1d_calc_projection_arc_length() / 2 ) + 1 ) 未満の場合は、 F_ERR_INVALID_PARAM が返されます。

また、濃度プロファイルを保存するための配列( pprj )も、本関数内部でメモリ確保しません。 fnFIE_edge1d_calc_projection_arc_length() で求められる計測ラインの長さ以上のサイズの メモリを確保した配列を用意してください。 prj_lenfnFIE_edge1d_calc_projection_arc_length() で取得される長さ未満の場合は、 F_ERR_INVALID_PARAM が返されます。

引数:
[in] hsrc 入力画像(type:uc8,s16,us16,double / ch:1)
[in] arc 計測ライン(円弧)
  • x 中心x座標
  • y 中心y座標
  • radius 半径:0 < radius
  • start_angle 開始角:[0, $2\pi$]
  • sweep_angle 円弧の角度
    • 時計回り 正
    • 反時計回り 負
[in] prj_width 濃度投影片幅(0以上、単位:画素)
[out] pprj 濃度プロファイル配列
[in] prj_len 濃度プロファイル配列の長さ
[out] valid_reg 濃度プロファイルの有効領域配列
  • index 要素番号:濃度プロファイル配列の原点からのオフセット量
  • size 長さ :有効領域の長さ
[in] vreg_len 濃度プロファイルの有効領域配列の長さ
[out] prj_num 濃度プロファイル配列の有効領域個数
戻り値:
F_ERR_NONE 正常終了
F_ERR_INVALID_IMAGE 不正な画像が渡された
F_ERR_INVALID_PARAM 不正なパラメータが渡された
F_ERR_NO_LICENCE ライセンスエラー、または未初期化エラー

INT FVALGAPI fnFIE_edge1d_detect_edges_DoG ( const DOUBLE *  pprj,
INT  prj_len,
enum f_edge1d_edge_direction  direct_mode,
enum f_diff_type  diff_type,
DOUBLE  diff_thr,
enum f_edge1d_sort_mode  sort_mode,
F_DEDGE edges,
INT  edge_len,
INT *  edge_num 
)

DoGフィルタによるエッジ検出

入力濃度プロファイルに微分方式であるDoGフィルタにより強度計算を行い、サブピクセル精度でエッジを検出します。

本関数で取得されるエッジ点( edges )は、濃度プロファイル上の座標となります。 そのため、すべてのエッジ点のy座標は 0 で保存されます。 入力画像での座標に変換するには、計測ラインの形状により、 fnFIE_edge1d_trans_coord_line()fnFIE_edge1d_trans_coord_arc() にて座標変換をしてください。

また本関数は、 エッジ検出アルゴリズムの違いにより、 fnFIE_edge1d_detect_edges_diff() のように1次微分データは取得できません。

濃度プロファイル配列( pprj )の長さ( prj_len )は、 DoGフィルタの長さにより最少値が決定します。 DoGフィルタの最小長さは5であり、その周辺の2個分の座標を参照することから、 prj_len の最小長さは9となります。 prj_len が9未満だった場合は、 F_ERR_NODATA が返されます。

検出されたエッジ点を保存するための配列( edges )は、本関数内部でメモリ確保しません。 メモリを確保した配列を用意してください。 edges は、 prj_len 以上のメモリを確保してください。 edge_lenprj_len 未満だった場合は F_ERR_INVALID_PARAM が返されます。

濃度プロファイルからのエッジ位置探索法
本関数のエッジ検出は、エッジ部を取得後、サブピクセル位置の計算がなされます。 エッジ部とは、濃度プロファイルにおいて隣り合う極大点と極小点の濃度差が、指定値以上の箇所を指します。

エッジ点は、このエッジ部内に"ひとつ"であると考えます。 しかし、例外的にひとつのエッジ部に、エッジ強度極大点が複数存在することがあります。 その場合は、濃度差の50%点(エッジ部の最小濃度 + 0.5 × エッジ部濃度差)となる位置を頂点位置とします。

濃度プロファイル内で、濃度が単調に増加または減少する部分をエッジ部として検出します。 しかし、単調の変化の中に、緩やかな変化が発生する場合は、これを分割します。

本関数では、濃度プロファイル内の隣り合う要素の濃度差が1以下の場合は、その部分を平坦であると判定します。 そのため、濃度差が1以下の部分のエッジ点は検出されません。 ただし濃度プロファイルは、微小な濃度変化を吸収するために、 fnFIE_d4i5() にて四捨五入をした後に上記処理を行います。

fie_edge1d_edge1.png

エッジ部

fie_edge1d_edge2.png

エッジ部の分割

サブピクセル位置の計算
エッジのピーク点は、エッジ強度最大点とその前後2点の計3点に関数をあてはめ、その頂点位置として求めます。 あてはめる関数は、正規分布関数です。

引数:
[in] pprj 濃度プロファイル配列
[in] prj_len 濃度プロファイル配列の長さ
  • prj_len >= 9
[in] direct_mode 検出するエッジ方向の指定
  • F_DRK_TO_BRI 暗→明のエッジ
  • F_BRI_TO_DRK 明→暗のエッジ
  • F_DTC_BOTH 両極性
[in] diff_type 濃度差しきい値の種別
  • F_ABSOLUTE_THR 絶対濃度差
  • F_RELATIVE_THR 相対濃度差
[in] diff_thr エッジの最小濃度差しきい値
  • F_ABSOLUTE_THR を指定した場合:[0, 2147483647]
  • F_RELATIVE_THR を指定した場合:[0,100](%)
    • 生成された濃度プロファイル内の最大値と最小値の差に対する割合
    • 求められたしきい値は、 fnFIE_d4i5() にて四捨五入される
[in] sort_mode 検出されたエッジの保存順を指定
  • F_MAG_SORT 強度順
  • F_POS_SORT 始点からの位置順
[out] edges 検出されたエッジ点保存配列
  • x x座標
  • y y座標(必ず0となる)
  • q 勾配方向
    • 暗→明のエッジ 1
    • 明→暗のエッジ -1
  • mag 強度(0以上)
[in] edge_len エッジ点配列の長さ
  • edge_len >= prj_len
[out] edge_num 検出されたエッジ点個数
戻り値:
F_ERR_NONE 正常終了
F_ERR_NOMEMORY メモリ不足
F_ERR_INVALID_PARAM 不正なパラメータが渡された
  • pprj , edges または edge_num が NULL
  • direct_mode , diff_type, diff_thr または sort_mode が不正な値
  • prj_len > edge_len
F_ERR_NODATA 濃度プロファイルに有効領域が存在しない
F_ERR_NO_LICENCE ライセンスエラー、または未初期化エラー

INT FVALGAPI fnFIE_edge1d_detect_edges_corr ( const DOUBLE *  pprj,
INT  prj_len,
enum f_edge1d_edge_direction  direct_mode,
enum f_diff_type  diff_type,
DOUBLE  diff_thr,
enum f_edge1d_sort_mode  sort_mode,
F_DEDGE edges,
INT  edge_len,
INT *  edge_num 
)

相関エッジフィルタによるエッジ検出

入力濃度プロファイルにテンプレート方式である相関エッジフィルタにより強度計算を行い、サブピクセル精度でエッジを検出します。

本関数で取得されるエッジ点( edges )は、濃度プロファイル上の座標となります。 そのため、すべてのエッジ点のy座標は 0 で保存されます。 入力画像での座標に変換するには、計測ラインの形状により、 fnFIE_edge1d_trans_coord_line()fnFIE_edge1d_trans_coord_arc() にて座標変換をしてください。

また本関数は、 エッジ検出アルゴリズムの違いにより、 fnFIE_edge1d_detect_edges_diff() のように1次微分データは取得できません。

濃度プロファイル配列( pprj )の長さ( prj_len )は、 相関エッジフィルタの長さにより最少値が決定します。 相関エッジフィルタの最小長さは5であり、その周辺の2個分の座標を参照することから、 prj_len の最小長さは9となります。 prj_len が9未満だった場合は、 F_ERR_NODATA が返されます。

検出されたエッジ点を保存するための配列( edges )は、本関数内部でメモリ確保しません。 メモリを確保した配列を用意してください。 edges は、 prj_len 以上のメモリを確保してください。 edge_lenprj_len 未満だった場合は F_ERR_INVALID_PARAM が返されます。

濃度プロファイルからのエッジ位置探索法
本関数のエッジ検出は、エッジ部を取得後、サブピクセル位置の計算がなされます。 エッジ部とは、濃度プロファイルにおいて隣り合う極大点と極小点の濃度差が、指定値以上の箇所を指します。

エッジ点は、このエッジ部内に"ひとつ"であると考えます。 しかし、例外的にひとつのエッジ部に、エッジ強度極大点が複数存在することがあります。 その場合は、濃度差の50%点(エッジ部の最小濃度 + 0.5 × エッジ部濃度差)となる位置を頂点位置とします。

濃度プロファイル内で、濃度が単調に増加または減少する部分をエッジ部として検出します。 しかし、単調の変化の中に、緩やかな変化が発生する場合は、これを分割します。

本関数では、濃度プロファイル内の隣り合う要素の濃度差が1以下の場合は、その部分を平坦であると判定します。 そのため、濃度差が1以下の部分のエッジ点は検出されません。 ただし濃度プロファイルは、微小な濃度変化を吸収するために、 fnFIE_d4i5() にて四捨五入をした後に上記処理を行います。

fie_edge1d_edge1.png

エッジ部

fie_edge1d_edge2.png

エッジ部の分割

サブピクセル位置の計算
エッジのピーク点は、エッジ強度最大点とその前後2点の計3点に関数をあてはめ、その頂点位置として求めます。 あてはめる関数は、正規分布関数です。

引数:
[in] pprj 濃度プロファイル配列
[in] prj_len 濃度プロファイル配列の長さ
  • prj_len >= 9
[in] direct_mode 検出するエッジ方向の指定
  • F_DRK_TO_BRI 暗→明のエッジ
  • F_BRI_TO_DRK 明→暗のエッジ
  • F_DTC_BOTH 両極性
[in] diff_type 濃度差しきい値の種別
  • F_ABSOLUTE_THR 絶対濃度差
  • F_RELATIVE_THR 相対濃度差
[in] diff_thr エッジの最小濃度差しきい値
  • F_ABSOLUTE_THR を指定した場合:[0, 2147483647]
  • F_RELATIVE_THR を指定した場合:[0,100](%)
    • 生成された濃度プロファイル内の最大値と最小値の差に対する割合
    • 求められたしきい値は、 fnFIE_d4i5() にて四捨五入される
[in] sort_mode 検出されたエッジの保存順を指定
  • F_MAG_SORT 強度順
  • F_POS_SORT 始点からの位置順
[out] edges 検出されたエッジ点保存配列
  • x x座標
  • y y座標(必ず0となる)
  • q 勾配方向
    • 暗→明のエッジ 1
    • 明→暗のエッジ -1
  • mag 強度(0以上)
[in] edge_len エッジ点配列の長さ
  • edge_len >= prj_len
[out] edge_num 検出されたエッジ点個数
戻り値:
F_ERR_NONE 正常終了
F_ERR_NOMEMORY メモリ不足
F_ERR_INVALID_PARAM 不正なパラメータが渡された
  • pprj , edges または edge_num が NULL
  • direct_mode , diff_type, diff_thr または sort_mode が不正な値
  • prj_len > edge_len
F_ERR_NODATA 濃度プロファイルに有効領域が存在しない
F_ERR_NO_LICENCE ライセンスエラー、または未初期化エラー

INT FVALGAPI fnFIE_edge1d_detect_edges_diff ( const DOUBLE *  pprj,
INT  prj_len,
F_EDGE1D_DIFF_FILTER  diff_filter,
INT  arnd,
INT  interval,
enum f_edge1d_edge_direction  direct_mode,
enum f_diff_type  diff_type,
DOUBLE  diff_thr,
enum f_edge1d_sort_mode  sort_mode,
F_DEDGE edges,
INT  edge_len,
INT *  edge_num,
INT *  diff,
INT  diff_len 
)

1次微分によるエッジ検出

入力濃度プロファイルに1次微分フィルタにより強度計算を行い、サブピクセル精度でエッジを検出します。

本関数で取得されるエッジ点( edges )は、濃度プロファイル上の座標となります。 そのため、すべてのエッジ点のy座標は 0 で保存されます。 入力画像での座標に変換するには、計測ラインの形状により、 fnFIE_edge1d_trans_coord_line()fnFIE_edge1d_trans_coord_arc() にて座標変換をしてください。

濃度プロファイル配列( pprj )の長さ( prj_len )の最小値は、 微分フィルタとサブピクセル計算に使用する周辺情報の片幅により以下の通りに決定されます。

prj_len の最小値 = ( arnd + diff_filter.minus_foot + diff_filter.minus_len + diff_filter.plus_len + diff_filter.plus_foot + arnd );

prj_len が上記の値未満の場合は、 F_ERR_NODATA が返されます。

検出されたエッジ点を保存するための配列( edges )は、本関数内部でメモリ確保しません。 メモリを確保した配列を用意してください。 edge_len が、 prj_len 未満の場合は、 F_ERR_INVALID_PARAM が返されます。

微分値作成法
本関数では、濃度プロファイルを取得後、 diff_filter にて設定されるパラメータに従って、微分データを生成します。 生成される微分データは、 fnFIE_d4i5() にて四捨五入された後に、 diff に保持され、以後の処理に利用されます。 なお、 diff が NULL で指定された場合は、関数内部でメモリを確保され、以後の処理に利用されます。
fie_edge1d_diff.png

上図のように、注目画素(x)の位置に対して len で指定される領域を無視して、 foot で指定される領域の平均値より、プラス側とマイナス側で差分を求めます。 plus_footminus_foot の値が違っていても、それぞれで平均値での差分を求めるため、 問題ありません。

微分値からのエッジ位置探索法
  1. しきい値以上の1次微分データの位置を1次微分値が大きい順にソートしながら検出する
  2. 1で作成したデータを基に、1次微分値が最大の画素と、その周辺画素の1次微分値からエッジのサブピクセル位置を求める
  3. 2で求められた1次微分値が最大の画素と、その画素とエッジ方向が等しく前後 interval 画素以内にある画素をデータから除去する
  4. 2、3のプロセスをしきい値以上のデータがなくなるまで繰り返す
サブピクセル位置の計算
微分最大値の位置と、前後 arnd 個の値から、重み付き平均により求めます。
	位置  : 0  1  2  3  4  5  6  7
	微分値: 0 10 10 30 20 15  0  0
	
上記のデータの場合で、3が最大位置として登録されていて arnd = 2 の場合、 サブピクセル位置の計算は3の位置に前後2個を加えた、1〜5のデータが対象になります。 重み付き平均は、微分値をd、位置をxとすると、(Σd*x)/(Σd)で計算されます。 この場合、
( 1*10 + 2*10 + 3*30 + 4*20 + 5*15 ) / ( 10+10+30+20+15 ) ≒ 3.24
となります。
エッジ取得間隔
エッジ方向が等しい場合、エッジ計測に利用された1次微分データ上で取得される隣り合うエッジ間の距離は少なくとも interval 以上となります。 interval が0であれば、連続した座標で同じ方向のエッジが取得されることがあります。 interval が1以上であれば、連続した座標で同じ方向のエッジが取得されることはありません。 いずれの場合においても、方向が異なるエッジは連続した座標で取得されることがあります。
引数:
[in] pprj 濃度プロファイル配列
[in] prj_len 濃度プロファイル配列の長さ
  • prj_lne >= ( arnd + diff_filter.minus_foot + diff_filter.minus_len + diff_filter.plus_len + diff_filter.plus_foot + arnd )
[in] diff_filter 微分フィルタの指定
  • minus_foot 負側のfoot長さ(1以上)
  • minus_len 負側のlen長さ(0以上)
  • plus_foot 正側のfoot長さ(1以上)
  • plus_len 正側のlen長さ(0以上)
[in] arnd サブピクセル計算に使用する周辺情報の片幅(0以上)
検出した濃度微分データのピーク位置(または、または最初にしきい値を超えた位置)に対して、 ここで指定した画素分の両端の濃度微分データを使用してサブピクセル精度の計算をする
[in] interval エッジ取得間隔(0以上)
[in] direct_mode 検出するエッジ方向の指定
  • F_DRK_TO_BRI 暗→明のエッジ
  • F_BRI_TO_DRK 明→暗のエッジ
  • F_DTC_BOTH 両極性
[in] diff_type 濃度差しきい値の種別
  • F_ABSOLUTE_THR 絶対濃度差
  • F_RELATIVE_THR 相対濃度差
[in] diff_thr エッジの最小濃度差しきい値
  • F_ABSOLUTE_THR を指定した場合:[0, 2147483647]
  • F_RELATIVE_THR を指定した場合:[0,100](%)
    • 生成された濃度プロファイル内の最大値と最小値の差に対する割合
    • 求められたしきい値は、 fnFIE_d4i5() にて四捨五入される
[in] sort_mode 検出されたエッジの保存順を指定
  • F_MAG_SORT 強度順
  • F_POS_SORT 始点からの位置順
[out] edges 検出されたエッジ点保存配列のポインタ
  • x x座標
  • y y座標(必ず0となる)
  • q 勾配方向
    • 暗→明のエッジ 1
    • 明→暗のエッジ -1
  • mag 強度(0以上)
[in] edge_len エッジ点配列の長さ
  • edge_len >= prj_len
[out] edge_num 検出されたエッジ点個数
[out] diff 1次微分データ(必要ない場合はNULL)
[in] diff_len 1次微分データの長さ
  • diff_len >= prj_len
戻り値:
F_ERR_NONE 正常終了
F_ERR_NOMEMORY メモリ不足
F_ERR_INVALID_PARAM 不正なパラメータが渡された
  • pprj , edges または edge_num が NULL
  • diff_filter , arnd または interval が不正な値
  • direct_mode , diff_type, diff_thr または sort_mode が不正な値
  • prj_len > edge_len
  • diff または diff_len が不正な値
F_ERR_NODATA 濃度プロファイルに有効領域が存在しない
F_ERR_NO_LICENCE ライセンスエラー、または未初期化エラー

INT FVALGAPI fnFIE_edge1d_trans_coord_line ( F_DEDGE edges,
INT  edge_num,
DSGMT_T  line,
INT  offset 
)

計測ライン(線分)上への座標変換

fnFIE_edge1d_detect_edges_DoG() 等によって求められたエッジ点座標は、濃度プロファイル配列での位置となります。 本関数により、入力画像での計測ライン(線分)上の座標に変換します。

なお line は、 fnFIE_edge1d_projection_line() で指定した計測ラインと同じものを指定してください。

引数:
[in,out] edges 検出されたエッジ点保存配列のポインタ
  • x x座標
  • y y座標
  • q 勾配方向
    • 暗→明のエッジ 1
    • 明→暗のエッジ -1
  • mag 強度(0以上)
[in] edge_num 検出されたエッジ点個数(0以上)
[in] line 計測ライン(線分)
  • st 始点
  • ed 終点
[in] offset 濃度プロファイル配列の要素番号の始点からのオフセット量(0以上)
戻り値:
F_ERR_NONE 正常終了
F_ERR_INVALID_PARAM 不正なパラメータが渡された
F_ERR_NO_LICENCE ライセンスエラー、または未初期化エラー

INT FVALGAPI fnFIE_edge1d_trans_coord_arc ( F_DEDGE edges,
INT  edge_num,
F_ARC  arc,
INT  offset 
)

計測ライン(円弧)上への座標変換

fnFIE_edge1d_detect_edges_DoG() 等によって求められたエッジ点座標は、濃度プロファイル配列での位置となります。 本関数により、入力画像での計測ライン(円弧)上の座標に変換します。

なお arc は、 fnFIE_edge1d_projection_arc() で指定した計測ラインと同じものを指定してください。

引数:
[in,out] edges 検出されたエッジ点保存配列のポインタ
  • x x座標
  • y y座標
  • q 勾配方向
    • 暗→明のエッジ 1
    • 明→暗のエッジ -1
  • mag 強度(0以上)
[in] edge_num 検出されたエッジ点個数(0以上)
[in] arc 計測ライン(円弧)
  • x 中心x座標
  • y 中心y座標
  • radius 半径:0 < radius
  • start_angle 開始角:[0, $2\pi$]
  • sweep_angle 円弧の角度
    • 時計回り 正
    • 反時計回り 負
[in] offset 濃度プロファイル配列の要素番号の始点からのオフセット量(0以上)
戻り値:
F_ERR_NONE 正常終了
F_ERR_INVALID_PARAM 不正なパラメータが渡された
F_ERR_NO_LICENCE ライセンスエラー、または未初期化エラー


Documentation copyright © 2009-2023 FAST Corporation.
Generated on Fri Jan 13 11:09:33 2023 for FIEライブラリ by doxygen 1.5.6-FASTSP-p2