質問するログイン新規登録
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

806閲覧

C 疑似カラー画像の作成方法が分からない。

kouchan_dd

総合スコア20

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2024/06/14 06:30

編集2024/06/14 14:31

0

0

実現したいこと

画像に疑似カラーをつけるプログラムを作成したいです。

入力はグレースケール画像(.pgmファイル)で、それをRGBそれぞれの疑似カラー変換関数式で変換を行い、結果をRGBそれぞれのチャンネルへ出力する(.ppmファイル)方法で作成したいです。

変換式は疑似カラー変換関数を参考にします。
R=0 (I < 128), (I - 128)255/192-128 (128 < I <= 192), 255 (I > 192)
G=I*255/64 (I <= 64), 255(64 < I <= 192), (I-255)255/192-255(I > 192)
B=255(I<=64), (I - 128)255/64-128(64 < I <= 128), 0(I > 128)

また、ファイルを読み書き吸うためのヘッダファイルをppmpgm.hとします。

発生している問題・分からないこと

以下のようなプログラムを作って実行しましたが、GIMPで以下のようなエラーメッセージが出力され、画像が生成されませんでした。なお、画像自体は著作権の関係もあり、ここでは表示しません。

「GIMP エラーメッセージ
'(File)'のオープンに失敗しました。
PNM画像 plug-in could not open image

PNM画像 エラーメッセージ
不正な X解像度です」

おそらく、void equality 内の2重ループの中に記載した疑似カラー変換関数の書き方(if文の使い方)などが誤っていると考えています。

ヘッダファイルの内容は変更せずに、void equalityの中身をどのように書き換えれば、画像が正しく生成されるかを教えていただきたいです。

なお、実行すると下記のような画面になりました。

モノクロ階調画像入力ル-チン

file形式はpgm、バイナリ形式とします。
入力file名(*.pgm):farinfrared.pgm
横の画素数 = 811, 縦の画素数 = 607
最大階調値 = 255
デ-タは正しく読み込まれました。


カラ-画像(ppm形式)出力ル-チン

出力file名(*.ppm):farinfrared_1.ppm
デ-タは正しく出力されました。

続行するには何かキーを押してください . . .

該当のソースコード

C

1#include <stdio.h> 2#include <stdlib.h> 3#include "ppmpgm.h" 4 5void equality(void) 6{ 7 int x,y,k,p; 8 //画像の幅と高さを設定 9 pXdim2 = pXdim1; pYdim2 = pYdim1; 10 for(y=0;y<pYdim2;y++) 11 for(x=0;x<pXdim2;x++) 12 p = pimage1[0][y][x]; 13 if(p<128) 14 pimage2[0][y][x] = 0; 15 else if(p>192) 16 pimage2[0][y][x] = 255; 17 else 18 pimage2[0][y][x] = 255*(p-128)/(192-128); 19 20 p = pimage1[1][y][x]; 21 if(p<=64) 22 pimage2[1][y][x] = p*(255/64); 23 else if(p>192) 24 pimage2[1][y][x] = 255*(p-255)/(192-255); 25 else 26 pimage2[1][y][x] = 255; 27 28 p = pimage1[2][y][x]; 29 if(p<=64) 30 pimage2[2][y][x] = 255; 31 else if(p>128) 32 pimage2[2][y][x] = 0; 33 else 34 pimage2[2][y][x] = 255*(p-128)/(64-128); 35} 36 37 38void main(void) 39{ 40 load_image_pgm(); 41 equality(); 42 save_image_ppm(); 43 return; 44} 45

C

