グレースケールのRAW画像を、RGB合成するプログラムについて。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
いちこ
記事: 62
登録日時: 8年前
連絡を取る:

グレースケールのRAW画像を、RGB合成するプログラムについて。

#1

投稿記事 by いちこ » 7年前

現在、3枚のグレースケールRAW画像を読み込み、「ヒストグラム伸張化」を行ってから、RGB合成を行う画像処理プログラムを作成しています。

そこで、合成したカラー画像が、どうしても紫がかった色になってしまい困っています。


3枚の原画像それぞれに、ヒストグラム伸張化の処理を行うのですが…
この処理では、画像の輝度値の最大レベルmaxと最小レベルminを設定し
a' = (a-min)*255/(max-min)
という式で、輝度値aをa'に補正しています。

この処理を行うと、ヒストグラムが無理やり引き延ばされて、ある輝度値と、次の輝度値とに間ができてしまいます。(伝わりにくければすみません)
3枚の原画像それぞれでmaxとminの値が違うので、作成するRGB画像の、ある画素には例えばRの値しか入っていないということになってしまうと思うのです。

これが、原因かと考えたのですが、どうなのでしょうか。
いろいろと調べてみたところヒストグラム伸張化を行ってカラー画像を作成できるらしいのですが…何度確認してもプログラムのおかしいところを見付けることができません。

非常にわかりにくい文章であるとは思いますが、アドバイスだけでもいただけると嬉しいです。
どうかよろしくお願いします。

ホヅミ
記事: 110
登録日時: 9年前

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#2

投稿記事 by ホヅミ » 7年前

お願いします!プログラムを……プログラムを貼り付けてください!

コード:

で囲われたプログラムが読みたいです!

アバター
asd
記事: 318
登録日時: 9年前

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#3

投稿記事 by asd » 7年前

元のプログラムとRAW画像がないので一般的な回答しかできませんが、

・ヒストグラム伸長化を行わずにRGB合成(Rチャネル、Gチャネル、Bチャネルのグレースケール画像からRGB画像を作るということですよね?)を行った場合に紫がかった状態になっていないか
→何もせずに紫がかった状態ならば、ヒストグラム伸長化の処理は原因でないと考えます

・上で問題なかった場合、ヒストグラム伸長化したあとのグレースケール画像が明暗のくっきりしたグレースケール画像になっているか
→この時点で明暗のくっきりしていない画像になっていない場合、ヒストグラム伸長化の処理がおかしい可能性があります

ここからは推測ですが、ヒストグラム伸長を行う計算においてint型を使って計算しているために誤差が発生している可能性はないでしょうか。
挙げていただいた式でいうと、a、max、minをそれぞれfloatなりdoubleにキャストして小数での演算を行い、
最後にint型に丸めて最終画素値とする感じです(たとえば以下のような感じに)
#あまり効果はないかもしれませんが^^;

コード:

