NumPyでRGB画像の色チャンネルを分離して単色化、白黒化、色交換
Python, NumPyを使った画像処理において、RGB画像は行(高さ) x 列(幅) x 色(3)の三次元の配列ndarray
、白黒画像は行(高さ) x 列(幅)の二次元の配列ndarray
になる。
ただの配列なのでそれぞれの色チャンネルに対する処理も簡単。
- 単色化
- 白黒化(グレースケール化)
- 色交換(色の入れ替え)
について説明する。
画像ファイルの読み込みや保存については以下の記事を参照。
単色化
他の色の値を0にして単色画像を生成する。さらに横に並べて結合する。
結合についての詳細は以下の記事参照。
from PIL import Image
import numpy as np
im = np.array(Image.open('data/src/lena_square.png'))
im_R = im.copy()
im_R[:, :, (1, 2)] = 0
im_G = im.copy()
im_G[:, :, (0, 2)] = 0
im_B = im.copy()
im_B[:, :, (0, 1)] = 0
# 横に並べて結合(どれでもよい)
im_RGB = np.concatenate((im_R, im_G, im_B), axis=1)
# im_RGB = np.hstack((im_R, im_G, im_B))
# im_RGB = np.c_['1', im_R, im_G, im_B]
pil_img_RGB = Image.fromarray(im_RGB)
pil_img_RGB.save('data/dst/lena_numpy_split_color.jpg')
source: numpy_image_color.py
白黒化(グレースケール化)
ここでは輝度信号Yを計算して白黒画像(グレースケール画像)を生成する。Yの計算式については以下のページ参照。
im_gray = 0.299 * im[:, :, 0] + 0.587 * im[:, :, 1] + 0.114 * im[:, :, 2]
print(im.dtype)
print(im_gray.dtype)
# uint8
# float64
print(im.shape)
print(im_gray.shape)
# (512, 512, 3)
# (512, 512)
pil_img_gray = Image.fromarray(np.uint8(im_gray))
pil_img_gray.save('data/dst/lena_numpy_gray.jpg')
source: numpy_image_color.py
小数点を使った計算によって型dtype
がfloat
になるので、Pillowでの保存時はuint8
に変換する。
RGB画像(行(高さ) x 列(幅) x 色(3)の三次元の配列ndarray
)から白黒画像(行(高さ) x 列(幅)の二次元の配列ndarray
)を算出しているが、Pillowを使って保存save
すると、特に指定しなくても白黒画像として保存してくれる。
PillowやOpenCVの関数を使ってカラー画像を白黒画像に変換することもできる。以下の記事を参照。
色交換(入れ替え)
RとBを入れ替える。
im_swap = im.copy()
im_swap[:, :, 0], im_swap[:, :, 2] = im[:, :, 2], im[:, :, 0]
pil_img_swap = Image.fromarray(im_swap)
pil_img_swap.save('data/dst/lena_numpy_swap_color.jpg')
source: numpy_image_color.py