1/* ppmpgm.h */ 2 3#define MAX_IMAGESIZE 1024 4#define MAX_BRIGHTNESS 255 5#define GRAYLEVEL 256 6#define MAX_FILENAME 256 7#define MAX_BUFFERSIZE 256 8 9unsigned char pimage1[3][MAX_IMAGESIZE][MAX_IMAGESIZE], 10 pimage2[3][MAX_IMAGESIZE][MAX_IMAGESIZE]; 11float ptmp[3][MAX_IMAGESIZE][MAX_IMAGESIZE]; 12int pXdim1, pYdim1, 13 pXdim2, pYdim2; 14 15unsigned char gimage1[MAX_IMAGESIZE][MAX_IMAGESIZE], 16 gimage2[MAX_IMAGESIZE][MAX_IMAGESIZE]; 17float gtmp[MAX_IMAGESIZE][MAX_IMAGESIZE]; 18int gXdim1, gYdim1, 19 gXdim2, gYdim2; 20 21void load_image_ppm(void); 22void save_image_ppm(void); 23void load_image_pgm(void); 24void save_image_pgm(void); 25 26void load_image_ppm(void) 27{ 28 char file_name[MAX_FILENAME]; 29 char buffer[MAX_BUFFERSIZE]; 30 FILE *fp; 31 int max_gray; 32 int x,y,k; 33 34 35 printf("-------------------------------------\n"); 36 printf(" カラ-画像入力ル-チン\n"); 37 printf("-------------------------------------\n"); 38 printf("file形式はppm、バイナリ形式とします。\n"); 39 printf("入力file名(*.ppm):"); 40 scanf("%s",file_name); 41 fp=fopen(file_name,"rb"); 42 if(NULL==fp){ 43 printf("その名前のfileは存在しません。\n"); 44 exit(1); 45 } 46 47 48 fgets(buffer,MAX_BUFFERSIZE,fp); 49 if(buffer[0]!='P' || buffer[1]!='6'){ 50 printf("fileのフォ-マットがP6とは異ります。\n"); 51 exit(1); 52 } 53 54 /* pXdim1, pYdim1の代入(#から始まるコメントは読み飛ばす) */ 55 pXdim1 = 0; 56 pYdim1 = 0; 57 while(pXdim1 == 0 || pYdim1 == 0){ 58 fgets(buffer,MAX_BUFFERSIZE,fp); 59 if(buffer[0]!='#'){ 60 sscanf(buffer,"%d %d",&pXdim1,&pYdim1); 61 } 62 } 63 64 max_gray = 0; 65 while(max_gray == 0){ 66 fgets(buffer, MAX_BUFFERSIZE,fp); 67 if(buffer[0]!='#'){ 68 sscanf(buffer,"%d",&max_gray); 69 } 70 } 71 72 printf("横の画素数 = %d, 縦の画素数 = %d\n", pXdim1, pYdim1); 73 printf("最大階調値 = %d\n",max_gray); 74 if(pXdim1 > MAX_IMAGESIZE || pYdim1 > MAX_IMAGESIZE){ 75 printf("想定値 %d x %d を超えています。\n", 76 MAX_IMAGESIZE,MAX_IMAGESIZE); 77 printf("もう少し小さい画像を使って下さい。\n"); 78 exit(1); 79 } 80 if(max_gray != MAX_BRIGHTNESS){ 81 printf("最大階調値が不適切です。\n"); 82 exit(1); 83 } 84 85 for(y=0; y<pYdim1; y++){ 86 for(x=0;x<pXdim1; x++){ 87 for(k=0;k<3;k++) 88 pimage1[k][y][x] = (unsigned char)fgetc(fp); 89 } 90 } 91 92 printf("デ-タは正しく読み込まれました。\n"); 93 printf("--------------------------------------\n"); 94 fclose(fp); 95} 96 97void save_image_ppm(void) 98{ 99 char file_name[MAX_FILENAME]; 100 FILE *fp; 101 int x,y,k; 102 103 printf("------------------------------------\n"); 104 printf(" カラ-画像(ppm形式)出力ル-チン\n"); 105 printf("------------------------------------\n"); 106 printf("出力file名(*.ppm):"); 107 scanf("%s",file_name); 108 fp = fopen(file_name,"wb"); 109 110 fputs("P6\n",fp); 111 fputs("# Created by H.I.T\n",fp); 112 fprintf(fp,"%d %d\n",pXdim2,pYdim2); 113 fprintf(fp,"%d\n",MAX_BRIGHTNESS); 114 115 for(y=0; y<pYdim2; y++){ 116 for(x=0; x<pXdim2; x++){ 117 for(k=0;k<3;k++) 118 fputc(pimage2[k][y][x],fp); 119 } 120 } 121 122 printf("デ-タは正しく出力されました。\n"); 123 printf("------------------------------------\n"); 124 fclose(fp); 125} 126 127void load_image_pgm(void) 128{ 129 char file_name[MAX_FILENAME]; 130 char buffer[MAX_BUFFERSIZE]; 131 FILE *fp; 132 int max_gray; 133 int x,y; 134 135 printf("-------------------------------------\n"); 136 printf(" モノクロ階調画像入力ル-チン\n"); 137 printf("-------------------------------------\n"); 138 printf("file形式はpgm、バイナリ形式とします。\n"); 139 printf("入力file名(*.pgm):"); 140 scanf("%s",file_name); 141 fp=fopen(file_name,"rb"); 142 if(NULL==fp){ 143 printf("その名前のfileは存在しません。\n"); 144 exit(1); 145 } 146 147 fgets(buffer,MAX_BUFFERSIZE,fp); 148 if(buffer[0]!='P' || buffer[1]!='5'){ 149 printf("fileのフォ-マットがP5とは異ります。\n"); 150 exit(1); 151 } 152 153 gXdim1 = 0; 154 gYdim1 = 0; 155 while(gXdim1 == 0 || gYdim1 == 0){ 156 fgets(buffer,MAX_BUFFERSIZE,fp); 157 if(buffer[0]!='#'){ 158 sscanf(buffer,"%d %d",&gXdim1,&gYdim1); 159 } 160 } 161 162 max_gray = 0; 163 while(max_gray == 0){ 164 fgets(buffer, MAX_BUFFERSIZE,fp); 165 if(buffer[0]!='#'){ 166 sscanf(buffer,"%d",&max_gray); 167 } 168 } 169 170 printf("横の画素数 = %d, 縦の画素数 = %d\n", gXdim1, gYdim1); 171 printf("最大階調値 = %d\n",max_gray); 172 if(gXdim1 > MAX_IMAGESIZE || gYdim1 > MAX_IMAGESIZE){ 173 printf("想定値 %d x %d を超えています。\n", 174 MAX_IMAGESIZE,MAX_IMAGESIZE); 175 printf("もう少し小さい画像を使って下さい。\n"); 176 exit(1); 177 } 178 if(max_gray != MAX_BRIGHTNESS){ 179 printf("最大階調値が不適切です。\n"); 180 exit(1); 181 } 182 183 for(y=0; y<gYdim1; y++){ 184 for(x=0;x<gXdim1; x++){ 185 gimage1[y][x] = (unsigned char)fgetc(fp); 186 } 187 } 188 189 printf("デ-タは正しく読み込まれました。\n"); 190 printf("--------------------------------------\n"); 191 fclose(fp); 192} 193 194void save_image_pgm(void) 195{ 196 char file_name[MAX_FILENAME]; 197 FILE *fp; 198 int x,y; 199 200 printf("------------------------------------\n"); 201 printf(" モノクロ階調画像(pgm形式)出力ル-チン\n"); 202 printf("------------------------------------\n"); 203 printf("出力file名(*.pgm):"); 204 scanf("%s",file_name); 205 fp = fopen(file_name,"wb"); 206 207 fputs("P5\n",fp); 208 fputs("# Created by H.I.T\n",fp); 209 fprintf(fp,"%d %d\n",gXdim2,gYdim2); 210 fprintf(fp,"%d\n",MAX_BRIGHTNESS); 211 212 for(y=0; y<gYdim2; y++){ 213 for(x=0; x<gXdim2; x++){ 214 fputc(gimage2[y][x],fp); 215 } 216 } 217 218 printf("デ-タは正しく出力されました。\n"); 219 printf("------------------------------------\n"); 220 fclose(fp); 221} 222

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

