OpenCVではデフォルトのカラー画像はBGR色空間となりますが、一般的なRGB色空間に変換したり、HSV色空間に変換したり、あるいはグレースケールに変換したりということが自由に行えます。ここではOpenCVで読み込んだ画像に対してその色空間を変換する方法を説明します。
開発環境
- OpenCV 4.2.0
- Python 3.7.9
OpenCVにおける色空間
色空間とはカラー画像を表現するときに、カラーチャネルごとに分離したときの表現方法を表します。
OpenCVでカラー画像を表すときはBGR色空間がデフォルトになっており、各画素ごとに(青・緑・赤)の順番で画素値が格納されています。このほかにも色空間としてはHSV色空間といって、Hue(色相), Saturation(彩度), Value(明度)について、(Hue, Saturation, Value)の順番で格納する表現方法もあります。また、不透明度を表すアルファチャンネルを加えて色空間を表すことや、カラーチャネルを1つにだけにまとめてグレースケール画像とすることもできます。
詳細は以下の記事もご覧ください。
OpenCVを用いて、BGR色空間から通常よく用いられるRGB色空間に変換したり、あるいはBGR色空間からHSV色空間に変換したりということが自由に行えます。また、カラー画像からグレースケール画像への変換なども可能です。
OpenCVを用いた色空間の変換
OpenCVを用いた色空間の変換にはcvtColor関数を用います。
- cvtColor関数:cvtColor(src, code[, dst[, dstCn]]) -> dst
cvtColor関数のcode引数にColorConversionCodesを指定して色空間を何から何に変換するかを指定します。
BGR色空間からRGB色空間に変換する
BGR色空間からRGB色空間に変換するにはcode引数にCOLOR_BGR2RGBを指定します。これによりOpenCVでデフォルトのBGR色空間から一般的に用いられているRGB色空間に変換することができ、matplotlibなどの他のライブラリで画像を表示することも可能になります。
例えばカレントディレクトリに保存した画像(Lena.jpg)をOpenCVでBGR色空間のカラー画像として読み込んで、それをRGB色空間に変換してmatplotlibで表示させるコードは以下のようになります。
import cv2
import matplotlib.pyplot as plt
img_BGR = cv2.imread('Lena.jpg')
img_RGB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB)
plt.imshow(img_RGB)
plt.show()
逆にRGB画像からBGR画像に変換する場合は、cvtColor関数のcode引数にCOLOR_RGB2BGRを指定しますが、実際には青(B)と赤(R)を入れ替えるだけなのでCOLOR_BGR2RGBと同じ処理になります。
BGR色空間からHSV色空間に変換する
BGR色空間からHSV色空間に変換するにはcode引数にCOLOR_BGR2HSVもしくはCOLOR_BGR2HSV_FULLを指定します。COLOR_BGR2HSVで生成されるHSV色空間はHue(色相)は0-179の180段階で、Saturation(彩度)/Value(明度)は0-255の256段階で指定されたものになります。それに対して、COLOR_BGR2HSV_FULLで生成される色空間はHue(色相)が0-255の256段階になるという違いがあります。
では、試しにカレントディレクトリに保存した画像(Lena.jpg)をCOLOR_BGR2HSVとCOLOR_BGR2HSV_FULLでHSV色空間に変換してみて、Hue(色相)の最大値を取得してみましょう。
import cv2
img_BGR = cv2.imread('Lena.jpg')
img_HSV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HSV)
print('img_HSVのHue(色相)の最大値:' + str(img_HSV[:,:,0].max()))
img_HSV_FULL = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HSV_FULL)
print('img_HSV_FULLのHue(色相)の最大値:' + str(img_HSV_FULL[:,:,0].max()))
img_HSVのHue(色相)の最大値:179 img_HSV_FULLのHue(色相)の最大値:255
COLOR_BGR2HSVでHSV色空間に変換するとHue(色相)の最大値は179となり180段階となっているのに対して、COLOR_BGR2HSV_FULLでは256段階になっていることが分かります。本来のHSV色空間はHue(色相)の指定は360段階なので、COLOR_BGR2HSVで変換される180段階だとちょうどその半分となり変換が楽になるという特徴があります。
なお、HSV画像からBGR画像に戻す場合はcode引数にそれぞれCOLOR_HSV2BGRとCOLOR_HSV2BGR_FULLを指定します。
BGR色空間からグレースケールに変換する
BGR色空間からグレースケールに変換するにはcode引数にCOLOR_BGR2GRAYを指定します。
では、試しにカレントディレクトリに保存した画像(Lena.jpg)をグレースケールに変換してみて、画像を表すndarrayの形状(shape)がどのように変換するのかを見てみましょう。
import cv2
img_BGR = cv2.imread('Lena.jpg')
print('img_BGRの形状:' + str(img_BGR.shape))
img_GRAY = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY)
print('img_GRAYの形状:' + str(img_GRAY.shape))
img_BGRの形状:(512, 512, 3) img_GRAYの形状:(512, 512)
これよりカラー画像をグレースケールに変換することで、3つあったカラーチャネルが1つだけになっていることが分かります。
この形状の違いを利用してカラー画像かグレースケールが増加を判定することも可能です。読み込まれた画像がカラー画像かグレースケール画像かを判定して、カラー画像であればグレースケールに変換する処理を書いてみましょう。
import cv2
img = cv2.imread('Lena.jpg')
if len(img.shape) == 3:
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
カラー画像かグレースケール画像かの判定は画像を表すndarrayが第3軸を持つかどうかで判定しています。
これによりLena.jpgの画像が次のようにグレースケールに変換されました。
コメント