カラー画像データは各データが8bit(0~255の256諧調)のR, G, Bの要素からなる24bitカラー画像や、さらに透過率(A)を追加しR, G, B, Aの要素からなる32bitカラー画像があります。
Pythonでは、このカラー画像のデータの並びが使用するモジュールによって異なり、PillowではRGB や RGBA の並びとなり、NumPyのndarrayで画像データを管理しているOpenCVでは BGR や BGRA の並びとなっています。
つまり、カラー画像をPillowとOpenCV間で変換する場合、画像データの並びも RGB⇔BGRやRGBA⇔BGRA と変換する必要があります。
これを間違うと、RとBが入れ替わった状態となるため、下図のように変な画像になってしまいます。
(正しい画像データの並び)
(間違った画像データの並び)
カラー画像データの事前準備
Pillowでカラー画像を開き、24bitのカラー画像と32bitのカラー画像を用意し、これをNumPyのndarrayへ変換します。
import numpy as np
from PIL import Image
import cv2
# Pillowでカラー画像(RGB)を開く
pillow_rgb24 = Image.open("Mandrill.bmp")
# 24bitカラー(RGB)から32bitカラー(RGBA)へ変換
pillow_rgb32 = pillow_rgb24.convert("RGBA")
###############################
# PillowからNumPyのndarrayへ変換
numpy_rgb24 = np.array(pillow_rgb24) # 24bitカラー(RGB)
numpy_rgb32 = np.array(pillow_rgb32) # 32bitカラー(RGBA)
上記のようにPillowで開いたカラー画像をNumPyへ変換しただけの状態の画像をOpenCVのimshowで表示すると、RとBが入れ替わった画像が表示されます。
cv2.imshow("Image", numpy_rgb24)
cv2.waitKey()
(表示結果)
NumPyでRGB→BGR, RGBA→BGRAへ変換
Pillowのカラー画像をNumPyへ変換した直後のデータは
24bitカラーのとき
[[[R, G, B], [R, G, B], [R, G, B]],
[[R, G, B], [R, G, B], [R, G, B]],
[[R, G, B], [R, G, B], [R, G, B]]]
32bitカラーのとき
[[[R, G, B, A], [R, G, B, A], [R, G, B, A]],
[[R, G, B, A], [R, G, B, A], [R, G, B, A]],
[[R, G, B, A], [R, G, B, A], [R, G, B, A]]]
のように、RGBやRGBAの順で並んでいます。
これをOpenCVで使うときは、データの並びをBGRやBGRAの順へ変換する必要があります。
具体的には
24bitカラーのとき
[[[B, G, R], [B, G, R], [B, G, R]],
[[B, G, R], [B, G, R], [B, G, R]],
[[B, G, R], [B, G, R], [B, G, R]]]
32bitカラーのとき
[[[B, G, R, A], [B, G, R, A], [B, G, R, A]],
[[B, G, R, A], [B, G, R, A], [B, G, R, A]],
[[B, G, R, A], [B, G, R, A], [B, G, R, A]]]
のようにR, G, Bのデータを並び変える必要があります。
このRGB→BGR、RGBA→BGRAの変換は以下のように行います。
# NumPyでRGBからBGRへ変換(24bitの場合) その1
numpy_bgr24 = numpy_rgb24[:, :, ::-1]
# NumPyでRGBからBGRへ変換(24bitの場合) その2
numpy_bgr24 = numpy_rgb24[:, :, [2, 1, 0]]
# RGBAからBGRAへ変換(32bitの場合)
numpy_bgr32 = numpy_rgb32[:, :, [2, 1, 0, 3]]
OpenCVでRGB→BGR, RGBA→BGRAへ変換
OpenCVの画像データはNumPyのndarrayなので、PillowからNumPyへ変換した画像データは、そのままOpenCVの関数で処理することができます。
# cvtColorで24bitカラー(RGB)から24bitカラー(BGR)へ変換
numpy_bgr24 = cv2.cvtColor(numpy_rgb24, cv2.COLOR_RGB2BGR)
# cvtColorで32bitカラー(RGBA)から32bitカラー(BGRA)へ変換
numpy_bgr32 = cv2.cvtColor(numpy_rgb32, cv2.COLOR_RGBA2BGRA)
24bitか?、32bitか?を調べる
カラー画像データの並びを入れ替える時は、24bitカラーのときと、32bitカラーのときとで、処理を変える必要があるため、NumPy配列(ndarray)が24bitと32bitのどちらなのか?を調べる必要があります。
それには、NumPyのshapeを取得しshape[2]の値が3であれば24bit、4であれば32bitとなります。
# 24bitか?32bit?かを調べる
print(numpy_rgb24.shape)
print("チャンネル数 = ", numpy_rgb24.shape[2])
print(numpy_rgb32.shape)
print("チャンネル数 = ", numpy_rgb32.shape[2])
(実行結果)
コメント