/* * ***************************************************************** * * * * * Copyright (c) Fast Corporation, 1998 * * * * * * All Rights Reserved. Unpublished rights reserved under * * * the copyright laws of the Japan. * * * * * * The software contained on this media is proprietary to * * * and embodies the confidential technology of Fast * * * Corporation. Possession, use, duplication or * * * dissemination of the software and media is authorized only * * * pursuant to a valid written license from Fast Corporation. * * * * * ***************************************************************** */ /* CSC90X NEW直線検出ハフ (Lib_xlhough_xxx) サンプルソフト XLHSMPL.C */ /*[作成者] E.Ishiyama*/ /* 目的:本サンプルソフトは新直線検出ハフ Lib_xlhough_xxx の使用例です。 ハフは複数オープンすることができます。 1つのハフには1回のみ投票ができるようになっています。 検出の対象となる濃淡画像はカメラからカレントメモリに撮り込まれ るものとします。 また、検出された直線はすべて最小2乗法によって求め直されます。 エッジは各ハフごとに取得し直していますが、投票範囲の状況次第で は取得する回数を減らして処理時間を短縮することが可能です。 関数: 履歴: Ver 1.0 1998/08/11 初版。ライブラリに付属しているサンプル(XLHOUGH.C)より一部改造。 Ver 2.0 2000/02/01 メモリ不足で検出エラーの場合のエラー表示(4Mで実行された場合の対策) ヘルプに、「16MB以上のメモリを搭載した機種で実行」のコメント追加 Ver.2.5 2000/07/07 exec_xlhough の Lib_xlhough_refine_line のコール部分で配列の添え字に 誤りがあったため、修正。 注記:m_menu.hをインクルードして下さい。 m_menu.c及びm_note.cをリンクして下さい。 */ /***** インクルードファイル *****/ #include #include "f_hough.h" #include "f_graph.h" #include "f_video.h" #include "f_gui.h" #include "f_stdlib.h" #include "f_stdio.h" #include "f_time.h" #include "f_image.h" #include "f_binmem.h" #include "f_gray.h" #include "f_pinf.h" #include "m_menu.h" /***** マクロ定義 *****/ #define OPEN_MODE 0 /* オープンモード */ #define SET_EACH_CNDT_MODE 1 /* 個別設定モード */ #define SET_COMMON_CNDT_MODE 2 /* 共通設定モード */ #define EXEC_TRIAL_MODE 3 /* 試行実行モード */ #define MAX_OPEN_NUM 10 /* オープンできるハフの最大数 */ #define MAX_LINE_NUM 256 /* 検出直線の最大数 */ #define MLN MAX_LINE_NUM #define DUMMY_INPUT 1 /***** ハフ構造体 *****/ typedef struct { /*** Lib_xlhough_open で決める条件 ***/ void *dscrp; /* 識別子 */ int ln_st_q; /* 検出する直線の法線方向の角度の範囲の始値 */ int ln_ed_q; /* 検出する直線の法線方向の角度の範囲の終値 */ int sx; int sy; int ex; int ey; /* 投票範囲(オープンの範囲) */ /*** Lib_xlhough_voting の条件 ***/ int vot_wid; /* 投票θ片幅 */ /*** Lib_xlhough_detection の条件 ***/ int rq_ln_num; /* 検出したい直線の数 */ int rgn_r; /* ρ方向極大値決定サイズ */ int rgn_q; /* θ方向極大値決定サイズ */ /*** Lib_xlhough_refine_line の条件 ***/ int err_r; /* 直線とエッジ点との距離の許容誤差 */ int err_q; /* 直線とエッジ点との向きの許容誤差 */ /*** 回答 ***/ int ans_ln_num; /* 検出された直線の数 */ XHLINE_T ans_ln[ MLN ]; /* 検出された直線 */ }XLH_T; /***** プロトタイプ *****/ /* 外部参照モジュール */ extern int message_note( void ); /* ファイル内モジュール */ static void init_sys( void ); static int select_help_pad( void ); static void display_help( int ); static void main_menu_disp( void ); static void xlhough_main_menu( void ); static void init_hough_t( XLH_T * ); static int home_pad( void ); static void open_xlhough( XLH_T[ ], int ); static int aux_open_xlhough( XLH_T * ); static void each_condition( XLH_T[ ], int ); static int aux_each_condition( XLH_T * ); static void common_condition( int * ); static void exec_xlhough( int, XLH_T[ ], int, int ); static int select_hough_no( XLH_T[ ], int, char[ ] ); static void close_all_xlhough( XLH_T[ ], int ); static void draw_line( XHLINE_T *, int ); static int d4i5_d( double ); static int edge_threshold_test_open( int, int ); static void edge_threshold_test_close( void ); static void edge_threshold_test( int, int, PARADIGM[ ] ); /***** メイン関数 *****/ void main( void ) { int pad_back; /* 初期メッセージ表示 */ if( NORMAL_RETURN != message_note() ) return; /* システムの初期化 */ init_sys(); /* パッドの表示色は黒 */ pad_back = Lib_get_pad_background(); Lib_set_pad_background( ON ); Lib_set_pad_maxstring( 10 ); /* default */ /* 新直線検出ハフのサンプル実行 */ xlhough_main_menu( ); /* パッドの表示色を元に戻す */ Lib_set_pad_background( pad_back ); } /* システムの初期化 */ static void init_sys() { /* 入力ビデオ制御 */ Lib_input_video_control( GRAY_PLANE ); /* ビデオ出力表示項目制御 */ Lib_display_control( GRAY_PLANE | LINE_PLANE | CHAR_PLANE ); /* ビデオ表示項目クリア */ Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); /* カーソル初期化 */ Lib_init_cursor(); } /* HELP選択パッド */ static int select_help_pad() { int no; int xpos,ypos; int flag; int pad_lev; int old_max_string, language; language = Lib_get_disp_language(); old_max_string = Lib_get_pad_maxstring(); /* open command2_pad */ pad_lev = Lib_view_open(); Lib_get_start_pad( pad_lev, &xpos, &ypos ); Lib_view_set_title( pad_lev, "HELP選択" ); Lib_view_set_null( pad_lev, 15, 5, " 概要説明 ", 0 ); Lib_view_set_null( pad_lev, 15, 35, " 操作説明 ", 1 ); Lib_view_set_size( pad_lev, xpos, ypos, 15, 5 ); Lib_draw_command2( pad_lev ); for( flag = ON; OFF != flag; ) { /* get command2 no*/ if( ERROR_RETURN != ( no = Lib_process_command2( pad_lev ) ) ) { switch( no ) { case 0: case 1: case 102: flag = OFF; break; } } } Lib_erase_command( pad_lev ); Lib_view_close( pad_lev ); Lib_set_pad_maxstring( old_max_string ); return( no ); } /* ヘルプの表示 */ static void display_help( mode ) int mode; /* 入力:ヘルプ種類 0:概要説明 1:操作方法説明 */ { int fx_size, fy_size; int i; int column; fx_size = Lib_get_fx_size(); fy_size = Lib_get_fy_size(); Lib_view( 0, 0, fx_size-1, fy_size-1, GRAPH_ERAS ); if( 0 == mode ) { /* メッセージ表示 */ column = 10; i = 2; Lib_chrdisp( column-1, i, "【機能\概要】 XHSMPL" ); i += 3; Lib_chrdisp( column, i ++, "新ハフ変換ライブラリのサンプルソ\フトです。" ); Lib_chrdisp( column, i ++, "このライブラリは単なる点群から直線を検出するのでは" ); Lib_chrdisp( column, i ++, "なく、濃淡画像のエッジを特徴点として直線を検出する" ); Lib_chrdisp( column, i ++, "ことを考えて作成されています。" ); Lib_chrdisp( column, i ++, "エッジの勾配方向を利用する等により従来の直線検出ハ" ); Lib_chrdisp( column, i ++, "フと比較して以下の点が改良されています;" ); i ++; column = 9; Lib_chrdisp( column, i ++, "・投票にかかる処理速度を大幅に短縮できます。" ); Lib_chrdisp( column, i ++, "・無駄な投票を減らすことで検出能\力が向上しています。" ); Lib_chrdisp( column, i ++, "・検出する直線の傾きの範囲を指定できます。" ); Lib_chrdisp( column, i ++, "・識別子により複数の直線ハフを切り分けられます。" ); Lib_chrdisp( column, i ++, " よって、例えば垂直線と水平線を独立に検出する、" ); Lib_chrdisp( column, i ++, " といったこともできます。" ); Lib_chrdisp( column, i ++, "・例えば同色の長方形のワークが非常に接近して並置" ); Lib_chrdisp( column, i ++, " されている場合でもその辺を別々に検出することが" ); Lib_chrdisp( column, i ++, " できます。" ); Lib_chrdisp( column, i ++, "・従来の検出ライブラリ Lib_lhough_detection では" ); Lib_chrdisp( column, i ++, " その処理時間が検出する直線の数に比例して増大し" ); Lib_chrdisp( column, i ++, " ていましたが、新しいライブラリでは検出直線の数" ); Lib_chrdisp( column, i ++, " が多くなってもそれほど処理時間は増大しません。" ); i++; column = 10; Lib_chrdisp( column, i ++, "なお、16MB以上のメモリを搭載した機種でご使用下さい。" ); } else { /* メッセージ表示 */ column = 5; i = 2; Lib_chrdisp( column-1, i, "【操作方法】 XHSMPL" ); i += 3; Lib_chrdisp( column, i ++, "新ハフ変換ライブラリのサンプルソ\フトです。" ); Lib_chrdisp( column, i ++, "画面上にある複数の直線を検出することができます。" ); i++; Lib_chrdisp( column, i ++, "1 オープン でハフのオープンを行います。サンプルソ\フト" ); Lib_chrdisp( column, i ++, " が起動した時点では、ハフは1個もオープンされていません。" ); Lib_chrdisp( column, i ++, " 必ず最初にオープンを実行して、検出する直線の傾きの範囲な" ); Lib_chrdisp( column, i ++, " どの条件を決めて下さい。既にオープン済みの番号を選ぶと、" ); Lib_chrdisp( column, i ++, " 条件を更新して再オープンします。" ); i++; Lib_chrdisp( column, i ++, "2 次に 個別設定 でハフごとに検出本数など、こまかいパラ" ); Lib_chrdisp( column, i ++, " メータを設定します。検出本数以外はとりあえずディフォルト" ); Lib_chrdisp( column, i ++, " で実行して、うまくいかないときに調整すると良いでしょう。" ); i++; Lib_chrdisp( column, i ++, "3 次に 共通設定 で画像からエッジを検出する際のしきい値" ); Lib_chrdisp( column, i ++, " を決定します。数値を変えるごとにリアルタイムで検出エッジ" ); Lib_chrdisp( column, i ++, " が表\示されますので、確認しながら設定して下さい。−1に設" ); Lib_chrdisp( column, i ++, " 定すると、しきい値は自動決定されます。" ); i++; Lib_chrdisp( column, i ++, "4 最後に 試行実行 で新ハフ変換を実行します。オープンし" ); Lib_chrdisp( column, i ++, " たハフごとに、検出した直線が表\示されます。左下のボタンに" ); Lib_chrdisp( column, i ++, " は表\示しているハフの番号と検出本数が表\示され、このボタン" ); Lib_chrdisp( column, i ++, " をクリックすると、次のハフの結果を表\示します。最後に、す" ); Lib_chrdisp( column, i ++, " べてのハフの結果と検出本数を表\示します。" ); } /* 表示終了のトリガー */ Lib_display_keyinput( 420, 425, "確認" ); Lib_memory_clear( CHAR_PLANE ); Lib_view( 0, 0, fx_size-1, fy_size-1, GRAPH_DRAW ); } /* メニュー項目 */ #define MAIN_MENU_N 4 static const char *main_menu_str[MAIN_MENU_N][KIND_LANGUAGE] = { { " HOUGH OPEN ", " オープン " }, { " EACH SET ", " 個別設定 " }, { " COMMON SET ", " 共通設定 " }, { " HOUGH TRY ", " 試行実行 " } }; /* メインメニュー表示 */ static void main_menu_disp( void ) { int iLanguage; /* 日本語/英語表示文字列切替情報取得 */ iLanguage = Lib_get_disp_language(); /* 整列キー表示 ( m_menu.c の中に実体 ) */ SUB_menu_disp4he( (char *)main_menu_str[0][iLanguage], (char *)main_menu_str[1][iLanguage], (char *)main_menu_str[2][iLanguage], (char *)main_menu_str[3][iLanguage] ); } static void xlhough_main_menu( void ) { int open_num; /* 直線検出ハフのオープン最大数 */ XLH_T *hough; /* ハフ構造体の配列 */ int mem_no; /* カレント濃淡画像メモリ番号 */ int cmn_thres; /* 共通のエッジ取得の下限しきい値 */ int i, column, line; int xpos, ypos, old_xpos, old_ypos; int sts, help_no; int fx_size, fy_size; char string[100]; fx_size = Lib_get_fx_size(); fy_size = Lib_get_fy_size(); Lib_view( 0, 0, fx_size-1, fy_size-1, GRAPH_ERAS ); Lib_sprintf( string, "オープンするハフの最大数を決めて下さい。(MAX%d)", MAX_OPEN_NUM ); /* オープンする直線検出ハフの最大数を決める */ line = 5; column = 5; Lib_chrdisp( column, line, string ); line+=3; Lib_chrdisp( column-1, line, "[ヒント]" ); line+=2; Lib_chrdisp( column, line, "新ハフ変換では、検出したい直線の傾きの範囲を限定する" ); line++; Lib_chrdisp( column, line, "ことができます。そのことによって、水平方向の直線や、" ); line++; Lib_chrdisp( column, line, "垂直方向の直線に限定して検出したりできます。 " ); line++; Lib_chrdisp( column, line, "複数の異なった条件の直線を検出したい場合は、条件ごと" ); line++; Lib_chrdisp( column, line, "にハフをオープンします。" ); column++; line++; /* 数値取得のキーボード表示 */ open_num = Lib_get_value_by_ten_keyboad( 75, 300, 1L, 1L, MAX_OPEN_NUM ); Lib_memory_clear( CHAR_PLANE ); Lib_view( 0, 0, fx_size-1, fy_size-1, GRAPH_DRAW ); /* 共通のパラメータの初期化 */ cmn_thres = -1; /* ハフ構造体配列の確保 */ if( NULL != ( hough = ( XLH_T * )Lib_mlalloc( sizeof( XLH_T )* open_num ) ) ) { /* ハフ構造体の初期化 */ for( i = 0 ; i < open_num ; i ++ ) init_hough_t( &hough[ i ] ); /* カレントメモリの番号 */ mem_no = Lib_get_gray_memory( ); /* メニューの表示 */ main_menu_disp(); /* マウスカーソルの現在位置取得 */ Lib_look_current_position( &xpos, &ypos ); /* マウスカーソルの表示 */ Lib_draw_cursor( xpos, ypos ); /* メニュー制御 */ for (;;) { sts = 0; /* マウス位置読みとり */ Lib_look_current_position( &xpos, &ypos ); sts = Lib_see_current_position( &xpos, &ypos ); if ( old_xpos != xpos || old_ypos != ypos ) { /* マウス表示位置移動 */ Lib_move_cursor( xpos, ypos ); old_xpos = xpos; old_ypos = ypos; } /* 処理振り分け */ if( CURSOR_EXECUTE == sts ) { if ( xpos > MENU_1_XS && xpos < MENU_1_XE && ypos > MENU_1_YS && ypos < MENU_1_YE ) { Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); open_xlhough( hough, open_num ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); main_menu_disp(); } else if ( xpos > MENU_2_XS && xpos < MENU_2_XE && ypos > MENU_2_YS && ypos < MENU_2_YE ) { Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); each_condition( hough, open_num ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); main_menu_disp(); } else if ( xpos > MENU_3_XS && xpos < MENU_3_XE && ypos > MENU_3_YS && ypos < MENU_3_YE ) { Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); common_condition( &cmn_thres ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); main_menu_disp(); } /* 試行 */ else if ( xpos > MENU_4_XS && xpos < MENU_4_XE && ypos > MENU_4_YS && ypos < MENU_4_YE ) { Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); exec_xlhough( mem_no, hough, open_num, cmn_thres ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); main_menu_disp(); } else if ( xpos > MENU_H_XS && xpos < MENU_H_XE && ypos > MENU_H_YS && ypos < MENU_H_YE ) { Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); if( PAD_QUIT != ( help_no = select_help_pad() ) ) display_help(help_no ); /* ヘルプ */ main_menu_disp(); } else if ( xpos > MENU_E_XS && xpos < MENU_E_XE && ypos > MENU_E_YS && ypos < MENU_E_YE ) { break; /* 終了 */ } } } /* オープンされているハフを全てクローズする */ close_all_xlhough( hough, open_num ); /* ハフ構造体配列の解放 */ Lib_lfree( ( char * )hough ); } else { Lib_display_keyinput( 5, 450, " Memory Error " ); } } /***** ハフ構造体の初期化 *****/ static void init_hough_t( XLH_T *hough /* ハフ構造体 */ ) { int fx, fy; /* 画像のサイズ */ /* 画像のサイズ */ fx = Lib_get_fx_size( ); fy = Lib_get_fy_size( ); /* for Lib_xlhough_open */ hough->dscrp = NULL; hough->ln_st_q = -179; hough->ln_ed_q = 180; hough->sx = 0; hough->sy = 0; hough->ex = fx - 1; hough->ey = fy - 1; /* for Lib_xlhough_voting */ hough->vot_wid = 10; /* for Lib_xlhough_detection */ hough->rq_ln_num = 1; hough->rgn_r = 20; hough->rgn_q = 10; /* for Lib_xlhough_refine_line */ hough->err_r = 3; hough->err_q = 10; /* answer */ hough->ans_ln_num = 0; } /***** オープン *****/ static void open_xlhough( XLH_T hough[ ], /* ハフ構造体配列 */ int open_num /* 直線検出ハフのオープン最大数 */ ) { int no; /* 設定するハフの番号 */ /* フリーズ */ Lib_freeze( TRANSMIT ); while( 1 ) { /* 設定するハフの番号を選択;終了キーが押下されたら終了 */ if( PAD_QUIT == ( no = select_hough_no( hough, open_num, "オープン" ) ) ) break; /* 既にオープンされているものに対する更新の確認 */ if( NULL != hough[ no ].dscrp ) { Lib_display_control( LINE_PLANE | CHAR_PLANE ); if( PAD_EXECUTE == Lib_display_message2( 80, 150, " 確認 ", "これはオープン済ですが更新しますか?" ) ) { /* クローズしておく */ Lib_xlhough_close( hough[ no ].dscrp ); hough[ no ].dscrp = NULL; } Lib_display_control( GRAY_PLANE | LINE_PLANE | CHAR_PLANE ); } /* まだオープンされていないものに対する処理 */ if( NULL == hough[ no ].dscrp ) { /* オープンの条件設定 */ if( PAD_EXECUTE == aux_open_xlhough( &hough[ no ] ) ) { /* オープン */ if( NULL != ( hough[ no ].dscrp = Lib_xlhough_open( hough[ no ].ln_st_q, hough[ no ].ln_ed_q, hough[ no ].sx, hough[ no ].sy, hough[ no ].ex, hough[ no ].ey, DUMMY_INPUT ) ) ) { ; } else { Lib_display_keyinput( 5, 450, " Open Error " ); } } } } /* フリーラン */ Lib_freerun( ); } /***** オープンの条件設定 *****/ static int aux_open_xlhough( XLH_T *hough /* ハフ構造体 */ ) { int mode; /* 実行キーまたは取消キーの入力情報 */ int pad_level; /* パッドレベル */ PVAL value[ 5 ]; /* 各メニューの値 */ int max_str; int wx, wy; /* パラメータ初期化 */ wx = hough->ex - hough->sx + 1; wy = hough->ey - hough->sy + 1; /* パッドのオープン */ pad_level = Lib_view_open( ); /* 表示文字数の更新 */ max_str = Lib_get_pad_maxstring( ); Lib_set_pad_maxstring( 24 ); /* パッドのタイトル */ Lib_view_set_title( pad_level, " オープン " ); /* モード・キーの表示 */ Lib_view_set_comment( pad_level, 15, 15, " Lib_xlhough_open ", 0 ); Lib_view_set_uniq_numeral( pad_level, 15, 45, "直線の法線方向角度の始値", hough->ln_st_q, -360, 360, 1 ); Lib_view_set_uniq_numeral( pad_level, 15, 75, "直線の法線方向角度の終値", hough->ln_ed_q, 0, 360, 2 ); Lib_view_set_box( pad_level, 15, 115, "投票する範囲の始点 ", hough->sx, hough->sy, 3, 4, 3 ); Lib_view_set_box( pad_level, 15, 145, "投票する範囲のサイズ", wx, wy, 3, 3, 4 ); /* パッドの位置、右マージン、下マージンの設定 */ Lib_view_set_size( pad_level, 45, 45, 15, 15 ); /* パッドの表示 */ Lib_draw_menu( pad_level ); /* 選択されたキーの番号の取得 */ mode = Lib_process_menu( pad_level, value ); /* 「実行」が選択された場合の処理 */ if( PAD_EXECUTE == mode ) { hough->ln_st_q = value[ 1 ].value_type; hough->ln_ed_q = value[ 2 ].value_type; hough->sx = value[ 3 ].box_type.x; hough->sy = value[ 3 ].box_type.y; hough->ex = value[ 4 ].box_type.x + hough->sx - 1; hough->ey = value[ 4 ].box_type.y + hough->sy - 1; } /* パッドの消去 */ Lib_erase_menu( pad_level ); /* 表示文字数を戻しておく */ Lib_set_pad_maxstring( max_str ); /* パッドのクローズ */ Lib_view_close( pad_level ); /* 返値は実行キーまたは取消キーの入力情報 */ return( mode ); } /***** 個別設定 *****/ static void each_condition( XLH_T hough[ ], /* ハフ構造体配列 */ int open_num /* 直線検出ハフのオープン最大数 */ ) { int no; /* 設定するハフの番号 */ /* フリーズ */ Lib_freeze( TRANSMIT ); while( 1 ) { /* 設定するハフの番号を選択;終了キーが押下されたら終了 */ if( PAD_QUIT == ( no = select_hough_no( hough, open_num, "個別設定" ) ) ) break; /* まだオープンされていないものに対する処理 */ if( NULL == hough[ no ].dscrp ) { Lib_display_control( LINE_PLANE | CHAR_PLANE ); Lib_display_message( 80, 150, " エラー ", "この番号はまだオープンされていません" ); Lib_display_control( GRAY_PLANE | LINE_PLANE | CHAR_PLANE ); } else { /* 画像表示をオープンで設定したものにする */ Lib_window( hough[ no ].sx, hough[ no ].sy, hough[ no ].ex, hough[ no ].ey ); /* その他の設定 */ aux_each_condition( &hough[ no ] ); /* 画像表示を全面に戻す */ Lib_window( 0, 0, Lib_get_fx_size( ) - 1, Lib_get_fy_size( ) - 1 ); } } /* フリーラン */ Lib_freerun( ); } /***** 投票ウィンドウ以外の個別設定の実際 *****/ static int aux_each_condition( XLH_T *hough /* ハフ構造体 */ ) { int mode; /* 実行キーまたは取消キーの入力情報 */ int pad_level; /* パッドレベル */ PVAL value[ 9 ]; /* 各メニューの値 */ int mem_no; /* カレントメモリ番号 */ int max_str; /* カレントメモリ番号 */ mem_no = Lib_get_gray_memory( ); /* パッドのオープン */ pad_level = Lib_view_open( ); /* 表示文字数の更新 */ max_str = Lib_get_pad_maxstring( ); Lib_set_pad_maxstring( 24 ); /* パッドのタイトル */ Lib_view_set_title( pad_level, "個別設定" ); /* モード・キーの表示 */ Lib_view_set_comment( pad_level, 15, 15, " Lib_xlhough_voting ", 0 ); Lib_view_set_uniq_numeral( pad_level, 15, 45, "投票θ片幅", hough->vot_wid, 0L, 179L, 1 ); Lib_view_set_comment( pad_level, 15, 85, " Lib_xlhough_detection ", 2 ); Lib_view_set_uniq_numeral( pad_level, 15, 115, "検出直線数", hough->rq_ln_num, 1L, MLN, 3 ); Lib_view_set_uniq_numeral( pad_level, 15, 145, "ρ方向極大値決定サイズ", hough->rgn_r, 1L, 200L, 4 ); Lib_view_set_uniq_numeral( pad_level, 15, 175, "θ方向極大値決定サイズ", hough->rgn_q, 0L, 179L, 5 ); Lib_view_set_comment( pad_level, 15, 215, " Lib_xlhough_refine_line ", 6 ); Lib_view_set_uniq_numeral( pad_level, 15, 245, "距離の最大許容誤差", hough->err_r, 0L, 20L, 7 ); Lib_view_set_uniq_numeral( pad_level, 15, 275, "向きの最大許容誤差", hough->err_q, 0L, 90L, 8 ); /* パッドの位置、右マージン、下マージンの設定 */ Lib_view_set_size( pad_level, 45, 45, 15, 15 ); /* パッドの表示 */ Lib_draw_menu( pad_level ); /* 選択されたキーの番号の取得 */ mode = Lib_process_menu( pad_level, value ); /* 「実行」が選択された場合の処理 */ if( PAD_EXECUTE == mode ) { hough->vot_wid = value[ 1 ].value_type; hough->rq_ln_num = value[ 3 ].value_type; hough->rgn_r = value[ 4 ].value_type; hough->rgn_q = value[ 5 ].value_type; hough->err_r = value[ 7 ].value_type; hough->err_q = value[ 8 ].value_type; } /* パッドの消去 */ Lib_erase_menu( pad_level ); /* 表示文字数を戻しておく */ Lib_set_pad_maxstring( max_str ); /* パッドのクローズ */ Lib_view_close( pad_level ); /* 返値は実行キーまたは取消キーの入力情報 */ return( mode ); } /***** 共通の設定 *****/ static void common_condition( int *cmn_thres /* 共通のエッジの下限しきい値 */ ) { int mode; /* 実行キーまたは取消キーの入力情報 */ int pad_level; /* パッドレベル */ PVAL value[ 2 ]; /* 各メニューの値 */ int mem_no; /* カレントメモリ番号 */ int max_str; /* 返値の初期化 */ mode = ERROR_RETURN; /* フリーズ */ Lib_freeze( TRANSMIT ); /* カレントメモリ番号 */ mem_no = Lib_get_gray_memory( ); /* しきい値テストのオープン */ if( NORMAL_RETURN == edge_threshold_test_open( mem_no, *cmn_thres ) ) { /* パッドのオープン */ pad_level = Lib_view_open( ); /* 表示文字数の更新 */ max_str = Lib_get_pad_maxstring( ); Lib_set_pad_maxstring( 12 ); /* パッドのタイトル */ Lib_view_set_title( pad_level, "共通設定" ); /* モード・キーの表示 */ Lib_view_set_comment( pad_level, 15, 15, " Lib_xlhough_edge_open ", 0 ); Lib_view_set_uniq_numeral( pad_level, 15, 45, "しきい値", *cmn_thres, -1, 255, 1 ); /* エッジのしきい値テスト */ Lib_set_paradigm( pad_level, 1, WHOLE_TIMING, edge_threshold_test ); /* パッドの位置、右マージン、下マージンの設定 */ Lib_view_set_size( pad_level, 45, 45, 15, 15 ); /* パッドの表示 */ Lib_draw_menu( pad_level ); /* 選択されたキーの番号の取得 */ mode = Lib_process_menu( pad_level, value ); /* 「実行」が選択された場合の処理 */ if( PAD_EXECUTE == mode ) { *cmn_thres = value[ 1 ].value_type; } /* パッドの消去 */ Lib_erase_menu( pad_level ); /* 表示文字数を戻しておく */ Lib_set_pad_maxstring( max_str ); /* パッドのクローズ */ Lib_view_close( pad_level ); /* しきい値テストのクローズ */ edge_threshold_test_close( ); } /* フリーラン */ Lib_freerun( ); } /***** 【試行実行】--- 直線検出ハフの投票と検出、回答表示 *****/ static void exec_xlhough( int mem_no, /* 検出対象となる濃淡画像メモリ番号 */ XLH_T hough[ ], /* ハフ構造体配列 */ int open_num, /* 直線検出ハフのオープン最大数 */ int thres /* すべてのハフに共通のエッジ取得しきい値 */ ) { int time_init, time_edge, time_vot, time_det, time_ref; /* 各処理時間 */ int sum; /* 回答直線数の合計 */ QEDGE_T *edge; /* エッジ配列 */ int edge_num; /* エッジの数 */ XHLINE_T *ans_ln; int ans_ln_num; char str[ 100 ]; int i, j; /* 処理時間の初期化 */ time_init = 0; time_edge = 0; time_vot = 0; time_det = 0; time_ref = 0; /* フリーズ */ Lib_freeze( TRANSMIT ); for( i = 0 ; i < open_num ; i ++ ) { /* オープンされているハフをすべて試行 */ if( NULL != hough[ i ].dscrp ) { /*** ハフ投票空間の初期化 ***/ Lib_strtclk_count( ); Lib_xlhough_init_hough_sp( hough[ i ].dscrp ); time_init += Lib_readclk_count( ); /*** エッジの取得(オープン) ***/ Lib_strtclk_count( ); edge_num = Lib_xlhough_edge_open( mem_no, thres, hough[ i ].sx, hough[ i ].sy, hough[ i ].ex, hough[ i ].ey, &edge ); /* 正常終了 2000.02.01 エラーチェック追加 E,Ishiyama*/ if( 0 <= edge_num ) { time_edge += Lib_readclk_count( ); /*** 投票 ***/ Lib_strtclk_count( ); Lib_xlhough_voting( hough[ i ].dscrp, edge, edge_num, hough[ i ].vot_wid ); time_vot += Lib_readclk_count( ); /*** 検出 ***/ Lib_strtclk_count( ); ans_ln_num = Lib_xlhough_detection( hough[ i ].dscrp, hough[ i ].rq_ln_num, hough[ i ].rgn_r, hough[ i ].rgn_q, hough[ i ].ans_ln ); /* 正常終了 2000.02.01 エラーチェック追加 E,Ishiyama */ if( 0 <= ans_ln_num ) { hough[ i ].ans_ln_num = ans_ln_num; time_det += Lib_readclk_count( ); /*** 最小2乗法で求め直す ***/ Lib_strtclk_count( ); for( j = 0, ans_ln = hough[ i ].ans_ln ; j < ans_ln_num ; j ++ ) { /***** 00/07/07:index が間違えていたので修正 *****/ #if 0 Lib_xlhough_refine_line( &ans_ln[ i ], edge, edge_num, hough[ i ].err_r, hough[ i ].err_q ); #endif Lib_xlhough_refine_line( &ans_ln[ j ], edge, edge_num, hough[ j ].err_r, hough[ j ].err_q ); /****************************************************/ } time_ref += Lib_readclk_count( ); } /*メモリ不足等のエラー*/ else { hough[ i ].ans_ln_num = ERROR_RETURN; } } /*メモリ不足等のエラー*/ else { hough[ i ].ans_ln_num = ERROR_RETURN; } /*** エッジの解放(クローズ) ***/ Lib_xlhough_edge_close( edge ); } } /* 処理時間の補正 */ time_init = time_init * 8138 / 10000;; time_edge = time_edge * 8138 / 10000;; time_vot = time_vot * 8138 / 10000;; time_det = time_det * 8138 / 10000;; time_ref = time_ref * 8138 / 10000;; /* 処理時間測定終了・表示 */ Lib_sprintf( str, " 初期化 :%5d (ms)", time_init ); Lib_chrdisp( 40, 3, str ); Lib_sprintf( str, " エッジ :%5d (ms)", time_edge ); Lib_chrdisp( 40, 4, str ); Lib_sprintf( str, " 投票 :%5d (ms)", time_vot ); Lib_chrdisp( 40, 5, str ); Lib_sprintf( str, " 検出 :%5d (ms)", time_det ); Lib_chrdisp( 40, 6, str ); Lib_sprintf( str, " 最小2乗法 :%5d (ms)", time_ref ); Lib_chrdisp( 40, 7, str ); Lib_chrdisp( 40, 8, "------------------------" ); Lib_sprintf( str, "処理時間合計:%5d (ms)", time_init + time_edge + time_vot + time_det + time_ref ); Lib_chrdisp( 40, 9, str ); /*** 回答表示 ***/ /* まずは各ハフごとに表示;ついでに直線数の合計も算出 */ for( i = 0, sum = 0 ; i < open_num ; i ++ ) { if( NULL != hough[ i ].dscrp ) { if( 0 <= hough[ i ].ans_ln_num ) { sum += hough[ i ].ans_ln_num; for( j = 0 ; j < hough[ i ].ans_ln_num ; j ++ ) { draw_line( &hough[ i ].ans_ln[ j ], SOLID_LINE ); } /*2000.02.01 結果表示日本語へ E,Ishiyama*/ Lib_sprintf( str, "ハフNo = %d, 検出本数 = %3d", i, hough[ i ].ans_ln_num ); } else { /*2000.02.01 結果表示日本語へ E,Ishiyama*/ Lib_sprintf( str, "ハフNo = %d, ハフ実行エラー!!", i ); } Lib_display_keyinput( 5, 420, str ); for( j = 0 ; j < hough[ i ].ans_ln_num ; j ++ ) { draw_line( &hough[ i ].ans_ln[ j ], BLACK_LINE ); } } } /* 最後に一遍に表示 */ for( i = 0 ; i < open_num ; i ++ ) { if( NULL != hough[ i ].dscrp ) { if( ERROR_RETURN != hough[ i ].ans_ln_num ) { for( j = 0 ; j < hough[ i ].ans_ln_num ; j ++ ) { draw_line( &hough[ i ].ans_ln[ j ], SOLID_LINE ); } } } } /*2000.02.01 結果表示日本語へ E,Ishiyama*/ Lib_sprintf( str, " 全ハフ 検出本数 = %3d", sum ); Lib_display_keyinput( 5, 420, str ); /* 画面のクリア */ Lib_cls( LINE_PLANE | CHAR_PLANE, BLACK_COLOR ); /* フリーラン */ Lib_freerun( ); } /***** 設定するハフの番号を選択;終了キーが押下されたら終了 *****/ static int select_hough_no( XLH_T hough[ ], /* ハフ構造体配列 */ int open_num, /* 直線検出ハフのオープン最大数 */ char title[ ] /* パッドのタイトル */ ) { int mode; /* 選択されたキーの番号 */ int pad_level; /* パッドレベル */ char str[ 11 ]; int w, h; int i; /* パッドのオープン */ pad_level = Lib_view_open( ); /* パッドのタイトル */ Lib_view_set_title( pad_level, title ); /* キーの大きさ */ Lib_get_standard_key_size( &w, &h ); /* モード・キーの表示 */ for( i = 0 ; i < open_num ; i ++ ) { if( NULL != hough[ i ].dscrp ) Lib_sprintf( str, "ハフ%d[○]", i ); else Lib_sprintf( str, "ハフ%d[×]", i ); Lib_view_set_null( pad_level, 5, i * h, str, i ); } /* パッドの位置、右マージン、下マージンの設定 */ Lib_view_set_size( pad_level, 45, 45, 5, 0 ); /* パッドの表示 */ Lib_draw_command( pad_level ); /* 選択されたキーの番号の取得 */ mode = Lib_process_command( pad_level ); /* パッドの消去 */ Lib_erase_command( pad_level ); /* パッドのクローズ */ Lib_view_close( pad_level ); /* 返値は選択されたキーの番号 */ return( mode ); } /***** クローズされていないハフを全てクローズする *****/ static void close_all_xlhough( XLH_T hough[ ], /* ハフ構造体配列 */ int open_num /* 直線検出ハフのオープン最大数 */ ) { int i; for( i = 0 ; i < open_num ; i ++ ) { if( NULL != hough[ i ].dscrp ) Lib_xlhough_close( hough[ i ].dscrp ); } } #undef EPS #define DBL_EPS 1.0e-9 /* ε(double用) */ #define EPS DBL_EPS /* ε */ /***** 画面いっぱいの直線の描画 *****/ static void draw_line( XHLINE_T *line, /* 直線 */ int ptn /* 描画パタン */ ) { double a, b, c; int sx, ex, sy, ey; int max_x, max_y; a = line->a; b = line->b; c = line->c; max_x = Lib_get_fx_size( ) - 1; max_y = Lib_get_fy_size( ) - 1; if(( DBL_EPS < fabs( a ) )||( DBL_EPS < fabs( b ) ) ) { if( fabs( a ) < DBL_EPS ) { sx = 0; ex = max_x; sy = ey = d4i5_d( -c / b ); } else if( fabs( b ) < DBL_EPS ) { sy = 0; ey = max_y; sx = ex = d4i5_d( -c / a ); } else { if( 1.0 < fabs( a / b ) ) { sy = 0; ey = max_y; sx = d4i5_d( -c / a ); ex = d4i5_d( -( ( b *( double )max_y ) + c )/ a ); } else { sx = 0; ex = max_x; sy = d4i5_d( -c / b ); ey = d4i5_d( -( a *( double )max_x + c ) / b ); } } Lib_line( sx, sy, ex, ey, ptn ); } } /***** 小数の四捨五入 *****/ static int d4i5_d( double in_val /* 入力小数 */ ) { if( in_val >= 0.0 ) return( ( int )( in_val + 0.5 ) ); else return( ( int )( in_val - 0.5 ) ); } /***** エッジのしきい値テストに用いる静的グローバル変数 *****/ static int test_org_mem_no; static int test_edge_mem_no; static int test_thres; static int test_sx, test_sy, test_ex, test_ey; /***** エッジ画像しきい値テストのオープン *****/ int edge_threshold_test_open( int org_mem_no, /* 濃淡画像メモリ番号 */ int init_thres /* しきい値の初期値 */ ) { int err_rprt; test_thres = init_thres; test_org_mem_no = org_mem_no; /* 処理は全面 */ test_sx = 0; test_sy = 0; test_ex = Lib_get_fx_size( ) - 1; test_ey = Lib_get_fy_size( ) - 1; if( ERROR_RETURN != ( test_edge_mem_no = Lib_alloc_gray_memory( ) ) ) { err_rprt = NORMAL_RETURN; } else { err_rprt = ERROR_RETURN; } return( err_rprt ); } /***** エッジ画像しきい値テストのクローズ *****/ void edge_threshold_test_close( void ) { Lib_change_gray_memory( test_org_mem_no ); Lib_free_gray_memory( test_edge_mem_no ); } /***** エッジ画像の下限濃度しきい値を決める;パッドのパラダイム機能を使用 *****/ void edge_threshold_test( int timing, int num, PARADIGM val[ ] ) { static int bin_mem_no; int thres; /* カレント使わせてもらいます */ bin_mem_no = Lib_get_bin_memory( ); switch( timing ) { case START_TIMING: { Lib_bin_memory_cls( bin_mem_no ); Lib_display_control( BIN_PLANE | CHAR_PLANE | LINE_PLANE ); thres = ( int )val[ 0 ].long_type; Lib_xlhough_thres_test( test_org_mem_no, bin_mem_no, thres, test_sx, test_sy, test_ex, test_ey ); Lib_xvideo_transmit( bin_mem_no, BIN_PLANE ); break; } case PROCESS_TIMING: { thres = ( int )val[ 0 ].long_type; Lib_xlhough_thres_test( test_org_mem_no, bin_mem_no, thres, test_sx, test_sy, test_ex, test_ey ); Lib_xvideo_transmit( bin_mem_no, BIN_PLANE ); break; } case END_TIMING: { Lib_display_control( GRAY_PLANE | CHAR_PLANE | LINE_PLANE ); Lib_xvideo_transmit( test_org_mem_no, GRAY_PLANE ); test_thres = ( int )val[ 0 ].long_type; break; } } }