- 締切済み
ガンマ変換 C言語でプログラムの作成
次式のように、原画像の任意の階調値fから、点線の矢印のようにして交換後の階調値gを決める。このような階調値の変換を表す配列 unsigned char trans[256];を用いて画像の濃度補正を行うプログラム作成せよとあるのですが、どのような計算式を用いて任意の変換の プログラムを作成してよいかわかりません。 同、問題でガンマ変換のプログラムは作成したのですが、 詳しい方で添付画像のようなプログラムを作成できる方がいましたらよろしくお願いします。 ESPライブラリを使用していますので、添付ファイルにソースとヘッダファイルと図を添付しています プログラムの開始: sを押す 終了: xを押す --------------------------------------------------------------*/ #include <stdio.h> #include <stdlib.h> #include "mypgmesp.h" /* ESP関係の関数が定義されているヘッダファイル */ #define FINAL_LEVEL 64 //最終的な表現階調数// // 関数のプロトタイプ宣言 void gamma_histgram(void); /************************************************************************* このプログラムを実行したとき、はじめに実行される処理を書く *************************************************************************/ void ESP_Ready(void) { ESP_Open_Window(); } /************************************************************************* このプログラムが終了したとき、実行される処理を書く *************************************************************************/ void ESP_Finish(void) { } /************************************************************************* startボタンが押されたときに、実行される処理を書く *************************************************************************/ void ESP_Main(void) { int ret; /* 準備 */ ESP_Prepare(); /* 画像データを image1 に読み込んで表示する */ ret = ESP_load_image_data(); if(ret){ ESP_StartMenu(); return; } /////////////////////////////////////////////////// // 以下に関数や命令を記述する gamma_histgram(); // ここまで /////////////////////////////////////////////////// /* image2 を保存し表示する */ ESP_save_image_data(); /* メッセージの表示 */ ESP_StartMenu( ); } ////////////////////////////////////////////////// // 以下の関数内にプログラムを追加する /////////////////////////////////////////////////// void gamma_histgram(void) { int i, x, y,g; /* ループ変数 */ long int target_value;//変換後の頻度の目標値// double gam = 2.0,j; unsigned char trans[256]; ESP_Printf("ガンマ補正を行う\n"); for (i = 0; i < 256; i ++){ j=i; g=255*pow(j/255.0,1.0/gam); if(g>255) { trans[i]=255; } else if (g<0) { trans[i]=0; } else { trans[i]=(unsigned char)g; } x_size2=x_size1; y_size2=y_size1; for ( y = 0; y < y_size2; y ++ ) { for ( x = 0; x < x_size2; x ++ ) image2[y][x] = trans[image1[y][x]]; } } }
- みんなの回答 (1)
- 専門家の回答
みんなの回答
- orenotan
- ベストアンサー率0% (0/0)
補足でヘッダファイルと濃度補正の図です /* ------------------------------------------------------- pgm ファイルを読み書きし、 ウィンドウ出力するためのヘッダファイル mypgmesp.h Ver 1.10 # 入力画像と出力画像のパス変更,拡張子の省略 ----------------------------------------------------------*/ #include <string.h> #include <stdlib.h> #include <esplib.h> /* 定数宣言 */ #define MAX_IMAGESIZE 1024 /* 想定する縦・横の最大画素数 */ #define MAX_BRIGHTNESS 255 /* 想定する最大階調値 */ #define GRAYLEVEL 256 /* 想定する階調数(=最大階調値+1) */ #define MAX_FILENAME 256 /* 想定するファイル名の最大長 */ #define MAX_BUFFERSIZE 256 /* 利用するバッファ最大長 */ #define IN_PATH "input" // 入力画像のパス #define OUT_PATH "output" // 出力画像のパス #define IMAGE_PREFIX ".pgm" // 画像の拡張子 #define ZOOM_E 120 /* 小さな画像を表示するときの自動ズーム調整 */ #define ZOOM 100 /* グラフィック表示のウィンドウの表示倍率 */ #define TXT_M 1 /* テキスト表示ウィンドウ番号 */ #define TXT_F 2 /* テキスト表示ウィンドウ番号 */ #define IMG_A 1 /* グラフィックウィンドウ番号 */ #define IMG_B 2 /* グラフィックウィンドウ番号 */ #define TXT_WIN_WIDTH_M 600 /* テキスト表示のウィンドウ横サイズ */ #define TXT_WIN_HIGHT_M 500 /* テキスト表示のウィンドウ縦サイズ */ #define TXT_WIN_WIDTH_F 200 /* テキスト表示のウィンドウ横サイズ */ #define IMG_WIN_WIDTH 120 /* グラフィック表示のウィンドウ横サイズ */ #define IMG_WIN_HIGHT 120 /* グラフィック表示のウィンドウ縦サイズ */ /* 大域変数の宣言 */ /* 画像用配列1,画像用配列2 */ unsigned char image1[MAX_IMAGESIZE][MAX_IMAGESIZE], image2[MAX_IMAGESIZE][MAX_IMAGESIZE]; int x_size1, y_size1, /* image1 の横画素数,縦画素数 */ x_size2, y_size2; /* image2 の横画素数,縦画素数 */ char in_fname[100][20]; int in_fno; /* 関数のプロトタイプ宣言 */ int ESP_load_image_data(void); /* 画像読み込み用関数 */ void ESP_save_image_data(void); /* 画像書き込み用関数 */ void ESP_Draw_image_data(int ino); void ESP_Open_Window(void); void ESP_Prepare(void); void ESP_StartMenu(void); /* 以下は関数の本体 */ int ESP_load_image_data( ) /* pgm 画像,横画素数,縦画素数のデータをファイルから読み込み,*/ /* image1[ ][ ],x_size1,y_size1 にそれぞれ代入する. */ { char file_name[MAX_FILENAME]; /* ファイル名用の文字配列 */ char buffer[MAX_BUFFERSIZE]; /* データ読み込み用作業変数 */ FILE *fp; /* ファイルポインタ */ int max_gray; /* 最大階調値 */ int x, y,i; /* ループ変数 */ /* 入力ファイルのオープン */ ESP_SelectTW(TXT_M); ESP_Printf("-----------------------------------------------------\n"); ESP_Printf(" モノクロ階調画像入力ルーチン\n"); ESP_Printf("-----------------------------------------------------\n"); ESP_Printf("ファイル形式は pgm, バイナリ形式とします.\n"); ESP_Printf("ファイルは Release\\%s フォルダから読み込みます.\n", IN_PATH); ESP_Printf("入力ファイルウィンドウの番号指定は /番号 です.\n"); ESP_Printf("入力ファイル名 (*.pgm) : "); ESP_Input(file_name); if(file_name[0] == '/'){ i=1; x=0; while(file_name[i]!='\0'){ x = x * 10 + (file_name[i]-'0'); i++; } if(x <= in_fno && x > 0) strcpy(file_name, in_fname[x-1]); } sprintf(buffer, "%s\\%s",IN_PATH, file_name); strcpy(file_name, buffer); fp = fopen( file_name, "rb" ); if ( NULL == fp ){ ESP_Printf("その名前のファイルは存在しません.\n"); ESP_Input(buffer); //exit(1); return 1; } /* ファイルタイプ(=P5)の確認 */ fgets( buffer, MAX_BUFFERSIZE, fp ); if ( buffer[0] != 'P' || buffer[1] != '5' ){ ESP_Printf("ファイルのフォーマットが P5 とは異なります.\n"); ESP_Input(buffer); exit(1); } /* x_size1, y_size1 の代入(#から始まるコメントは読み飛ばす) */ x_size1 = 0; y_size1 = 0; while ( x_size1 == 0 || y_size1 == 0 ){ fgets( buffer, MAX_BUFFERSIZE, fp ); if ( buffer[0] != '#' ){ sscanf( buffer, "%d %d", &x_size1, &y_size1 ); } } /* max_gray の代入(#から始まるコメントは読み飛ばす) */ max_gray = 0; while ( max_gray == 0 ){ fgets( buffer, MAX_BUFFERSIZE, fp ); if ( buffer[0] != '#' ){ sscanf( buffer, "%d", &max_gray ); } } /* パラメータの画面への表示 */ ESP_Printf("横の画素数 = %d, 縦の画素数 = %d\n", x_size1, y_size1 ); ESP_Printf("最大階調値 = %d\n",max_gray); if ( x_size1 > MAX_IMAGESIZE || y_size1 > MAX_IMAGESIZE ){ ESP_Printf("想定値 %d x %d を超えています.\n", MAX_IMAGESIZE, MAX_IMAGESIZE); ESP_Printf("もう少し小さな画像を使って下さい.\n"); ESP_Input(buffer); exit(1); } if ( max_gray != MAX_BRIGHTNESS ){ ESP_Printf("最大階調値が不適切です.\n"); ESP_Input(buffer); exit(1); } /* 画像データを読み込んで画像用配列に代入する */ for ( y = 0; y < y_size1; y ++ ){ for ( x = 0; x < x_size1; x ++ ){ image1[y][x] = (unsigned char)fgetc( fp ); } } ESP_Draw_image_data(1); ESP_Printf("データは正しく読み込まれました.\n"); ESP_Printf("-----------------------------------------------------\n"); fclose(fp); return 0; } void ESP_save_image_data() /* image2[ ][ ], x_size2, y_size2 のデータを,それぞれ pgm 画像,*/ /* 横画素数,縦画素数としてファイルに保存する. */ { char file_name[MAX_FILENAME]; /* ファイル名用の文字配列 */ char buffer[MAX_BUFFERSIZE]; /* データ読み込み用作業変数 */ FILE *fp; /* ファイルポインタ */ int x, y, i; /* ループ変数 */ /* 出力ファイルのオープン */ ESP_Printf("-----------------------------------------------------\n"); ESP_Printf(" モノクロ階調画像(pgm形式)出力ルーチン\n"); ESP_Printf("-----------------------------------------------------\n"); ESP_Printf("ファイルは Release\\%s フォルダに書き出します.\n", OUT_PATH); ESP_Printf("入力ファイルウィンドウの番号指定は /番号 です.\n"); ESP_Printf("拡張子を省略した場合は自動付加します.\n"); ESP_Printf("出力ファイル名を省略した場合は outimage.pgm とします.\n"); ESP_Printf("出力ファイル名 (*.pgm) : "); ESP_Input(file_name); if(file_name[0] == '/'){ i=1; x=0; while(file_name[i]!='\0'){ x = x * 10 + (file_name[i]-'0'); i++; } if(x <= in_fno && x > 0) strcpy(file_name, in_fname[x-1]); } else if(file_name[0] == '\0'){ strcpy(file_name, "outimage.pgm"); } else if(strstr(file_name, IMAGE_PREFIX) == NULL){ strcat(file_name, IMAGE_PREFIX); } sprintf(buffer,"%s\\%s", OUT_PATH, file_name); strcpy(file_name, buffer); ESP_Printf("出力ファイル: %s\n", file_name); fp = fopen(file_name, "wb"); if ( NULL == fp ){ strcpy(buffer,"mkdir "); strcat(buffer, OUT_PATH); system(buffer); fp = fopen(file_name, "wb"); } /* ファイル識別子 "P5" を先頭に出力する */ fputs( "P5\n", fp ); /* # で始まるコメント行(省略可能) */ fputs( "# Created by Image Processing\n", fp ); /* 画像の横幅,縦幅の出力 */ fprintf( fp, "%d %d\n", x_size2, y_size2 ); /* 最大階調値の出力 */ fprintf( fp, "%d\n", MAX_BRIGHTNESS ); /* 画像データの出力 */ for ( y = 0; y < y_size2; y ++ ){ for ( x = 0; x < x_size2; x ++ ){ fputc( image2[y][x], fp ); } } ESP_Draw_image_data(2); ESP_Printf("データは正しく出力されました.\n"); ESP_Printf("-----------------------------------------------------\n"); fclose(fp); } void ESP_Draw_image_data(int ino){ /* inoに指定された画像をウィンドウに表示する */ /* ino == 1 : 入力画像の表示 */ /* ino == 2 : 出力画像の表示 */ int x, y; /* ループ変数 */ int x0, y0; /* 表示画像のサイズ */ int zv; /* ウィンドウ位置の調整変数 */ if(ino == 1){ /* 入力画像のサイズ設定 */ x0 = x_size1; y0 = y_size1; /* 最低ウィンドウサイズを考慮したウィンドウ位置調整 */ zv= (ZOOM_E - x0); if(zv < 2) zv = 2; /* 入力画像表示のウィンドウサイズの変更のための出力ウィンドウ位置を変更 */ ESP_PlaceImage(IMG_B, x0+ zv +5, TXT_WIN_HIGHT_M+40); } else if(ino == 2){ /* 出力画像のサイズ設定 */ x0 = x_size2; y0 = y_size2; } /* ウィンドウサイズの変更・ズームの設定・更新 */ ESP_ResizeImage(ino, x0, y0); ESP_ZoomImage(ino, 100); ESP_UpdateAll(); /* 画像の描画 */ ESP_Select(ino); for ( y = 0; y < y0; y ++ ){ for ( x = 0; x < x0; x ++ ){ if(ino==1) ESP_Pset(x,y,image1[y][x]); else if(ino==2) ESP_Pset(x,y,image2[y][x]); } } } void ESP_Open_Window(void){ /* メッセージテキストウィンドウを開く */ ESP_OpenTextWindow(TXT_M, 0, 0, TXT_WIN_WIDTH_M,TXT_WIN_HIGHT_M); ESP_OpenTextWindow(TXT_F, TXT_WIN_WIDTH_M + 8, 0, TXT_WIN_WIDTH_F,TXT_WIN_HIGHT_M); /* 起動メッセージ表示 */ ESP_SelectTW(TXT_M); ESP_Printf("プログラム開始: s キーを押してください\n"); ESP_Printf("プログラム終了: x キーを押してください\n"); /* 入力ファイルウィンドウにヘッダを表示 */ ESP_SelectTW(TXT_F); ESP_Printf("%s\n"," No: 入力ファイル"); /* グラフィックウィンドウを開く */ ESP_CreateImage8(IMG_A, "入力", 0 , TXT_WIN_HIGHT_M+40, IMG_WIN_WIDTH, IMG_WIN_HIGHT,ZOOM); ESP_CreateImage8(IMG_B, "出力",IMG_WIN_WIDTH + 7, TXT_WIN_HIGHT_M+40, IMG_WIN_WIDTH, IMG_WIN_HIGHT,ZOOM); } void ESP_Prepare(void){ char file_name[MAX_FILENAME]; /* ファイル名用の文字配列 */ char buf[MAX_BUFFERSIZE]; /* データ読み込み用作業変数 */ FILE *fp; /* ファイルポインタ */ int cnt; /* カウント */ in_fno=0; sprintf(buf, "dir /b %s > _temp.txt", IN_PATH); system(buf); fp = fopen( "_temp.txt", "r" ); if ( NULL == fp ){ ESP_Printf("_temp.txtファイルは存在しません.\n"); ESP_Input(buf); exit(1); } ESP_SelectTW(TXT_F); fgets( buf,20,fp); //ファイルから1行読み込み while(!feof(fp)){ //EOFになるまで cnt=strlen(buf); //1行の文字数を数える buf[cnt-1] = '\0'; //改行を取り除く if(strstr(buf,IMAGE_PREFIX) != NULL){ strcpy(in_fname[in_fno],buf); //配列の末尾に追加 in_fno++; ESP_Locate(0, in_fno); ESP_Printf("%3d:%s\n", in_fno, buf); if(in_fno == 30) break; } fgets( buf,20,fp); //ファイルから1行読み込み } fclose(fp); //ファイルのクローズ sprintf(buf, "del _temp.txt"); system(buf); /* テキストウィンドウのクリア */ ESP_SelectTW(TXT_M); ESP_ClearTextWindow(); } void ESP_StartMenu(void){ /* メッセージの表示 */ ESP_SelectTW(TXT_M); ESP_Printf("\n=======================================\n"); ESP_Printf("プログラム開始: s キーを押してください\n"); ESP_Printf("プログラム終了: x キーを押してください\n"); }