疑似カラー変換関数を調べてプログラムに実装したが、うまく画像が生成されなかった。
また、ChatGPTを使って、プログラムをAIに作成してもらったが、疑似カラー変換関数を用いた実行方法は出てこなかった。

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

int32_t

2024/06/14 07:15

> 画像がうまく生成されませんでした。 ここを具体的に書きましょう。 プログラムがクラッシュするのか、出力ファイルができないのか、出力ファイルが画像として開けないのか、出力ファイルの色がおかしいのか、など。
jimbe

2024/06/14 07:17

試された元データとそれを処理した結果どのようなファイルが出来なければならないのかをご提示ください。 >画像がうまく生成されませんでした。 何処まで想定通りに動作していてどこで問題が起きているのかをご自身で調べられましたでしょうか。 300行以上のコードをポンと出されて『何が問題か教えて』と言うのであれば、それは丸投げです。 せめて「○○行で△△変数の値が□□にならなければならないのに✕✕になっている」までは調べられては如何でしょうか。
KOZ6.0

2024/06/14 07:32

ググるとこんなのありました。 【C言語/画像処理】PNM(PPM・PGM・PBM)ファイルの読み込みと書き出し【ライブラリ不要】 https://daeudaeu.com/pnm/
tmp

2024/06/14 08:53

load_image_pgm();でgimage1に読み込み equality();でpimage1からpimage2を作成して(読み込んだデータは、どこにつかった???) save_image_ppm();pimage2を保存する。 グローバル変数って気がつきにくいよね。
KOZ6.0

2024/06/14 11:52

AI(CharGPT)に"C言語でPGMファイルをPPMファイルに変換するには"と聞くと、60 行くらいのサンプルを提供してくれました。 コンパイルして実行してみたら動いたので、AI に聞いてみるといいんじゃないですか?
KOZ6.0

2024/06/14 14:43

>また、ChatGPTを使って、プログラムをAIに作成してもらったが、疑似カラー変換関数を用いた実行方法は出てこなかった。 なんでそこであきらめるんでしょう?疑似カラー変換関数を用いた方法を要求したらそれなりのコードを提供されました。最初は OpenCV を使った方法を提案されましたが、ライブラリを使わずできないか?と聞いたら違うサンプルを提供されました。条件があるならどんどん入力していけばいいんですよ
jimbe

2024/06/14 23:32

