とらりもんHOME  Index  Search  Changes  Login

C言語による画像処理: 色の抜き出し/入れ換え/反転

筑波大学農林工学系 奈佐原(西田)顕郎

Note: 以下, プロンプトを$で表すので, 以下の説明で, $は打ち込まなくてよい。

色チャンネルの抜き出し

カラー画像は,基本的には赤(Red), 緑(Green), 青(Blue)の3つの色情報の組み合わせでひとつのピクセルの色が表現されます.ここから,たとえば赤の情報だけを抜き出すと,赤色のセロハンを通して見たようなモノクロ(単色)画像になります.それをやってみましょう.

以下の方針で,各自でプログラムしてみてください.

  • 基本的な構造は前回の"reverse_LR.c"と同じ.
  • 左右の反転はしないので,1ラインをまとめて読み込む必要はありません.そこで,前々回のcutimage.cのように,ループの部分を
for (y=0; y<YL; y++)
   for (x=0; x<XL; x++)
     {fread(data, BPP, 1, stdin);
      fwrite(data, 1, 1, stdout);
     }

と変更し,さらに配列data[ ]の宣言を,

unsigned char data[BPP]

と変更しましょう.

  • ファイル名はcolor_extract.cとしましょう.
  • 出力画像ファイル(今回はPPM形式ではなくてPGM形式となる)のヘッダの最初の行は,そのままの文字列(P6)を出力するのではなく,かわりにP5を出力しましょう.なぜなら...PNM形式の仕様では,P6はカラーRGB画像(それをPPMと呼ぶ).P5はモノクロ画像(PGMと呼ぶ).
  • ピクセルデータの出力(fwriteの部分)で,3バイト(プログラムの中ではBPP(byte per pixelの略)として定義されている)ではなく1バイトの出力としましょう.なぜなら...3バイトのうち最初の1バイトが赤.それを抜き出すとモノクロ(単色)画像になる.
  • コンパイル結果をcolor_extractとし,入力画像lake.ppmと出力画像lake_red.pgmをリダイレクトで指定しましょう.

その結果,次のようにlake_red.pgmができますが,もとのlake.ppmに比べて,ヘッダー部分は除き,大きさが1/3になります.

-rw-r--r--    1 xxxx xxxx     1440060 xx月 xx xx:xx lake.ppm
-rw-r--r--    1 xxxx xxxx      480060 xx月 xx xx:xx lake_red.pgm

lake_red.jpg ←赤チャンネルを抜き出した結果.

同様に,緑,青も抜き出して,並べてみましょう. ヒント: ピクセルデータの出力で,dataをdata+1にすれば緑の抜き出しになります.

lake_red.jpg ←赤チャンネル lake_grn.jpg ←緑チャンネル lake_blu.jpg ←青チャンネル

上の結果をみると,明らかに青チャンネルが他に比べて明るいですが,なぜでしょうか?

色の入れ換え

カラー画像の各ピクセルは,赤・緑・青の順番で1バイトづつ各色のデータが記述されていますが,この順番を,例えば青・緑・赤に入れ換えるとどうなるでしょうか? 以下の方針で,各自でプログラムしてみてください:

  • 基本的な構造は上の"color_extract.c"と同じ.(ただし,チャンネル抽出はしないので,ヘッダーはP6のまま出力)
  • ファイル名はcolor_swap.cとしよう.
  • 各ピクセルにつき,fwriteを3回行うことで,青・緑・赤の順に1バイトづつ出力する.各fwriteの中で,データの位置をどのように指定するべきか,考えてください.
  • コンパイル結果をcolor_swapとし,入力画像lake.ppmと出力画像lake_swap.ppmをリダイレクトで指定する.

lake_swap.jpg←赤と青を入れ換えた結果.

同様に,赤・青・緑や緑・赤・青などの組み合わせ(ぜんぶで3!=6通りあり得る)を試してみましょう.

明るさの反転

各ピクセルの各色は0から255までの数字で,大きいほど明るい状況を表しています.そこで,これをひっくりかえして,大きな値ほど「暗くなる」ようにしてみましょう.

まず,ひとつのチャンネルのみに注目して,たとえば赤チャンネルだけ抜き出し,反転させてみましょう.方針は,

  • 基本的な構造は上の"color_extract.c"と同じ.
  • freadの直後で,以下の行を入れる.
data[0]=255-data[0];
data[1]=255-data[1];
data[2]=255-data[2];

lake_red_reverse.jpg←赤チャンネルを抽出して明るさを反転した結果.

こんどは,3つのチャンネルを全て反転した結果をカラーで出してみましょう.ヒントは無しです.自分で考えてやってみてください.

lake_reverse.jpg←全チャンネルの明るさを反転した結果.

Last modified:2022/08/13 23:18:51
Keyword(s):
References:[画像解析入門] [C言語による画像処理: 明るさの調整・GIFアニメ]