/* * ***************************************************************** * * * * * Copyright (c) Fast Corporation, 1997 * * * * * * 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 サイズ及び面取り計測 MENTORI.C */ /*[作成者]S.Kodama */ /* 目的: 関数: 履歴: Ver 1.0 97/11/07 注記:m_menu.hをインクルードして下さい。 m_menu.c及びm_note.cをリンクして下さい。 */ /* * Include compiler runtime library */ #include #include #include /* * Include CSC90X library */ #include "f_stdlib.h" #include "f_time.h" #include "f_gui.h" #include "f_stdio.h" #include "f_graph.h" #include "f_image.h" #include "f_pinf.h" #include "f_video.h" #include "f_system.h" #include "f_math.h" #include "f_file.h" #include "f_gray.h" /* * Include CSC90X common local */ #include "m_menu.h" /* * プロトタイプ宣言 */ void main( void ); void main_menu_disp( void ); void disp_help( void ); int prog_Open( void ); /* 初期処理、初期設定 */ void prog_Close( void ); /* 終了処理 */ void Parameter_set( void ); /* メイン・メニューの表示 */ void P_position( void ); /* 計測対象画像の指示 */ void P_box( void ); /* エッジ抽出枠の設定 */ void box_set( int ); /* 枠設定サブルーチン */ void P_article( void ); /* エッジ抽出条件設定対象枠の指定 */ void article_set( int ); /* エッジ抽出条件設定 */ void scan_set( int, int, PARADIGM * ); /* エッジ抽出条件→走査方向設定 */ void pitch_set( int, int, PARADIGM * ); /* エッジ抽出条件→走査線間隔設定 */ void P_calib( void ); /* キャリブレーション */ void P_other( void ); /* その他(表示SW等)設定 */ void P_save( void ); /* データ・セーブ */ void Execute( int ); /* 計測実行 */ int get_adr_data( int, int, int, int, int * ); int get_gray_data( int, int, int, int, int *, int * ); void light_to_dark_border( int, int, int, int *, int *, int * ); void dark_to_light_border( int, int, int, int *, int *, int * ); extern int message_note( void ); /* * メニュー項目 */ #define LANG_N 2 #define MAIN_MENU_N 4 static const char *str_main_menu[MAIN_MENU_N][LANG_N] = { { " SET ", " 設 定 " }, { " EXEC ", " 実 行 " }, { " PROC3 ", " 処理3 " }, { " PROC4 ", " 処理4 " } }; #define INIT_CUR_POS_X 255 #define INIT_CUR_POS_Y 239 #define GRAPHIC_DATA_SIZE 31220 /* 文字(or線画)プレーン退避サイズ */ #define MAX_BOX 4 /* エッジ抽出枠の最大登録数(はこの数字を増減させるだけで増減できる) */ #define CAMERA_CH0 0 /* 処理&パラメータ設定対象画面はチャンネル0 */ #define CAMERA_CH1 1 /* 処理&パラメータ設定対象画面はチャンネル1 */ #define HORIZONTAL_SCAN 0 /* 横(X)方向走査 */ #define VERTICAL_SCAN 1 /* 縦(Y)方向走査 */ #define LIB_SCAN 0 /* ライブラリを使ったエッジ抽出 */ #define ORG_SCAN 1 /* 独自方式のエッジ抽出 */ #define H_LEFT_TO_RIGHT 0 /* 左から右へ走査 */ #define H_RIGHT_TO_LEFT 1 /* 右から左へ走査 */ #define V_HIGH_TO_LOW 0 /* 上から下へ走査 */ #define V_LOW_TO_HIGH 1 /* 下から上へ走査 */ #define ABS_LEVEL 0 /* エッジ検出レベルは固定レベル */ #define PERCENT_LEVEL 1 /* エッジ検出レベルは百分率レベル */ #define NON_ENTRY -1 /* 計測部位指定格納エリアが未登録の場合は -1 */ #define EXE 0 /* リモート時の実行 */ #define TRY 1 /* 手操作での実行 */ #define MAX_KIND 100 /* 品種の総数 */ #define MENTORI_ED_LINE_LIMIT 30 /*面取り部エッジ検出ラインの各交点から中心方向へのリミッタ(画素)*/ /*--------------------------------------*/ /* 内容保持(ファイル化)パラメータ群 */ /*--------------------------------------*/ static struct SAVE_DATA { int box_no; /* エッジ抽出枠の総個数 */ int xs[MAX_BOX]; /* 枠の始点X:0〜511 */ int ys[MAX_BOX]; /* 枠の始点Y:0〜479 */ int xe[MAX_BOX]; /* 枠の終点X:0〜511 */ int ye[MAX_BOX]; /* 枠の終点Y:0〜479 */ int scan_vh[MAX_BOX]; /* 走査方向:0=X方向、1=Y方向 */ int pitch[MAX_BOX]; /* 走査線の間隔:2〜100 */ int zero_cross[MAX_BOX]; /* ゼロクロス位置処理法:0=平均、1=生 */ int edge_level[MAX_BOX]; /* エッジ検出しきい値:0〜255 */ int scan_type[MAX_BOX]; /* エッジ抽出法:0=ライブラリ、1=オリジナル */ int org_direction[MAX_BOX]; /* 抽出方向:右→左、左→右、上→下、下→上 */ int org_level_type[MAX_BOX]; /* 抽出レベル:0=固定、1=百分率 */ int retry[MAX_BOX]; /* 再計測スイッチ */ int eliminate_pos[MAX_BOX]; /* 再計測の際に排除するエッジ点 */ double pm_multiplier; /* 画素→μ 変換乗数(内部で計算) */ int box_dispray; /* エッジ抽出枠表示スイッチ */ int scan_line_display; /* 走査線表示スイッチ */ int edge_display; /* エッジ検出位置表示スイッチ */ int calc_line_display; /* 近似直線表示スイッチ */ } *userp[MAX_KIND]; /*--------------------------------*/ /* (サブルーチン間)共用エリア */ /*--------------------------------*/ static unsigned char *gray_mem_base_adr; /* 濃淡画像メモリベースアドレス */ static int current_position; /* 現在選択されている対象(チャンネル)画像 */ static int current_box_no; /* 現在選択されているエッジ抽出枠 */ /* * メイン */ void main( void ) { int sts; int xpos; int ypos; int s_xpos; int s_ypos; /* 初期メッセージ表示 */ if( NORMAL_RETURN != message_note() ) return; /* パラメタ初期化 */ xpos = INIT_CUR_POS_X; ypos = INIT_CUR_POS_Y; s_xpos = INIT_CUR_POS_X; s_ypos = INIT_CUR_POS_Y; /* 入力ビデオ制御 */ 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(); /* メインメニューの表示 */ main_menu_disp(); /* マウスカーソルの表示 */ Lib_draw_cursor( INIT_CUR_POS_X, INIT_CUR_POS_Y ); if( -1 == prog_Open() ) return; /* イニシャライザーが -1=ERROR を返答したらオシマイ */ /* メニュー制御 */ for (;;) { sts = 0; /* マウス位置読みとり */ sts = Lib_see_current_position( &xpos, &ypos ); if ( s_xpos != xpos || s_ypos != ypos ) { /* マウス表示位置移動 */ Lib_move_cursor( xpos, ypos ); s_xpos = xpos; s_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 ); Parameter_set(); /*設定*/ 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 ); Execute( TRY ); /*実行*/ 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 ); disp_help(); /* ヘルプ */ main_menu_disp(); } else if ( xpos > MENU_E_XS && xpos < MENU_E_XE && ypos > MENU_E_YS && ypos < MENU_E_YE ) { break; /* 終了 */ } } } prog_Close(); } /* * メインメニュー表示 */ static void main_menu_disp( void ) { int iLanguage; /* 日本語/英語表示文字列切替情報取得 */ iLanguage = Lib_get_disp_language(); /* 整列キー表示 -> ( m_menu.c ) */ SUB_menu_disp4he( (char *)str_main_menu[0][iLanguage], (char *)str_main_menu[1][iLanguage], (char *)NULL, (char *)NULL ); } /* * ヘルプ表示 */ static void disp_help( void ) { Lib_chrdisp( 10, 8, "【機能\概要】 MENTORI" ); Lib_chrdisp( 11, 10, "<サイズ及び面取り計測>" ); Lib_chrdisp( 11, 12, "面取りされたパッケージ等の縦横寸法および中心" ); Lib_chrdisp( 11, 14, "から四隅の面取り部分(面取り方向に沿った直線)" ); Lib_chrdisp( 11, 16, "までの距離を求めます。" ); Lib_chrdisp( 11, 18, "面取り部エッジ検出ラインの各交点から中心方向" ); Lib_chrdisp( 11, 20, "へのリミッタは30画素固定です。" ); } /**************************************************************/ /*  初期処理、初期設定                   */ /**************************************************************/ int prog_Open() { int i, pos; long size; char *pointer; /** RAM上にパラメータ領域を確保する */ size = (long)sizeof( struct SAVE_DATA ); if( NULL == ( pointer = Lib_mlalloc( size * MAX_KIND )) ) { Lib_invdisp( 2, 10, "ERROR:ユーザーパラメータ領域が確保できない。 動作不能!" ); Lib_time_delay( 5000 ); return( -1 ); } userp[0] = (void *)pointer; for( i = 1; i < MAX_KIND; i++ ) userp[i] = userp[i-1] + 1; /** 保存データを呼び出す **/ if( 0L == Lib_fload( "\\FS0\\MENTORI.DAT", pointer, size * MAX_KIND ) ) { /* 過去に保存したデータが無ければ動作条件パラメータを全て初期(デフォルト値)化 */ for( pos = 0; pos < MAX_KIND; pos++ ) { userp[pos]->box_no = 0; /* エッジ抽出枠の登録総個数:0 */ for( i = 0; i < MAX_BOX; i++ ) { userp[pos]->xs[i] = 200; /* 枠の始点X:200 */ userp[pos]->ys[i] = 200; /* 枠の始点Y:200 */ userp[pos]->xe[i] = 300; /* 枠の終点X:300 */ userp[pos]->ye[i] = 250; /* 枠の終点Y:250 */ userp[pos]->scan_vh[i] = 0; /* 走査方向:X方向 */ userp[pos]->pitch[i] = 5; /* 枠内の走査線の間隔:5画素 */ userp[pos]->zero_cross[i] = 0; /* ゼロクロス位置処理法:0=平均 */ userp[pos]->edge_level[i] = 10; /* エッジ検出しきい値:10 */ userp[pos]->retry[i] = 0; /* 再計測スイッチ:off */ userp[pos]->eliminate_pos[i] = 5; /* 再計測時の排除距離点:5画素 */ userp[pos]->scan_type[i] = 0; /* エッジ抽出法:ライブラリ */ userp[pos]->org_direction[i] = 0; /* 抽出方向:左→右、上→下 */ userp[pos]->org_level_type[i] = 0; /* 抽出レベル:固定 */ } userp[pos]->pm_multiplier = 1.0; /* 画素→μ変換乗数 */ userp[pos]->box_dispray = 1; /* エッジ抽出枠表示スイッチ :ON */ userp[pos]->scan_line_display = 1; /* 走査線表示スイッチ    :ON */ userp[pos]->edge_display = 1; /* エッジ検出位置表示スイッチ:ON */ userp[pos]->calc_line_display = 1; /* 近似直線表示スイッチ   :ON */ } } current_position = 0; /* 対象品種の初期(デフォルト値)は "0" */ Lib_change_gray_memory( 0 ); /* 濃淡画像のカレントメモリを 0 に設定 */ gray_mem_base_adr = (unsigned char *)Lib_adrs_gray_memory( 0 ); /* 0メモリの先頭アドレス */ return( 0 ); /* 正常終了 */ } /**************************************************************/ /*  終了処理                   */ /**************************************************************/ void prog_Close() { Lib_lfree( (char *)userp[0] ); /* メモリの解放 */ Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); /* 文字、線画メモリをクリア */ } /**************************************************************/ /**** パラメータ設定(メイン) ********************************/ /**************************************************************/ void Parameter_set() { char disp_buff[5]; int pad_level, w, h, no; Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); Lib_get_standard_key_size( &w, &h ); for(;;) { pad_level = Lib_view_open(); Lib_view_set_title( pad_level, "設定" ); Lib_view_set_null( pad_level, 5, 5, "対象画像", 0 ); Lib_view_set_null( pad_level, 5, 35, "エッジ抽出枠", 1 ); Lib_view_set_null( pad_level, 5, 65, "抽出条件", 2 ); Lib_view_set_null( pad_level, 5, 95, "キャリブレーション", 3 ); Lib_view_set_null( pad_level, 5, 125, "表\示関連", 4 ); Lib_view_set_null( pad_level, 5, 155, "セーブ", 5 ); Lib_sprintf( disp_buff, "%02d", current_position ); Lib_view_set_comment( pad_level, w + 10, 5, disp_buff, 6 ); Lib_view_set_size( pad_level, 15, 15, 5, 5 ); Lib_draw_command( pad_level ); for(;;) { no = Lib_process_command( pad_level ); switch( no ) { case 0: P_position(); break; case 1: P_box(); break; case 2: P_article(); break; case 3: P_calib(); break; case 4: P_other(); break; case 5: P_save(); break; } if( 0 == no ) break; if( PAD_QUIT == no ) break; } Lib_erase_command( pad_level ); Lib_view_close( pad_level ); if( PAD_QUIT == no ) break; } } /**********************************************/ /*     計測対象とする品種の設定     */ /**********************************************/ void P_position( void ) { char *graphic_data_buffer; /* グラフィック メモリ データ退避エリア */ graphic_data_buffer = Lib_mlalloc( GRAPHIC_DATA_SIZE ); Lib_get( 0, 0, 511, 479, CHAR_PLANE, graphic_data_buffer ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); current_position = (int)Lib_get_value_by_ten_keyboad( 50, 100, (long)current_position, 0L, (long)MAX_KIND - 1 ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); Lib_put( graphic_data_buffer ); Lib_lfree( graphic_data_buffer ); } /**************************************************************/ /*  BOX(エッジ抽出範囲)の設定              */ /**************************************************************/ void P_box( void ) { char *graphic_data_buffer; /* グラフィック メモリ データ退避エリア */ int i, x, y, w, h, ch; graphic_data_buffer = Lib_mlalloc( GRAPHIC_DATA_SIZE ); Lib_get( 0, 0, 511, 479, CHAR_PLANE, graphic_data_buffer ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); ch = current_position; Lib_get_key_size( 4, &w, &h ); /* キーの表示サイズを得る */ for( ; ; ) { Lib_display_key( 0, 0, "登録", 1 ); Lib_display_key( 511 - w, 0, "変更", 1 ); Lib_display_key( 0, 479 - h, "消去", 1 ); Lib_display_key( 511 - w, 479 - h, "終了", 1 ); for( i = 0; i < userp[ch]->box_no; i++ ) Lib_box( userp[ch]->xs[i], userp[ch]->ys[i], userp[ch]->xe[i], userp[ch]->ye[i], SOLID_LINE ); if( CURSOR_EXECUTE == Lib_get_current_position( &x, &y ) ) { if( 0 <= x && x <= w && 0 <= y && y <= h ) { /* [登録]がクリックされたらBOXの登録 */ Lib_display_key( 0, 0, "登録", 2 ); box_set( userp[ch]->box_no ); } if( 511 - w <= x && x <= 511 && 0 <= y && y <= h ) { /* [変更]がクリックされたらBOXサイズの変更 */ Lib_display_key( 511 - w, 0, "変更", 2 ); Lib_memory_clear( CHAR_PLANE ); Lib_display_comment( 0, 0, "BOXサイズの変更" ); Lib_chrdisp( 1, 29, "矢印カーサを変更したい枠の中に移動し左[EXECUTE]キーをクリック。" ); Lib_chrdisp( 1, 30, "何もせずに戻る場合は右[CANCEL]キーをクリック。" ); for(;;) { if( CURSOR_CANCEL == Lib_get_current_position( &x, &y ) ) { Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); break; } for( i = 0; i < userp[ch]->box_no; i++ ) { if( userp[ch]->xs[i] < x && x < userp[ch]->xe[i] && userp[ch]->ys[i] < y && y < userp[ch]->ye[i] ) { box_set( i ); break; } } if( i < userp[ch]->box_no ) break; } } if( 0 <= x && x <= w && 479 - h <= y && y <= 479 ) { /* [消去]がクリックされたらBOXの全消去 */ Lib_display_key( 0, 479 - h, "消去", 2 ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); userp[ch]->box_no = 0; } if( 511 - w <= x && x <= 511 && 479 - h <= y && y <= 479 ) { /* [終了]がクリックされたらメインメニューに戻る */ Lib_display_key( 511 - w, 479 - h, "終了", 2 ); break; } } } Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); Lib_put( graphic_data_buffer ); Lib_lfree( graphic_data_buffer ); } /********** BOX生成サブルーチン **********/ void box_set( int no ) { int x_start, y_start, x_size, y_size; int pad_level, ch; static PVAL value[2]; ch = current_position; if( MAX_BOX <= no ) { Lib_invdisp( 2, 10, "ERROR:これ以上の登録は出来ません。" ); Lib_time_delay( 2000 ); Lib_chrdisp( 2, 10, " " ); return; } Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); pad_level = Lib_view_open(); Lib_view_set_title( pad_level, "エッジ抽出範囲" ); x_start = userp[ch]->xs[ no ]; y_start = userp[ch]->ys[ no ]; x_size = userp[ch]->xe[ no ] - userp[ch]->xs[ no ] + 1; y_size = userp[ch]->ye[ no ] - userp[ch]->ys[ no ] + 1; Lib_view_set_box( pad_level, 5, 5,"始点", x_start, y_start, 3,1,0 ); Lib_view_set_box( pad_level, 5,35,"サイズ", x_size, y_size, 3,0,1 ); Lib_view_set_size( pad_level, 5, 5, 8, 5 ); Lib_draw_menu( pad_level ); if( PAD_EXECUTE == Lib_process_menu( pad_level, value ) ) { userp[ch]->xs[ no ] = value[0].box_type.x; userp[ch]->ys[ no ] = value[0].box_type.y; userp[ch]->xe[ no ] = value[0].box_type.x + value[1].box_type.x - 1; userp[ch]->ye[ no ] = value[0].box_type.y + value[1].box_type.y - 1; /* no と userp[ch]->box_no が同値なら[登録]なので userp[ch]->box_no をインクリメントしておく */ if( no == userp[ch]->box_no ) userp[ch]->box_no++; } Lib_erase_menu( pad_level ); Lib_view_close( pad_level ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); } /**************************************************************/ /*  エッジ抽出条件群の設定               */ /**************************************************************/ void P_article() { char *graphic_data_buffer; /* グラフィック メモリ データ退避エリア */ int i, x, y, ch; graphic_data_buffer = Lib_mlalloc( GRAPHIC_DATA_SIZE ); Lib_get( 0, 0, 511, 479, CHAR_PLANE, graphic_data_buffer ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); ch = current_position; if( 0 == userp[ch]->box_no ) { Lib_invdisp( 2, 10, "ERROR:エッジ抽出枠が登録されていません" ); Lib_time_delay( 2000 ); Lib_chrdisp( 2, 10, " " ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); Lib_put( graphic_data_buffer ); Lib_lfree( graphic_data_buffer ); return; } for(;;) { for( i = 0; i < userp[ch]->box_no; i++ ) Lib_box( userp[ch]->xs[i], userp[ch]->ys[i], userp[ch]->xe[i], userp[ch]->ye[i], SOLID_LINE ); Lib_display_comment( 0, 0, "エッジ抽出条件の設定" ); Lib_chrdisp( 1, 29, "矢印カーサを設定したい枠の中に移動し左[EXECUTE]キーをクリック。" ); Lib_chrdisp( 1, 30, "この設定モードを抜け出す場合は右[CANCEL]キーをクリック。" ); if( CURSOR_CANCEL == Lib_get_current_position( &x, &y ) ) break; for( i = 0; i < userp[ch]->box_no; i++ ) { if( userp[ch]->xs[i] < x && x < userp[ch]->xe[i] && userp[ch]->ys[i] < y && y < userp[ch]->ye[i] ) article_set( i ); } } Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); Lib_put( graphic_data_buffer ); Lib_lfree( graphic_data_buffer ); } /********** エッジ抽出条件サブルーチン **********/ void article_set( int no ) { int ch; int pad_level; static char *select_scan[2]={"横(X)方向","縦(Y)方向"}; static char *select_cross[2]={"平均処理","生データ"}; static char *select_type[2]={"ライブラリ","オリジナル"}; static char *select_direction[2]={"左>右・上>下","右>左・下>上"}; static char *select_level[2]={"固定値","百分率"}; static PVAL value[11]; Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); ch = current_position; current_box_no = no; Lib_box( userp[ch]->xs[no], userp[ch]->ys[no], userp[ch]->xe[no], userp[ch]->ye[no], SOLID_LINE ); pad_level = Lib_view_open(); Lib_view_set_title( pad_level, "エッジ抽出条件" ); Lib_view_set_select( pad_level, 5, 5, "走査線方向", userp[ch]->scan_vh[no], 2, select_scan, 0 ); Lib_view_set_uniq_numeral( pad_level, 5, 35, "走査線間隔", (long)userp[ch]->pitch[no], 2L, 100L, 1 ); Lib_view_set_select( pad_level, 5, 65, "エッジ検出法", userp[ch]->scan_type[no], 2, select_type, 2 ); Lib_view_set_comment( pad_level, 5, 95, "ライブラリ使用の場合", 3 ); Lib_view_set_select( pad_level, 25,125, "ゼロクロス処理", userp[ch]->zero_cross[no], 2, select_cross, 4 ); Lib_view_set_comment( pad_level, 5,155, "オリジナル方法の場合", 5 ); Lib_view_set_select( pad_level, 25,185, "走査の向き", userp[ch]->org_direction[no], 2, select_direction, 6 ); Lib_view_set_select( pad_level, 25,215, "濃度決定法", userp[ch]->org_level_type[no], 2, select_level, 7 ); Lib_view_set_uniq_numeral( pad_level, 5, 245, "しきい値", (long)userp[ch]->edge_level[no], 0L, 255L, 8 ); Lib_view_set_uniq_alter( pad_level, 5, 275, "再計測", userp[ch]->retry[no], 9 ); Lib_view_set_uniq_numeral( pad_level, 5, 305, "排除距離点", (long)userp[ch]->eliminate_pos[no], 0L, 50L, 10 ); Lib_set_paradigm( pad_level, 0, END_TIMING, scan_set ); Lib_set_paradigm( pad_level, 1, WHOLE_TIMING, pitch_set ); Lib_view_set_size( pad_level, 15, 15, 8, 5 ); Lib_draw_menu( pad_level ); if( PAD_EXECUTE == Lib_process_menu( pad_level, value ) ) { userp[ch]->scan_type[no] = value[2].select_type; userp[ch]->zero_cross[no] = value[4].select_type; userp[ch]->org_direction[no] = value[6].select_type; userp[ch]->org_level_type[no]= value[7].select_type; userp[ch]->edge_level[no] = (int)value[8].value_type; userp[ch]->retry[no] = value[9].on_off_type; userp[ch]->eliminate_pos[no] = (int)value[10].value_type; if( ORG_SCAN == userp[ch]->scan_type[no] && PERCENT_LEVEL == userp[ch]->org_level_type[no] && 100 < userp[ch]->edge_level[no] ) userp[ch]->edge_level[no] = 100; } Lib_erase_menu( pad_level ); Lib_view_close( pad_level ); } /*--------- 走査方向の設定( パラダイム ) ---------*/ void scan_set( int timing, int no, PARADIGM val[] ) { userp[current_position]->scan_vh[current_box_no] = val[0].int_type; } /*--------- 走査線間隔の設定( パラダイム ) ---------*/ void pitch_set( int timing, int no, PARADIGM val[] ) { int ch, box, x, y, xs, ys, xe, ye, pitch; ch = current_position; box = current_box_no; xs = userp[ch]->xs[box]; ys = userp[ch]->ys[box]; xe = userp[ch]->xe[box]; ye = userp[ch]->ye[box]; pitch = (int)val[0].long_type; switch( timing ) { case START_TIMING: Lib_box( xs, ys, xe, ye, SOLID_LINE ); if( 0 == userp[ch]->scan_vh[box] ) { /* 横方向走査線表示 */ for( y = ys + pitch; y < ye; y += pitch ) Lib_drawline( xs, y, xe, y ); } else { /* 縦方向走査線表示 */ for( x = xs + pitch; x < xe; x += pitch ) Lib_drawline( x, ys, x, ye ); } break; case PROCESS_TIMING: Lib_memory_clear( LINE_PLANE ); Lib_box( xs, ys, xe, ye, SOLID_LINE ); if( 0 == userp[ch]->scan_vh[box] ) { /* 横方向走査線表示 */ for( y = ys + pitch; y < ye; y += pitch ) Lib_drawline( xs, y, xe, y ); } else { /* 縦方向走査線表示 */ for( x = xs + pitch; x < xe; x += pitch ) Lib_drawline( x, ys, x, ye ); } break; case END_TIMING: Lib_memory_clear( LINE_PLANE ); userp[ch]->pitch[box] = pitch; break; } } /**************************************************************/ /*  画素→μ変換乗数生成          */ /**************************************************************/ void P_calib() { static char *graphic_data_buffer; /* グラフィック メモリ データ退避エリア */ static char disp_buff[64]; static int x, y, xs, ys, xe, ye, key, old_x, old_y; static double in_data, length; graphic_data_buffer = Lib_mlalloc( GRAPHIC_DATA_SIZE ); Lib_get( 0, 0, 511, 479, CHAR_PLANE, graphic_data_buffer ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); for(;;) { Lib_display_comment( 0, 0, "適当な位置に始点(矢印カーサ)を置き、左キーをクリック" ); Lib_chrdisp( 1, 30, "ここで右キーをクリックすると中止" ); Lib_draw_cursor( 256, 240 ); key = Lib_get_current_position( &xs, &ys ) ; if( key == CURSOR_CANCEL ) { Lib_chrdisp( 10, 10, "通知 : 設定を中止します。" ); Lib_time_delay( 1000 ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); Lib_put( graphic_data_buffer ); Lib_lfree( graphic_data_buffer ); return; } Lib_chrdisp( 1, 30, "                " ); Lib_memory_clear( CHAR_PLANE ); Lib_display_comment( 170, 0, "終点位置まで直線を引き、左キーをクリック" ); Lib_erase_cursor(); xe = xs + 2; ye = ys + 2; old_x = xe; old_y = ye; for( key = 0; key != CURSOR_EXECUTE; ) { Lib_drawline( xs, ys, xe, ye ); key = Lib_see_current_position( &xe, &ye ); if( old_x != xe || old_y != ye ) { Lib_erasline( xs, ys, old_x, old_y ); old_x = xe; old_y = ye; } } Lib_drawline( xs, ys, xe, ye ); /* 数値データ入力 */ Lib_memory_clear( CHAR_PLANE ); Lib_display_comment( 0, 0, "設定した直線の長さは何μに相当するのかを入力" ); in_data = (double)Lib_get_value_by_ten_keyboad( 50, 100, 1L, 1L, 50000L ); length = (double)Lib_sqrt32( ((xs-xe) * (xs-xe)) + ((ys-ye) * (ys-ye)) ); length = in_data / length; Lib_memory_clear( CHAR_PLANE ); Lib_sprintf( disp_buff, "【1画素は %.5lfμ に相当しています】", length ); Lib_chrdisp( 10, 6, disp_buff ); Lib_display_comment( 0, 0, "良ければ左(EXECUTE)キーを、やり直しなら右(CANCEL)キーをクリック" ); key = Lib_get_current_position( &x, &y ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); if( key == CURSOR_EXECUTE ) break; } Lib_put( graphic_data_buffer ); Lib_lfree( graphic_data_buffer ); Lib_draw_cursor( 256, 240 ); userp[0]->pm_multiplier = length; userp[1]->pm_multiplier = length; } /**************************************************************/ /*  表示関連の設定          */ /**************************************************************/ void P_other() { char *graphic_data_buffer; /* グラフィック メモリ データ退避エリア */ int pad_level; static PVAL value[4]; graphic_data_buffer = Lib_mlalloc( GRAPHIC_DATA_SIZE ); Lib_get( 0, 0, 511, 479, CHAR_PLANE, graphic_data_buffer ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); pad_level = Lib_view_open(); Lib_view_set_title( pad_level, "表\示の設定" ); Lib_view_set_uniq_alter( pad_level, 15, 5, "エッジ抽出枠", userp[0]->box_dispray, 0 ); Lib_view_set_uniq_alter( pad_level, 15, 35, "走査線", userp[0]->scan_line_display, 1 ); Lib_view_set_uniq_alter( pad_level, 15, 65, "エッジ座標点", userp[0]->edge_display, 2 ); Lib_view_set_uniq_alter( pad_level, 15, 95, "近似直線", userp[0]->calc_line_display, 3 ); Lib_view_set_size( pad_level, 15, 15, 40, 5 ); Lib_draw_menu( pad_level ); if( PAD_EXECUTE == Lib_process_menu( pad_level, value ) ) { userp[0]->box_dispray = userp[1]->box_dispray = value[0].on_off_type; userp[0]->scan_line_display = userp[1]->scan_line_display = value[1].on_off_type; userp[0]->edge_display = userp[1]->edge_display = value[2].on_off_type; userp[0]->calc_line_display = userp[1]->calc_line_display = value[3].on_off_type; } Lib_erase_menu( pad_level ); Lib_view_close( pad_level ); Lib_put( graphic_data_buffer ); Lib_lfree( graphic_data_buffer ); } /**************************************************************/ /*  データ・セーブ                */ /**************************************************************/ void P_save() { char *graphic_data_buffer; /* グラフィック メモリ データ退避エリア */ long size; Lib_erase_cursor(); graphic_data_buffer = Lib_mlalloc( GRAPHIC_DATA_SIZE ); Lib_get( 0, 0, 511, 479, CHAR_PLANE, graphic_data_buffer ); Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); Lib_display_comment( 100, 200, "全ての設定データをセーブ中・・・・・" ); size = (long)sizeof( struct SAVE_DATA ); if( 0L == Lib_fsave( "\\FS0\\MENTORI.DAT", (char *)userp[0], size * MAX_KIND ) ) { Lib_memory_clear( CHAR_PLANE ); Lib_invdisp( 2, 10, "ERROR:設定パラメータ類がPCカードに保存できません。" ); Lib_time_delay( 5000 ); } Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); Lib_put( graphic_data_buffer ); Lib_lfree( graphic_data_buffer ); Lib_draw_cursor( 256, 240 ); } /**************************************************************/ /**** 計測実行 ************************************************/ /**************************************************************/ void Execute( int mode ) { int ch; int i, j, k, m, x, y, xs, ys, xe, ye, px, py, pitch; int status, edge_cnt, ok, ng; int h_index[2], v_index[2]; int angle, cxi, cyi, xs1, ys1, xe1, ye1, xs2, ys2, xe2, ye2; static int adr_work1[20][2], adr_work2[20][2]; static POINT edge_data[256]; static LINE coeff; double a[MAX_BOX], b[MAX_BOX], c[MAX_BOX]; /* 近似直線a,b,cの各係数 */ double a1, b1, c1, a2, b2, c2; /* 交点計算ワーク */ double sqrt_ab, edge_distance; double cross_x[MAX_BOX], cross_y[MAX_BOX], center_x, center_y; double length, width, ans_distance[4]; double x1, y1, x2, y2; double d_work1, d_work2; static char disp_buff[64]; static char out_buff[128]; static int address_table[512][2]; static int gray_data_table[520]; int boundary_data[2]; int point, pct_level; if( TRY == mode ) Lib_strtclk_count(); /* 処理時間計測スタート */ Lib_freeze( TRANSMIT ); /* 画面フリーズ */ ch = current_position; /* CH0側パラメータあるいはCH1側パラメータのインデックス取り出し */ Lib_memory_clear( LINE_PLANE | CHAR_PLANE ); /* 画面をクリア */ if( ON == userp[ch]->box_dispray ) /* エッジ抽出枠表示? */ for( i = 0; i < userp[ch]->box_no; i++ ) Lib_box( userp[ch]->xs[i], userp[ch]->ys[i], userp[ch]->xe[i], userp[ch]->ye[i], SOLID_LINE ); if( ON == userp[ch]->scan_line_display ) /* エッジ抽出枠内の走査線群表示? */ { for( i = 0; i < userp[ch]->box_no; i++ ) { xs = userp[ch]->xs[i]; ys = userp[ch]->ys[i]; xe = userp[ch]->xe[i]; ye = userp[ch]->ye[i]; pitch = userp[ch]->pitch[i]; if( 0 == userp[ch]->scan_vh[i] ) { /* 横方向走査線表示 */ for( y = ys; y < ye; y += pitch ) Lib_drawline( xs, y, xe, y ); Lib_drawline( xs, ye, xe, ye ); } else { /* 縦方向走査線表示 */ for( x = xs; x < xe; x += pitch ) Lib_drawline( x, ys, x, ye ); Lib_drawline( xe, ys, xe, ye ); } } } ok = ng = 0; /***** 全箇所の近似直線を計測 *****/ for( i = 0; i < userp[ch]->box_no; i++ ) { xs = userp[ch]->xs[i]; ys = userp[ch]->ys[i]; xe = userp[ch]->xe[i]; ye = userp[ch]->ye[i]; if( LIB_SCAN == userp[ch]->scan_type[i] ) { /* ◆◆◆◆ ライブラリを使用したエッジの抽出 ◆◆◆◆ */ pitch = userp[ch]->pitch[i]; j = 0; if( HORIZONTAL_SCAN == userp[ch]->scan_vh[i] ) { /* 横方向走査 */ for( y = ys; y < ye; y += pitch ) { status = Lib_edge_pos_xy( xs, y, xe, y, userp[ch]->zero_cross[i], userp[ch]->edge_level[i], 0, &px, &py ); if( NORMAL_RETURN == status ) { if( ON == userp[ch]->edge_display ) /* エッジ位置表示? */ Lib_drawline( px / 16, py / 16 - 1, px / 16, py / 16 + 1 ); edge_data[j].x = ( px * 10 ) / 16; edge_data[j].y = ( py * 10 ) / 16; j++; } } if( 2 < ye - ( y - pitch ) ) /* BOXの終端とその直前の走査線の間に3画素以上の間隔があるか? */ { /* あればBOXの終端位置(枠線下)のエッジも抽出する。 */ status = Lib_edge_pos_xy( xs, ye, xe, ye, userp[ch]->zero_cross[i], userp[ch]->edge_level[i], 0, &px, &py ); if( NORMAL_RETURN == status ) { if( ON == userp[ch]->edge_display ) /* エッジ位置表示? */ Lib_drawline( px / 16, py / 16 - 1, px / 16, py / 16 + 1 ); edge_data[j].x = ( px * 10 ) / 16; edge_data[j].y = ( py * 10 ) / 16; j++; } } } else { /* 縦方向走査線表示 */ for( x = xs; x < xe; x += pitch ) { status = Lib_edge_pos_xy( x, ys, x, ye, userp[ch]->zero_cross[i], userp[ch]->edge_level[i], 0, &px, &py ); if( NORMAL_RETURN == status ) { if( ON == userp[ch]->edge_display ) /* エッジ位置表示? */ Lib_drawline( px / 16 - 1, py / 16, px / 16 + 1, py / 16 ); edge_data[j].x = ( px * 10 ) / 16; edge_data[j].y = ( py * 10 ) / 16; j++; } } if( 2 < xe - ( x - pitch ) ) /* BOXの終端とその直前の走査線の間に3画素以上の間隔があるか? */ { /* あればBOXの終端位置(枠線下)のエッジも抽出する。 */ status = Lib_edge_pos_xy( xe, ys, xe, ye, userp[ch]->zero_cross[i], userp[ch]->edge_level[i], 0, &px, &py ); if( NORMAL_RETURN == status ) { if( ON == userp[ch]->edge_display ) /* エッジ位置表示? */ Lib_drawline( px / 16 - 1, py / 16, px / 16 + 1, py / 16 ); edge_data[j].x = ( px * 10 ) / 16; edge_data[j].y = ( py * 10 ) / 16; j++; } } } edge_cnt = j; /* 抽出できたエッジ点数 */ } else { /* ◆◆◆◆ オリジナル方式によるエッジ検出 ◆◆◆◆ */ pitch = userp[ch]->pitch[i]; j = 0; if( HORIZONTAL_SCAN == userp[ch]->scan_vh[i] ) { /* 横方向走査 */ for( y = ys; y < ye; y += pitch ) { if( H_LEFT_TO_RIGHT == userp[ch]->org_direction[i] ) /* 左から右へ走査して濃度データを抽出する */ point = get_gray_data( xs, y, xe, y, gray_data_table, (int *)address_table ); else /* 右から左へ走査して濃度データを抽出する */ point = get_gray_data( xe, y, xs, y, gray_data_table, (int *)address_table ); if( ABS_LEVEL == userp[ch]->org_level_type[i] ) /* 濃度エッジは固定レベル(明から暗に変わる変化点。2画素以下はノイズと見なす) */ light_to_dark_border( userp[ch]->edge_level[i], 2, point, gray_data_table, (int *)address_table, boundary_data ); else { /* 濃度エッジは百分率レベル(明から暗に変わる変化点。2画素以下はノイズと見なす) */ pct_level = gray_data_table[point] - gray_data_table[point+1]; pct_level = pct_level * userp[ch]->edge_level[i] / 100 + gray_data_table[point+1]; light_to_dark_border( pct_level, 2, point, gray_data_table, (int *)address_table, boundary_data ); } if( -1 != boundary_data[0] && -1 != boundary_data[1] ) { if( ON == userp[ch]->edge_display ) /* エッジ位置表示? */ Lib_drawline( boundary_data[0], boundary_data[1] - 1, boundary_data[0], boundary_data[1] + 1 ); edge_data[j].x = boundary_data[0] * 10; edge_data[j].y = boundary_data[1] * 10; j++; } } } else { /* 縦方向走査線表示 */ for( x = xs; x < xe; x += pitch ) { if( V_HIGH_TO_LOW == userp[ch]->org_direction[i] ) /* 上から下へ走査して濃度データを抽出する */ point = get_gray_data( x, ys, x, ye, gray_data_table, (int *)address_table ); else /* 下から上へ走査して濃度データを抽出する */ point = get_gray_data( x, ye, x, ys, gray_data_table, (int *)address_table ); if( ABS_LEVEL == userp[ch]->org_level_type[i] ) /* 濃度エッジは固定レベル(明から暗に変わる変化点。2画素以下はノイズと見なす) */ light_to_dark_border( userp[ch]->edge_level[i], 2, point, gray_data_table, (int *)address_table, boundary_data ); else { /* 濃度エッジは百分率レベル(明から暗に変わる変化点。2画素以下はノイズと見なす) */ pct_level = gray_data_table[point] - gray_data_table[point+1]; pct_level = pct_level * userp[ch]->edge_level[i] / 100 + gray_data_table[point+1]; light_to_dark_border( pct_level, 2, point, gray_data_table, (int *)address_table, boundary_data ); } if( -1 != boundary_data[0] && -1 != boundary_data[1] ) { if( ON == userp[ch]->edge_display ) /* エッジ位置表示? */ Lib_drawline( boundary_data[0], boundary_data[1] - 1, boundary_data[0], boundary_data[1] + 1 ); edge_data[j].x = boundary_data[0] * 10; edge_data[j].y = boundary_data[1] * 10; j++; } } } edge_cnt = j; /* 抽出できたエッジ点数 */ } /***** 直線近似 *****/ if( 2 <= edge_cnt ) /* エッジ点は2点以上抽出できた? */ { status = Lib_calcline( edge_cnt, edge_data, &coeff ); /* 直線近似 */ if( NORMAL_RETURN == status ) { a[i] = (double)coeff.a / 65536.0; /* それぞれの係数a,b,cを取り出す */ b[i] = (double)coeff.b / 65536.0; c[i] = (double)coeff.c / 16.0; if( ON == userp[ch]->retry[i] ) /* 再計測? */ { sqrt_ab = sqrt( ( a[i] * a[i] ) + ( b[i] * b[i] ) ); for( j = k = 0; j < edge_cnt; j++ ) { /* 近似直線から見た各エッジ点の距離を求める */ edge_distance = fabs( ( a[i] * (double)edge_data[j].x ) + ( b[i] * (double)edge_data[j].y ) + c[i] ) / sqrt_ab; if( abs( (int)edge_distance / 10 ) < userp[ch]->eliminate_pos[i] ) /* 距離は許容範囲内? */ { edge_data[k].x = edge_data[j].x; edge_data[k].y = edge_data[j].y; k++; } } if( 2 <= k ) /* 2点以上残った? */ { edge_cnt = k; status = Lib_calcline( edge_cnt, edge_data, &coeff ); /* 直線近似 */ if( NORMAL_RETURN == status ) { a[i] = (double)coeff.a / 65536.0; /* それぞれの係数a,b,cを取り出す。*/ b[i] = (double)coeff.b / 65536.0; /* 再計測指定の場合は、これが最終 */ c[i] = (double)coeff.c / 16.0; /* 的な直線係数となる。 */ } else { Lib_sprintf( disp_buff, "ERROR:%1番目枠内の2回目の直線計算で不正処理発生", i+1 ); Lib_invdisp( 1, 30, disp_buff ); ng = 1; break; } } else { Lib_sprintf( disp_buff, "ERROR:%1番目枠内の再計測用エッジ点数が2点未満", i+1 ); Lib_invdisp( 1, 30, disp_buff ); ng = 1; break; } } if( ON == userp[ch]->calc_line_display ) /* 近似直線表示? */ { if( 0 == userp[ch]->scan_vh[i] ) { /* 横方向走査なら縦線描画 */ xs = (int)(( -b[i] * (double)ys * 10.0 - c[i] ) / a[i] ); xe = (int)(( -b[i] * (double)ye * 10.0 - c[i] ) / a[i] ); Lib_drawline( xs / 10, ys, xe / 10, ye ); /* 直線表示 */ } else { /* 縦方向走査なら横線描画 */ ys = (int)(( -a[i] * (double)xs * 10.0 - c[i] ) / b[i] ); ye = (int)(( -a[i] * (double)xe * 10.0 - c[i] ) / b[i] ); Lib_drawline( xs, ys / 10, xe, ye / 10 ); /* 直線表示 */ } } } else { Lib_sprintf( disp_buff, "ERROR:%1番目枠内の直線計算で不正処理発生", i+1 ); Lib_invdisp( 1, 30, disp_buff ); ng = 1; break; } } else { Lib_sprintf( disp_buff, "ERROR:%1番目枠内のエッジ抽出が2点未満", i+1 ); Lib_invdisp( 1, 30, disp_buff ); ng = 1; break; } } if( 0 == ng ) { /******* 縦線と横線がどのBOXかを見極める *******/ for( i = j = k = 0; i < MAX_BOX; i++ ) { if( HORIZONTAL_SCAN == userp[ch]->scan_vh[i] ) { h_index[j] = i; /* 横線 */ j++; } else { v_index[k] = i; /* 縦線 */ k++; } } /******* 各交点を求める *******/ for( i = j = 0; j < 2; j++ ) { a1 = a[ h_index[j] ]; b1 = b[ h_index[j] ]; c1 = c[ h_index[j] ]; for( k = 0; k < 2; k++ ) { a2 = a[ v_index[k] ]; b2 = b[ v_index[k] ]; c2 = c[ v_index[k] ]; if( 0.0 != ( a1 * b2 - a2 * b1 ) ) { cross_x[i] = (( -c1 * b2 ) - ( -c2 * b1 )) / (( a1 * b2 ) - ( a2 * b1 )); cross_y[i] = (( a1 * -c2 ) - ( a2 * -c1 )) / (( a1 * b2 ) - ( a2 * b1 )); cross_x[i] /= 10; /* ここまで値は全て10倍値で計測されて */ cross_y[i] /= 10; /* 来ているので、ここらで1/10しておく。*/ Lib_drawcircle( (int)cross_x[i], (int)cross_y[i], 2 ); i++; } else { /* 不定 or 不能 */ ng = 1; break; } } if( 0 != ng ) break; } } if( 0 == ng ) { /******* 求めた交点位置をチェック *******/ for( i = 0; i < MAX_BOX; i++ ) { if( cross_x[i] < 0.0 || 511.0 < cross_x[i] || cross_y[i] < 0.0 || 479.0 < cross_y[i] ) { /* 値が処理領域の範囲外に在り、不正 */ ng = 1; break; } } } if( 0 == ng ) { /***** 中心位置を求める *****/ center_x = center_y = 0; for( i = 0; i < MAX_BOX; i++ ) { center_x += cross_x[i]; center_y += cross_y[i]; } center_x /= 4; center_y /= 4; /***** 中心座標に+マークを表示 *****/ DRAWLIN( (int)center_x - 10, (int)center_y, (int)center_x + 10, (int)center_y ); DRAWLIN( (int)center_x, (int)center_y - 10, (int)center_x, (int)center_y + 10 ); /***** 4交点にも(1)〜(4)の番号を表示 *****/ for( i = 0; i < MAX_BOX; i++ ) { Lib_sprintf( disp_buff, "(%d)", i + 1 ); x = (int)( center_x + cross_x[i] ) / 2; y = (int)( center_y + cross_y[i] ) / 2; Lib_kanjishift( NORMAL_FONT, NORMAL_FONT, 0, x, y, disp_buff ); } /***** パッケージの長さと幅を求める *****/ x1 = ( cross_x[0] + cross_x[1] ) / 2; y1 = ( cross_y[0] + cross_y[1] ) / 2; x2 = ( cross_x[2] + cross_x[3] ) / 2; y2 = ( cross_y[2] + cross_y[3] ) / 2; d_work1 = sqrt( (( x1 - x2 ) * ( x1 - x2 )) + (( y1 - y2 ) * ( y1 - y2 )) ); Lib_line( (int)x1, (int)y1, (int)x2, (int)y2, DOTTED_LINE ); x1 = ( cross_x[0] + cross_x[2] ) / 2; y1 = ( cross_y[0] + cross_y[2] ) / 2; x2 = ( cross_x[1] + cross_x[3] ) / 2; y2 = ( cross_y[1] + cross_y[3] ) / 2; d_work2 = sqrt( (( x1 - x2 ) * ( x1 - x2 )) + (( y1 - y2 ) * ( y1 - y2 )) ); Lib_line( (int)x1, (int)y1, (int)x2, (int)y2, DOTTED_LINE ); if( d_work1 > d_work2 ) { length = d_work1; width = d_work2; } else { length = d_work2; width = d_work1; } length *= userp[ch]->pm_multiplier; width *= userp[ch]->pm_multiplier; Lib_sprintf( disp_buff, "長さ=%.3lfmm", length / 1000.0 ); Lib_chrdisp( 1, 3, disp_buff ); Lib_sprintf( disp_buff, " 幅=%.3lfmm", width / 1000.0 ); Lib_chrdisp( 1, 4, disp_buff ); } if( 0 == ng ) { /***** 中心位置データを cxi,cyi に持ってくる *****/ cxi = (int)center_x; cyi = (int)center_y; /***** 4つの交点位置全部について行う *****/ for( i = 0; i < 4; i++ ) { /***** 交点から外側に10画素離れた位置を得る *****/ x = (int)cross_x[i]; y = (int)cross_y[i]; angle = Lib_atan360( x - cxi, cyi - y ); xs = Lib_cosfunc( angle ); ys = Lib_sinfunc( angle ); xs = ( 10 * xs ) / 32767; ys = ( 10 * ys ) / 32767; x = x + xs; y = y - ys; /***** 中心に向かう角度に対して90゚方向に、両翼4画素離れた位置を得る *****/ xs = Lib_cosfunc( angle + 900 ); ys = Lib_sinfunc( angle + 900 ); xe = Lib_cosfunc( angle - 900 ); ye = Lib_sinfunc( angle - 900 ); xs = ( 4 * xs ) / 32767; ys = ( 4 * ys ) / 32767; xe = ( 4 * xe ) / 32767; ye = ( 4 * ye ) / 32767; xs1 = x + xs; ys1 = y - ys; xe1 = x + xe; ye1 = y - ye; Lib_drawline( xs1, ys1, xe1, ye1 ); point = get_adr_data( xs1, ys1, xe1, ye1, (int *)adr_work1 ); /***** 交点から内側に30画素離れた位置を得る *****/ x = (int)cross_x[i]; y = (int)cross_y[i]; angle = Lib_atan360( cxi - x, y - cyi ); xs = Lib_cosfunc( angle ); ys = Lib_sinfunc( angle ); xs = ( MENTORI_ED_LINE_LIMIT * xs ) / 32767; ys = ( MENTORI_ED_LINE_LIMIT * ys ) / 32767; x = x + xs; y = y - ys; /***** 中心に向かう角度に対して90゚方向に、両翼4画素離れた位置を得る *****/ xs = Lib_cosfunc( angle + 900 ); ys = Lib_sinfunc( angle + 900 ); xe = Lib_cosfunc( angle - 900 ); ye = Lib_sinfunc( angle - 900 ); xs = ( 4 * xs ) / 32767; ys = ( 4 * ys ) / 32767; xe = ( 4 * xe ) / 32767; ye = ( 4 * ye ) / 32767; xe2 = x + xs; ye2 = y - ys; xs2 = x + xe; ys2 = y - ye; Lib_drawline( xs2, ys2, xe2, ye2 ); get_adr_data( xs2, ys2, xe2, ye2, (int *)adr_work2 ); /***** 枠表示を完成させる *****/ Lib_drawline( xs1, ys1, xs2, ys2 ); Lib_drawline( xe1, ye1, xe2, ye2 ); /***** エッジ抽出 *****/ if( LIB_SCAN == userp[ch]->scan_type[i] ) { /* ◆◆◆◆ ライブラリを使用したエッジの抽出 ◆◆◆◆ */ j = 0; for( k = 0; k < point; k++ ) { xs = adr_work1[k][0]; ys = adr_work1[k][1]; xe = adr_work2[k][0]; ye = adr_work2[k][1]; status = Lib_edge_pos_xy( xs, ys, xe, ye, userp[ch]->zero_cross[i], userp[ch]->edge_level[i], 0, &px, &py ); if( NORMAL_RETURN == status ) { if( ON == userp[ch]->edge_display ) /* エッジ位置表示? */ Lib_pset( px / 16, py / 16, GRAPH_DRAW ); edge_data[j].x = ( px * 10 ) / 16; edge_data[j].y = ( py * 10 ) / 16; j++; } } edge_cnt = j; /* 抽出できたエッジ点数 */ } else { /* ◆◆◆◆ オリジナル方式によるエッジ検出 ◆◆◆◆ */ j = 0; for( k = 0; k < point; k++ ) { xs = adr_work1[k][0]; ys = adr_work1[k][1]; xe = adr_work2[k][0]; ye = adr_work2[k][1]; /* 外側から内側へ走査して濃度データを抽出する */ m = get_gray_data( xs, ys, xe, ye, gray_data_table, (int *)address_table ); if( ABS_LEVEL == userp[ch]->org_level_type[i] ) /* 濃度エッジは固定レベル(明から暗に変わる変化点。2画素以下はノイズと見なす) */ light_to_dark_border( userp[ch]->edge_level[i], 2, m, gray_data_table, (int *)address_table, boundary_data ); else { /* 濃度エッジは百分率レベル(明から暗に変わる変化点。2画素以下はノイズと見なす) */ pct_level = gray_data_table[m] - gray_data_table[m+1]; pct_level = pct_level * userp[ch]->edge_level[i] / 100 + gray_data_table[m+1]; light_to_dark_border( pct_level, 2, m, gray_data_table, (int *)address_table, boundary_data ); } if( -1 != boundary_data[0] && -1 != boundary_data[1] ) { if( ON == userp[ch]->edge_display ) /* エッジ位置表示? */ Lib_pset( boundary_data[0], boundary_data[1], GRAPH_DRAW ); edge_data[j].x = boundary_data[0] * 10; edge_data[j].y = boundary_data[1] * 10; j++; } } edge_cnt = j; /* 抽出できたエッジ点数 */ } /***** 直線近似 *****/ if( 2 <= edge_cnt ) /* エッジ点は2点以上抽出できた? */ { status = Lib_calcline( edge_cnt, edge_data, &coeff ); /* 直線近似 */ if( NORMAL_RETURN == status ) { a[i] = (double)coeff.a / 65536.0; /* それぞれの係数a,b,cを取り出す */ b[i] = (double)coeff.b / 65536.0; c[i] = (double)coeff.c / 16.0; if( ON == userp[ch]->retry[i] ) /* 再計測? */ { sqrt_ab = sqrt( ( a[i] * a[i] ) + ( b[i] * b[i] ) ); for( j = k = 0; j < edge_cnt; j++ ) { /* 近似直線から見た各エッジ点の距離を求める */ edge_distance = fabs( ( a[i] * (double)edge_data[j].x ) + ( b[i] * (double)edge_data[j].y ) + c[i] ) / sqrt_ab; if( abs( (int)edge_distance / 10 ) < userp[ch]->eliminate_pos[i] ) /* 距離は許容範囲内? */ { edge_data[k].x = edge_data[j].x; edge_data[k].y = edge_data[j].y; k++; } } if( 2 <= k ) /* 2点以上残った? */ { edge_cnt = k; status = Lib_calcline( edge_cnt, edge_data, &coeff ); /* 直線近似 */ if( NORMAL_RETURN == status ) { a[i] = (double)coeff.a / 65536.0; /* それぞれの係数a,b,cを取り出す。*/ b[i] = (double)coeff.b / 65536.0; /* 再計測指定の場合は、これが最終 */ c[i] = (double)coeff.c / 16.0; /* 的な直線係数となる。 */ } else { Lib_sprintf( disp_buff, "ERROR:%1番目(交点)枠内の2回目直線計算で不正処理発生", i+1 ); Lib_invdisp( 1, 30, disp_buff ); ng = 1; break; } } else { Lib_sprintf( disp_buff, "ERROR:%1番目(交点)枠内の再計測用エッジ点数が2点未満", i+1 ); Lib_invdisp( 1, 30, disp_buff ); ng = 1; break; } } if( ON == userp[ch]->calc_line_display ) /* 近似直線表示? */ { ys = 479; if( ys1 < ys ) ys = ys1; if( ye1 < ys ) ys = ye1; if( ys2 < ys ) ys = ys2; if( ye2 < ys ) ys = ye2; ye = 0; if( ys1 > ye ) ye = ys1; if( ye1 > ye ) ye = ye1; if( ys2 > ye ) ye = ys2; if( ye2 > ye ) ye = ye2; xs = (int)(( -b[i] * (double)ys * 10.0 - c[i] ) / a[i] ); xe = (int)(( -b[i] * (double)ye * 10.0 - c[i] ) / a[i] ); Lib_drawline( xs / 10, ys, xe / 10, ye ); /* 直線表示 */ } } else { Lib_sprintf( disp_buff, "ERROR:%1番目(交点)枠内の直線計算で不正処理発生", i+1 ); Lib_invdisp( 1, 30, disp_buff ); ng = 1; break; } } else { Lib_sprintf( disp_buff, "ERROR:%1番目(交点)枠内のエッジ抽出が2点未満", i+1 ); Lib_invdisp( 1, 30, disp_buff ); ng = 1; break; } /***** 得られた直線と中心までの距離 *****/ sqrt_ab = sqrt( ( a[i] * a[i] ) + ( b[i] * b[i] ) ); /* 近似直線から見た中心までの距離を求める */ ans_distance[i] = fabs( ( a[i] * ( center_x * 10.0 ) ) + ( b[i] * ( center_y * 10.0 ) ) + c[i] ) / sqrt_ab; ans_distance[i] /= 10.0; ans_distance[i] *= userp[ch]->pm_multiplier; /***** データの表示 *****/ Lib_sprintf( disp_buff, "(%d)=%.3lfmm", i + 1, ans_distance[i] / 1000.0 ); Lib_chrdisp( 1, i + 5, disp_buff ); } if( 4 == i ) ok = 1; } if( EXE == mode ) /* Remoteモードなら結果信号を出力 */ { if( ( 0 == ok && 0 == ng ) || 0 != ng ) /* ng が 0 以外の場合は何処かでエラーになったことを示す */ { /* ok,ng 共に 0 の場合は設定が不正で未計測だったことを示す */ Lib_putso( SIO_CHANNEL0, 9, "ERROR!!\r\n" ); /* NG情報を出力 */ } else { Lib_sprintf( out_buff, "%06.3lf,", length / 1000.0 ); Lib_sprintf( &out_buff[7], "%06.3lf,", width / 1000.0 ); for( i = 0; i < 4; i++ ) Lib_sprintf( &out_buff[i*7+14], "%06.3lf,", ans_distance[i] / 1000.0 ); out_buff[41] = '\r'; out_buff[42] = '\n'; Lib_putso( SIO_CHANNEL0, 43, out_buff ); /* 計測データを出力 */ } } if( TRY == mode ) { Lib_time_disp( 0, 0 ); Lib_stopclk_count(); } Lib_display_keyinput( 460, 0, "確認" ); Lib_cls( ( LINE_PLANE | CHAR_PLANE ), BLACK_COLOR ); Lib_freerun(); /* 画面フリーズの解除 */ } /***********************************************************************/ /* 計測処理に関する共通サブルーチン */ /***********************************************************************/ /**** ある点から点までの直線を構成する座標群を取り出す ****/ /***********************************************************************/ int get_adr_data( xs, ys, xe, ye, address_table ) int xs, ys, xe, ye; /* 直線の始点と終点座標 */ int *address_table; /* 直線を構成する座標群を格納するテーブルの先頭アドレス */ { register int i, x, y, xx, yy; register int x_size, y_size, x_add, y_add; int pixel_count; x = abs( xe - xs ) + 1; y = abs( ye - ys ) + 1; /* 座標群および濃度レベル群を得る */ if( x >= y ) { pixel_count = x; /* 参照点数 */ x_size = x; y_add = ( y << 22 ) / x; if( ys == ye ) y_add = 0; if( ys > ye ) y_add = 0 - y_add; if( xs == xe ) x_add = 0; if( xs > xe ) x_add = -1; else x_add = 1; x = xs; y = ys; yy = ys << 22; for( i = 0; i < x_size; i++ ) { *address_table++ = x; *address_table++ = y; x += x_add; yy += y_add; y = yy >> 22; } } else { pixel_count = y; /* 参照点数 */ y_size = y; x_add = ( x << 22 ) / y; if( xs == xe ) x_add = 0; if( xs > xe ) x_add = 0 - x_add; if( ys == ye ) y_add = 0; if( ys > ye ) y_add = -1; else y_add = 1; y = ys; x = xs; xx = xs << 22; for( i = 0; i < y_size; i++ ) { *address_table++ = x; *address_table++ = y; y += y_add; xx += x_add; x = xx >> 22; } } return( pixel_count ); } /***********************************************************************/ /* オリジナル・エッジ抽出法に関係するサブルーチン */ /***********************************************************************/ /**** カレント(グレー)メモリ上の1ラインの濃度データ及びそのアドレス群を取り出す ****/ /***********************************************************************/ int get_gray_data( xs, ys, xe, ye, gray_table, address_table ) int xs, ys, xe, ye; /* 直線の始点と終点座標 */ int *gray_table; /* 濃度データ群を格納するテーブルの先頭アドレス */ int *address_table; /* 直線を構成する座標群を格納するテーブルの先頭アドレス */ { register unsigned char *mem_base, *gmem_addr; register int i, x, y, xx, yy; register int x_size, y_size, x_add, y_add; int pixel_count; mem_base = (unsigned char *)Lib_adrs_gray_memory( Lib_get_gray_memory() ); x = abs( xe - xs ) + 1; y = abs( ye - ys ) + 1; /* 座標群および濃度レベル群を得る */ if( x >= y ) { pixel_count = x; /* 参照点数 */ x_size = x; y_add = ( y << 22 ) / x; if( ys == ye ) y_add = 0; if( ys > ye ) y_add = 0 - y_add; if( xs == xe ) x_add = 0; if( xs > xe ) x_add = -1; else x_add = 1; x = xs; y = ys; yy = ys << 22; for( i = 0; i < x_size; i++ ) { gmem_addr = y * 512 + x + mem_base; *gray_table++ = (int)*gmem_addr; *address_table++ = x; *address_table++ = y; x += x_add; yy += y_add; y = yy >> 22; } } else { pixel_count = y; /* 参照点数 */ y_size = y; x_add = ( x << 22 ) / y; if( xs == xe ) x_add = 0; if( xs > xe ) x_add = 0 - x_add; if( ys == ye ) y_add = 0; if( ys > ye ) y_add = -1; else y_add = 1; y = ys; x = xs; xx = xs << 22; for( i = 0; i < y_size; i++ ) { gmem_addr = y * 512 + x + mem_base; *gray_table++ = (int)*gmem_addr; *address_table++ = x; *address_table++ = y; y += y_add; xx += x_add; x = xx >> 22; } } /* 採取データ内の最大濃度値と最小濃度値、及び平均値を得る */ gray_table -= pixel_count; x_add = 0; xx = 0; yy = 255; x_size = pixel_count; for( x = 0; x < x_size; x++ ) { i = *gray_table++; x_add += i; if( xx < i ) xx = i; if( yy > i ) yy = i; } *gray_table++ = xx; /* 最大濃度値 */ *gray_table++ = yy; /* 最小濃度値 */ *gray_table = x_add / x_size; /* 平均濃度値 */ return( pixel_count ); } /**************************************************************************/ /**** 濃淡データ群から濃度境界(明から暗に変わる変化点)座標を見つける ****/ /**************************************************************************/ void light_to_dark_border( edge, noise, limit, gray_table, address_table, boundary_data ) int edge, noise, limit, *gray_table, *address_table, *boundary_data; { register int i, g_data, flag, brack_counter, white_counter; int x, y; flag = brack_counter = white_counter = 0; x = y = -1; for( i = 0; i < limit; i++, gray_table++, address_table += 2 ) { g_data = *gray_table; if( edge >= g_data ) { if( flag == 0 ) { if( white_counter > noise ) { x = *address_table; y = *( address_table + 1 ); flag = 1; white_counter = 0; } } brack_counter += 1; if( brack_counter > noise ) break; } if( edge < g_data ) { if( flag == 1 ) { flag = 0; brack_counter = 0; } white_counter += 1; } } *boundary_data++ = x; /* 変化点X */ *boundary_data = y; /* 変化点Y */ } /**************************************************************************/ /**** 濃淡データ群から濃度境界(暗から明に変わる変化点)座標を見つける ****/ /**************************************************************************/ void dark_to_light_border( edge, noise, limit, gray_table, address_table, boundary_data ) int edge, noise, limit, *gray_table, *address_table, *boundary_data; { register int i, g_data, flag, brack_counter, white_counter; int x, y; flag = brack_counter = white_counter = 0; x = y = -1; for( i = 0; i < limit; i++, gray_table++, address_table += 2 ) { g_data = *gray_table; if( edge <= g_data ) { if( flag == 0 ) { if( brack_counter > noise ) { x = *address_table; y = *( address_table + 1 ); flag = 1; brack_counter = 0; } } white_counter += 1; if( white_counter > noise ) break; } if( edge > g_data ) { if( flag == 1 ) { flag = 0; white_counter = 0; } brack_counter += 1; } } *boundary_data++ = x; /* 変化点X */ *boundary_data = y; /* 変化点Y */ }