2x3 位の極小さいデータならテキストエディタで作れるはずで、それを変換したらどんなデータが作られるのかも手作業で求められるはずです。 GIMP に読ませなくてもファイルダンププログラムがあれば変換したファイルの中身は確認出来、それを手作業で変換した結果と付き合わせることが出来ます。 計算に使用している変数の値(やその変化)とループの状況を調べれば、使う変数が間違っていることや二重ループが出来ていないことは即分かるでしょう。 思考で追うにしても思い込みを無くさないと見えるものも見えなくなりますから、手を使って検証・証拠集めもする事をお勧めします。
tmp

2024/06/16 15:51

load_image_pgm();でファイルを読み込んでgimage1のサイズがgXdim1, gYdim1がセットされます。 equality();で、読み込んでもいないpimage1のサイズpXdim1, pYdim1からpimage2を作成しているので画像サイズは縦横0x0からpimage2を作り出し、 それをsave_image_ppm();pimage2を保存しているので0x0の画像ファイルができるので それを読み込むと「不正な X解像度です」と出ていると思われます。 equality修正したいのであれば、pimage1からでなく、gimage1、gXdim1、gYdim1からpimage2作るように修正する。 そもそも、このような画像形式を使うのは、主に学習目的で、それを考えるのが目的だと思うので、 回答が欲しいだけだと考えるの機会を失うもったいないことになりませんか?
guest

回答2

0

そもそも「擬似カラーにする」というのがオレオレ用語定義だと思います。
過去私の聞いた「擬似カラー」は、いわゆる「元からのカラー情報に対して擬似」であって、モノクロの画像に対しオブジェクトが何かを判断しながら適切と思われる着色をするものでした。
単に輝度に応じてRGBを割り振るという手法は初めてみましたが、これを擬似カラーと言って通じるのか甚だ疑問です。AIに対してどういう聞き方をしたのか知りませんが、「擬似カラー」などという言葉は使わず、その変換手順をそのまま与えてみればよいのではないかと思います。
(ちょっと調べたら「擬似カラー」とは情報の可視化・強調などのために輝度に色を割り当てたもの、ということらしいので、この部分削除します)

つまり、

プログラムをAIに作成してもらったが、疑似カラー変換関数を用いた実行方法は出てこなかった。
それはあなたの指示が適切でないのだと思います。私の手元では、以下の指示をChatGPT4oに与えてそれっぽいプログラムが生成されました。

Text

1あなたはC言語のプログラマです。 2 3グレースケールの.pgmフォーマットの画像から、各ピクセルの輝度値Iに応じて以下の規則で色をつけて、.ppmフォーマットで出力するプログラムを書いて下さい。 4ただし、画像のファイル入出力は以下の関数を使用し、この関数は外部で規定されています。 5 6pgmファイル入力の関数: 7シグニチャ void load_image_pgm(void); 8ファイル名は関数中で決定されるので呼び出し側では管理しない。 9最大輝度は255である。 10得られたデータは、以下のグローバル変数に格納する。 11画像幅 int gXdim1; 12画像高さ int gYdim1; 13画素データ unsigned char gimage1[MAX_IMAGESIZE][MAX_IMAGESIZE] 14 15ppmファイル出力の関数: 16シグニチャ void save_image_ppm(void); 17ファイル名は関数中で決定されるので呼び出し側では管理しない。 18最大輝度は255である。 19以下のデータをグローバル変数に格納して呼び出す。 20画像幅 int pXdim2 21画像幅 int pYdim2 22画素データunsigned char pimage2[RGB][MAX_IMAGESIZE][MAX_IMAGESIZE]; 23 24なお、以下のシンボルが規定されている。 25#define MAX_IMAGESIZE 1024 26#define RGB 3 27 28画素の色付け規則: 29R=0 (I < 128), (I - 128)255/192-128 (128 < I <= 192), 255 (I > 192) 30G=I*255/64 (I <= 64), 255(64 < I <= 192), (I-255)255/192-255(I > 192) 31B=255(I<=64), (I - 128)255/64-128(64 < I <= 128), 0(I > 128)

あなたの手元ではいかがですか?

投稿2024/06/15 10:26

編集2024/06/15 13:02
thkana

総合スコア7739

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thkana

2024/06/15 10:40

あ、間違って > 画像幅 int pYdim2 とかしてるのに完全にスルーされたな。
guest

0

ベストアンサー

equality 関数内で変換元として用いているのは pXdim1pYdim1pimage1 などいずれも load_image_ppm 関数で読む想定のデータであり、load_image_pgm で読み込んだデータが使われていないと思われます。

投稿2024/06/14 16:01

yaito3014

総合スコア209

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kouchan_dd

2024/06/16 15:58

回答ありがとうございます。 試したところ問題が解決しました! ベストアンサーに選ばせていただきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問