int a2 = (int)( (double)(a-min)*255.0/(double)(max-min) );
Advanced Supporting Developer
無理やりこじつけ(ぉ

いちこ
記事: 62
登録日時: 8年前
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#4

投稿記事 by いちこ » 7年前

>>ホヅミさん
返信ありがとうございます。
失礼しました。
ソースコードを下に記します。

>>asdさん
RAW画像は、衛星画像です。

先ほど新しい事実が発覚したのですが… ><;;
以前、同じプログラムを作成した方のものも実行してみたのですが、以前はきちんとカラー画像が作成できていたプログラムとまったく同じものを使用しても、色みのおかしい画像ができてしまいました。
PCが違うのですが、これは原因のうちに入るのでしょうか。

キャストですか…あまり問題はないと思ったのですが、どうでしょうか。
プログラムを確認していただけるとうれしいです。
よろしくお願いします。

コード:

#include<stdio.h>
#include<stdlib.h>

int main(void)
{  
  static unsigned char buf_1[800*800], buf_2[800*800], buf_3[800*800] ,buf[800*800*3];
  FILE *file_1,*file;
  int i,max,min;
  

  file_1=fopen("sample1.gray","rb");
  max=201;
  min=85;
  for(i=0;i<800*800;i++)
    {
      fread(&buf_1[i],1,1,file_1);
      buf_1[i]=(255/(max-min))*(buf_1[i] - min);
    }
  fclose(file_1);
  
  
  
  file_1=fopen("sample2.gray","rb");
  max=106;
  min=27;
  for(i=0;i<800*800;i++)
    {
      fread(&buf_2[i],1,1,file_1);
      buf_2[i]=(255/(max-min))*(buf_2[i] - min);
    }
  fclose(file_1);
  

  file_1=fopen("sample3.gray","rb");
  max=138;
  min=24;
  for(i=0;i<800*800;i++)
    {
      fread(&buf_3[i],1,1,file_1);
      buf_3[i]=(255/(max-min))*(buf_3[i] - min);
    }
  fclose(file_1);
  

  for(i=0;i<800*800;i=i+1)
    {
      buf[i*3]=buf_3[i];
      buf[i*3+1]=buf_2[i];
      buf[i*3+2]=buf_1[i];
    }
  

  file= fopen("RGB.rgb","wb");
  for(i=0;i<800*800*3;i++)
    {
      fwrite(&buf[i],1,1,file);
    }
  fclose(file);
  
  return EXIT_SUCCESS;
}


beatle
記事: 1280
登録日時: 8年前
住所: 埼玉
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#5

投稿記事 by beatle » 7年前

例えばココが怪しいと思います。

コード:

(255/(max-min))*(buf_1[i] - min)
max, min, buf_1はいずれも整数型です。そこで、計算時にはint型へ昇格されます。
従って、255と(max-min)、(buf_1 - min)はすべてint型として扱われます。

特に割り算が問題で、整数/整数は小数点以下が「切り捨てられ」て、整数として結果が求まります。
max-minが256以上ですと、255/(max-min)が常に0となります。
そうでなくとも、かなりの誤差が出ることが予想されます。

今回のmax-minは116, 79, 114なので、255/(max-min)が常に0になるということはないみたいですね。

いちこ
記事: 62
登録日時: 8年前
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#6

投稿記事 by いちこ » 7年前

>>beatleさん
返信ありがとうございます。

なるほどです…ではfloat型で宣言して計算するのがよいのでしょうか…><;;
また、buf[]自体はcharですが、計算後代入するのは、文字型に明示的にキャストしてからのほうがよいでしょうか?

beatle
記事: 1280
登録日時: 8年前
住所: 埼玉
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#7

投稿記事 by beatle » 7年前

良いのかどうか、聞く前にやってみてください。
僕だって、floatにして計算したら症状が改善するかなんて分かりません。
変更は簡単ですよね?

いちこ
記事: 62
登録日時: 8年前
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#8

投稿記事 by いちこ » 7年前

>>beatleさん
返信ありがとうございます。
すみません、やってみました。

maxとminをfloat型で宣言し、
例えば

コード:

buf2[i]=(char)((255.0/(max-min))*((float)buf[i]-min))
のように変えてみたのですが、出力画像に変化はありませんでした。

beatle
記事: 1280
登録日時: 8年前
住所: 埼玉
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#9

投稿記事 by beatle » 7年前

asd さんが書きました:・ヒストグラム伸長化を行わずにRGB合成(Rチャネル、Gチャネル、Bチャネルのグレースケール画像からRGB画像を作るということですよね?)を行った場合に紫がかった状態になっていないか
→何もせずに紫がかった状態ならば、ヒストグラム伸長化の処理は原因でないと考えます

・上で問題なかった場合、ヒストグラム伸長化したあとのグレースケール画像が明暗のくっきりしたグレースケール画像になっているか
→この時点で明暗のくっきりしていない画像になっていない場合、ヒストグラム伸長化の処理がおかしい可能性があります
この質問にも無視せず答えて下さいね。

いちこ
記事: 62
登録日時: 8年前
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#10

投稿記事 by いちこ » 7年前

>>beatleさん
返信ありがとうございます。
それについては、
まず補正を行う前に合成を行うと、正しいはずの出力画像よりも青っぽい感じで出力されてしまいました。

また、伸張化を行ったあとのGRAY画像は、明暗のくっきりした画像になっていました。

これにより、原画像ファイルのデータが壊れているかもしれないと思い、新しく画像を取ってきたのですが、実行結果は変わりませんでした。

beatle
記事: 1280
登録日時: 8年前
住所: 埼玉
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#11

投稿記事 by beatle » 7年前

rgbの順番を間違えている、とかはないでしょうか?

コード:

      buf[i*3]=buf_3[i];
      buf[i*3+1]=buf_2[i];
      buf[i*3+2]=buf_1[i];
つまりここの順番が正しいのかどうか、です。

いちこ
記事: 62
登録日時: 8年前
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#12

投稿記事 by いちこ » 7年前

>>beatleさん
返信ありがとうございます。

それについても確認しましたが、正しいはずです。
3つの画像は衛星画像で、sample1はバンド1、sample2はバンド2、sample3はバンド3の画像です。
トゥルーカラーに合成したいので、Rにはバンド3、Gにはバンド2、Bにはバンド1を割り当てました。

beatle
記事: 1280
登録日時: 8年前
住所: 埼玉
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#13

投稿記事 by beatle » 7年前

後考えられるのは、画像の閲覧アプリが当時と違っていて、RGBの順番が実は違う、という感じでしょうか。

いちこ
記事: 62
登録日時: 8年前
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#14

投稿記事 by いちこ » 7年前

>>beatleさん
返信ありがとうございます。
閲覧アプリには「ImageMagick」を使用しています。
RGBの順番は間違っていないはずです。


今のコードは下のようになっています。
アドバイスだけでもよいので、どなたかお願い致します。

コード:

#include<stdio.h>
#include<stdlib.h>

int main(void)
{  
  static unsigned char buf_1[800*800], buf_2[800*800], buf_3[800*800] ,buf[800*800*3];
  FILE *file_1,*file;
  int i;
  float max,min,a;
  
  
  file_1=fopen("sample1.gray","rb");
  max=201.0;
  min=85.0;
  for(i=0;i<800*800;i++)
    {
      fread(&buf_1[i],1,1,file_1);
      a=buf_1[i]-0.0;
      buf_1[i]=(char)((255.0/(max-min))*(a - min));
    }
  fclose(file_1);
  
  
  
  file_1=fopen("sample2.gray","rb");
  max=106.0;
  min=27.0;
  for(i=0;i<800*800;i++)
    {
      fread(&buf_2[i],1,1,file_1);
      a=buf_2[i]-0.0;
      buf_2[i]=(char)((255.0/(max-min))*(a - min));
    }
  fclose(file_1);


  
  file_1=fopen("sample3.gray","rb");
  max=138.0;
  min=24.0;
  for(i=0;i<800*800;i++)
    {
      fread(&buf_3[i],1,1,file_1);
      a=buf_3[i]-0.0;
      buf_3[i]=(char)((255.0/(max-min))*(a - min));
    }
  fclose(file_1);
  

  for(i=0;i<800*800;i++)
    {
      buf[i*3]=buf_3[i];
      buf[i*3+1]=buf_2[i];
      buf[i*3+2]=buf_1[i];
    }
  
  
  file= fopen("RGB.rgb","wb"); 
  for(i=0;i<800*800*3;i++)
    {
      fwrite(&buf[i],1,1,file); 
    }
  fclose(file); 
  
  return EXIT_SUCCESS; 
}


beatle
記事: 1280
登録日時: 8年前
住所: 埼玉
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#15

投稿記事 by beatle » 7年前

RGBの順番が合ってると仰っているので余計なお世話かもしれませんが、本当にそうなのかを確認するために、

buf_3の全要素を255、buf_2,buf_1の全要素を0として、真っ赤な画像になることを確認する。
同様に、buf_2, buf_1それぞれを255に、他を0にした画像を作り、それぞれ緑、青の画像になることを確認する。

という作業をやってみたら如何でしょうか。

最後のあたりでbufにbuf_3, buf_2, buf_1を書き込むところを、buf_3の代わりに255を使い、buf_2とbuf_1の代わりに0を使えばいいでしょう。

アバター
asd
記事: 318
登録日時: 9年前

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#16

投稿記事 by asd » 7年前

しばらく離れている間に大分進んでるっΣ(´д`|||
いちこ さんが書きました:>>beatleさん
返信ありがとうございます。
それについては、
まず補正を行う前に合成を行うと、正しいはずの出力画像よりも青っぽい感じで出力されてしまいました。
念のため確認ですが、補正を行う前に合成した方法としては、
以下のような感じでピクセル単位でfreadしたものを一旦float型に変換し、キャストでcharに戻したということでよいでしょうか。

コード:

  file_1=fopen("sample1.gray","rb");
  max=201.0;
  min=85.0;
  for(i=0;i<800*800;i++)
    {
      fread(&buf_1[i],1,1,file_1);
      a=buf_1[i]-0.0;
      //buf_1[i]=(char)((255.0/(max-min))*(a - min));
      buf_1[i]=(char)a;//手を入れずにそのまま格納
    }
/*以下、残りのチャネルも同様*/
上記の推測で正しいならば、float型変数aを”介さずに”そのままbuf_1のデータを格納してトルゥーカラー画像を合成してもらえないでしょうか。

コード:

  file_1=fopen("sample1.gray","rb");
  max=201.0;
  min=85.0;
  for(i=0;i<800*800;i++)
    {
      fread(&buf_1[i],1,1,file_1);//読み込んだままを使う
    }
/*以下、残りのチャネルも同様*/
これで色がおかしくならないのならば、float型に変換している時点で値がおかしくなっているのではと疑っています。

コード:

a=buf_1[i]-0.0;
この部分でbuf_1であらわされている本来の値と変換後のaが実は違っているのではないかなと。
#そうでないとヒストグラム伸張化なしでも色がおかしくなる原因が謎になってしまうので。freadした時点で壊れてる?

実際のrawデータがあればこちらでも試して見られるのですが(ノ∀`)

beatleさんも指摘しているように、元の画像をただ読みこんでそのまま書き出し、それをRGB合成したときに
正しくRGB合成された画像が得られないと、ヒストグラム伸張化の結果も正しく表示できないので、
まずはRGB合成が正しくできるところまでこぎつけたいですね(`・ω・´)
Advanced Supporting Developer
無理やりこじつけ(ぉ

いちこ
記事: 62
登録日時: 8年前
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#17

投稿記事 by いちこ » 7年前

>>beatleさん
返信ありがとうございます!

おっしゃるとおり、下のように確認してみました。

コード:

 for(i=0;i<1600*1600;i++)
    {
      buf[i*3]=255;
      buf[i*3+1]=0;
      buf[i*3+2]=0;

    }
そうすると、どうやらGRBの順番に対応しているようでした…!!
「.rgb」の画像のフォーマットを調べてみるとRGBの順番だとあったのでとても不思議ですが、とにかくGRBの順番に変えると、トゥルースカラーの画像を表示させることができました!
長い間ご指摘くださってありがとうございました ><

フォーマットの方の原因を調べてきます。

いちこ
記事: 62
登録日時: 8年前
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#18

投稿記事 by いちこ » 7年前

>>asdさん
返信ありがとうございます!
どうやら、RGBへの各バンドの対応がおかしかったようです…。
「.rgb」の画像のフォーマットどおりに組んだつもりだったのですが…今、フォーマットについて調べ直しているところです。
気にかけてくださってありがとうございます。

beatle
記事: 1280
登録日時: 8年前
住所: 埼玉
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#19

投稿記事 by beatle » 7年前

動くようになってよかったですね。

いちこさんのソースコードにはいくつか問題があります。
  • 重複が多い。実質的にsample1, sample2, sample3の処理は同じです。
  • fread, fwiteが1バイトずつの処理しかしておらず、普通でない書き方になっている。速度的にもあまり良くない。
いちこさんが、プログラムの勉強がしたいと思うなら、ソースコードの改善策について質問してください。
(紫になってしまう問題とは大幅に異なる質問ですから、新規スレッドを建てたほうがいいかもしれません。「プログラムの改善策を教えて下さい」とか。)

ただし、いちこさんがプログラムの勉強はあまりする気はなく、動けばいいや、という気持ちなら質問しないでください。
「プログラムの改善には正直興味がないが、聞けるんだったら一応聞いておくか」という気持ちで質問すると回答者の皆様に失礼です。
よろしくお願いします。

いちこ
記事: 62
登録日時: 8年前
連絡を取る:

Re: グレースケールのRAW画像を、RGB合成するプログラムについて。

#20

投稿記事 by いちこ » 7年前

>>beatleさん
返信ありがとうございます。

勉強したい気持ちはおおいにあります。
しかしまずはもう少し自分で考えてから、質問させていただきます。
気にかけてくださってありがとうございます。

いろいろ考えてくださってありがとうございました。
精進します!


閉鎖

“C言語何でも質問掲示板” へ戻る