目的
ディジタルカラー画像の画素値は光の三原色であるBGR値によって表現されている.これはディスプレイやスクリーンに画像を表示する際に扱いやすい表現であるが,画像処理をする場合には必ずしも扱いやすい表現ではない.ここでは,色の表現の仕方を変更する表色系変換について学ぶ.
説明
輝度
まず,人間の視覚特性について考えよう.図の3つの四角形が24bitカラーで表現されているとすると,左の四角形の色はB: 255, G: 0, R: 0である.同様に中央の四角形の色はB: 0, G: 255, R: 0であり,右の四角形の色はB: 0, G: 0, R:255である.
3つの四角形は同一レベルで光らせているが,ほとんどの人には,緑が1番明るく見え,赤が次に明るく見え,青が1番暗く見えると思われる.BとGとRに対して,人間が感じる明るさの比は約1: 6: 3であることが知られている.その比率に合わせて重みをつけて加算したものが輝度と呼ばれる量になり,BGRから輝度Yを求める変換式は$$Y=0.114B + 0.587G + 0.299R$$となる.この変換式はカラー画像からグレースケール画像に変換するときに使用される.
カラーグレースケール変換
OpenCVを使用してカラー画像をグレースケール画像に変換するには以下のように記述すればよい.
19行目でカラー画像を読み込み,20行目でグレースケール画像に変換し,23行目で表示している.実行すると元のカラー画像と変換されたグレースケール画像が表示される.
HSV表色系
BGRによって表現されている色を画像処理をする際に扱いやすい表現に変更してみよう.色の表現方法は数多くあるが,ここでは画像処理で色を扱う際に使用されることが多いHSV表色系について考えよう.Hは色相(Hue)を,Sは彩度(Saturation)を,Vは明度(Value)と呼ばれる量である.
明度V
BGRから輝度を求める際には人間が感じる明るさの比率に応じて変換式\(Y=0.114B + 0.587G + 0.299R\)を使用した.HSV表色系ではBGRの最大値を明るさを表す量(明度)として使用する.$$V = \max(B, G, R)$$BGRが全て255のとき,すなわち色が白のときに輝度は255となり最大となった.一方,Bが255でGとRは0であっても明度は255となり最大となる.青はそれ程明るい色ではなかったため少しおかしいと思うかもしれないが,このように明るさを表現する方法もある.
彩度S
BGRの値が全て同じ場合,色は灰色となる.一方,BGRの値に差があるとき,色は鮮やかになる.色の鮮やかさを表す彩度はBGRの最大値と最小値の差として\(\max(B, G, R) – \min(B, G, R)\)と表すことができる.これをBGRの最大値で割れば,0から1の間の値になるように正規化することができる.この正規化された量\(\frac{\max(B, G, R) – \min(B, G, R)}{\max(B, G, R)}\)を彩度とする.分母\(\max(B, G, R)=0\)のとき,すなわちBGRが全て0のとき,色は黒である.そのため,彩度は0とすればよい.以上より,彩度Sは以下のように求めることができる.$$ S = \begin{cases} \frac{\max(B, G, R) – \min(B, G, R)}{\max(B, G, R)} & (\max(B, G, R)\neq0) \\ 0 & (\max(B, G, R)=0) \end{cases}$$
色相H
色合いを表す色相は角度で表現されることが多い.以下の図のように赤が0度の位置,緑が120度の位置,青が240度の位置となるように色相を表現てみよう.
\(\max(B, G, R)=R\)のとき,赤が一番強く入っていることになるため,このとき色相が-60度から60度の範囲となるようにしよう.緑が正の方向,青が負の方向であるため,\(G-B\)が正のとき,色相が0度から60度の範囲に,\(G-B\)が負のとき,色相が-60度から0度の範囲になるようにすればよい.\(G-B\)を\(\max(B, G, R) – \min(B, G, R)\)で割ると−1から1の間の値に正規化することができ,さらに60をかけると−60度から60度の間の値とすることができる.以上より,\(\max(B, G, R)=R\)のとき,色相Hは以下のように表現することができる.$$H = \frac{60(G-B)}{\max(B, G, R) – \min(B, G, R)}$$
同様に,\(\max(B, G, R)=G\)のとき,色相が60度から180度となるようにするには,\(B-R\)を\(\max(B, G, R) – \min(B, G, R)\)で割り,60をかけ,120を足せばよい.$$H = \frac{60(B-R)}{\max(B, G, R) – \min(B, G, R)}+120$$
また,\(\max(B, G, R)=B\)のとき,色相が180度から300度となるようにするには,\(R-G\)を\(\max(B, G, R) – \min(B, G, R)\)で割り,60をかけ,240を足せばよい.$$H = \frac{60(R-G)}{\max(B, G, R) – \min(B, G, R)}+240$$
分母\(\max(B, G, R) – \min(B, G, R)=0\)のとき,すなわちBGRが全て同じ値のとき,色は灰色となる.このとき色相はないため,適当な値とすればよい.
まとめると,色相Hは以下のように求められる.$$ H = \begin{cases} \frac{60(G-B)}{\max(B, G, R) – \min(B, G, R)} & (\max(B, G, R)=R) \\ \frac{60(B-R)}{\max(B, G, R) – \min(B, G, R)}+120 & (\max(B, G, R)=G) \\ \frac{60(R-G)}{\max(B, G, R) – \min(B, G, R)}+240 & (\max(B, G, R)=B) \end{cases}$$
色による領域の抽出
以下のような画像を入力し,色相の範囲を指定して赤い領域を抽出してみよう.
26行目でカラー画像を読み込み,21行目でBGRからHSVに変換している.22行目から24行目で色相・彩度・明度を取り出している.この場合,HSVのデータ型はuint8となる.そのため,色相Hの値は0から359ではなく,0(0度を表す)から179(358度を表す)となり,彩度Sの値も0から1ではなく,0から255となる.26行目で色相の範囲を0度から20度または340度から360度と指定し,赤い領域を抽出し,29行目で描画している.実行すると以下のように表示され,赤い領域が抽出できていることが確認できる.
クロマキー合成
カラー画像を2枚読み込み,青い領域を背景として指定し,クロマキー合成をしてみよう.
27行目で前景画像を,28行目で背景画像を読み込み,29行目で前景画像のHSV値を求めている.30行目で色相を取り出し,31,32行目で色相をコピーした3チャンネル画像を作っている.33行目で色相の範囲を指定し,前景画像の青い領域に背景画像を,青以外の領域にはそのまま前景画像を設定している.実行すると以下のように表示され,クロマキー合成されていることがわかる.
色相の変更
カラー画像を読み込み,色相の値を変更してみよう.
20行目でカラー画像を読み込み,22行目でHSV値を求めている.23行目で色相を90度増やし,24,25行目で色相の値の範囲が0から179を越えた場合の後処理を行っている.26行目で色相の値を変更し,27行目でHSVからBGRを求め,30行目で画像をとして表示している.実行すると以下のように表示され,色相が90度増加していることが確認できる.
色相・彩度・明度の変更
カラー画像を読み込み,色相・彩度・明度を変更してみよう.
20行目でカラー画像を読み込み,21行目でHSV値を求めている.23行目から26行目で色相を90度減らし,28行目から31行目で彩度を10増やし,33行目から36行目で明度を30増やしている.38行目でHSVからBGRを求め,41行目で画像として表示している.実行すると以下のように表示され,色相・彩度・明度が変更された画像を表示される.
課題
課題0
カラー画像を読み込み,グレースケール画像に変換せよ.
課題1
カラー画像を読み込み,赤色の領域を抽出せよ.
課題2
カラー画像を読み込み,黄色の領域を抽出せよ.
課題3
カラー画像を読み込み,緑色の領域を抽出せよ.
課題4
カラー画像を読み込み,青色の領域を抽出せよ.
課題5
カラー画像を読み込み,オレンジ色の領域を抽出せよ.
課題6
前景画像と背景画像を読み込み,クロマキー合成せよ.
課題7
カラー画像を読み込み,色相を変更せよ.
課題8
カラー画像を読み込み,彩度を変更せよ.
課題9
カラー画像を読み込み,明度を変更せよ.