こんにちは。くらくです。
今回は、プログラム上ではどのように画像が表現されるか、表色系や色空間について書いていきたいと思います。
色について
現実世界で人間が視覚で捉える世界は様々な色によって彩られています。
例えば、風景をスマホのカメラで撮影し、それをPCで開いてみると、撮影した風景がデジタル画像として表されることになります。
デジタル画像はRGB(赤、緑、青)の3つの原色で表されます。
画像処理を行う段階で、グレースケール画像へ変換を行ったり、HSV変換、Lab変換など、RGBではない表色系に変換を行い画像処理を行うことはよくあります。
デジタル画像とは
まず、スマホで撮影した画像をみてみましょう。(ミドラーシュかわいい)
ここで、撮影した画像を拡大してみましょう。
ブロックノイズができていますね。わかりやすくするためこれをもとに説明すると、デジタル画像は画素が格子状に並んでいるもの、という風に表現することができます。
この格子が細かければ細かいほど、解像度が高い、ということになります。
(大雑把ではありますが下図のような感じ)
デジタル画像は、画素(pixel)というものの集合体です。
カラーのデジタル画像では、格子状に並んだ画素の一つ一つがB、G、Rの値を持ちます。
一つの画素は、保有するBGRの値から表現する色を決定します。
画素がもつ要素の次元をチャンネルと呼びます。
画素一つが、BGRの3つの要素をもつカラー画像の場合、これは3チャンネルであると言えます。
このBGRの値を色値といい、0~255の範囲で値を持ちます。
0が黒色、255が白色になります。例えば、
- (B,G,R) = (255, 255, 255) の場合は白
- (B,G,R) = (0, 0, 0)の場合は黒
- (B,G,R) = (0, 255, 0)の場合は緑
となります。
カラー画像の場合は輝度値の3つの値から、その画素の色を決定し、表現します。
プログラム上での画像
結論から話しますと、プログラム上では、
画像は2次元配列として表現されます。
プログラム上では、画像はOpenCVに用意されている行列を管理する構造体、Matクラスを用いて扱います。
Matクラスは幅や高さなど、様々なプロパティを持ち、ライブラリ関数によってそれらを取得することが可能です。
(Matクラスに関しては別記事でもう少し深く書くかもしれません!)
以上を念頭に置いて、まず座標系のお話をしていきます。
数学等でグラフを書く際に用いる座標系は以下のようなものだったと思います。原点が左下にあり、右上に行くほど値が大きくなるといった感じでしたね。
対して、画像は下図のような座標系で表現されます。
画像は高さと幅を持ちます。上図で言えばxが幅、yが高さになります。画像の左上が原点となり、xは画像の幅-1の値を、yは画像の高さ-1の値を持ちます。
仮に入力画像をMat型で宣言したimgという変数に格納したとすると、原点にアクセスするのであれば、imgの配列要素の[0,0]にアクセスすれば良いです。(つまりimg[0][0])
カラー画像の場合、img[0][0]はB, G, Rの順で色値の3つの値をもちます。画素を変数pixelとして、3要素ベクトルVec3bで定義すると、
- pixel[0]に青の値
- pixel[1]に緑の値
- pixel[2]に赤の値
が格納されます。
RGBとよく言われますが、Mat型の場合、B,G,Rの順で格納されます!間違えやすいので注意!
まとめ
最後まで目を通してくださりありがとうございました。
デジタル画像の基本、というテーマでしたが、今回はこの辺りで終わりにしたいと思います。
まとめると、
- カラーのデジタル画像はRGBで色を表現する
- 画像は画素の集合。画素の要素の次元をチャンネルといい、その値を色値という
- 画像は2次元配列で表現される
という感じになります。
概念的にはわかったけど、実際にどうやってプログラム書くんだよ!って思われている方もいると思いますので、その辺りを次回に書いていきたいと思います。
また読んでいただけたら嬉しいです。
ps:
うまく説明できているのか不安です。わかりにくい点等ありましたらコメントくださると幸いです。
輝度値と色値を混同していたので修正しました