【Python入門】カラー画像をRGBに分離する方法

separating-colors numpy

カラー画像をnumpyを利用してRGBに分離する方法です。

カラー画像のデータは、光の3原色(赤R、緑G、青B)の色の強さを表現した三次元の配列でできています。
機械学習では、RGBを分離したり、入れ替えたりすることで新しい特徴量として使用することがあります。

カラー画像の読み込み

scilit-imageを利用して画像ファイルを読み込みます。

画像の読み込み方や、PillowやOpenCVを利用する方法は、次の記事をご覧ください。
>>【Python入門】画像の読み込み(Pillow、Scikit-image、OpenCV)

# Scikit-image
from skimage import io
%matplotlib inline

img = io.imread('RGB-sample.jpg')
io.imshow(img)   
図1: scikit-image 表示例

サンプルファイルを読み込むことができました。
180×180のJPEGファイルです。

サンプルファイルは、以下のリンクからダウンロードできます。

読み込んだデータimgは、numpyの配列(ndarray)です。
shapeメソッドで、配列の形状を確認できます。

img.shape

(180, 180, 3)と返ってきました。
(180行、180列、3色)の配列が読み込めています。

3色を分離していきます。

RGBチャンネルで表示(単色化)

配列の内容を確認します。
すべてを表示するには、配列が大きいので、左上から3行×3列を表示します。

numpy
In [1]:  img[:3, :3, :] 
Out[1]:  Array([[[55, 56, 60],
                 [54, 55, 59],
                 [51, 55, 58]],

                [[55, 56, 60],
                 [52, 56, 59],
                 [50, 55, 58]],

                [[53, 57, 60],
                 [52, 56, 59],
                 [50, 55, 58]]], dtype=uint8)

In [1]: numpy配列のスライスによる部分配列を表示
Out[1]: imgの内容

直感的にわかるように、配列を画像の位置に合わせてみます。

[[[55, 56, 60], [54, 55, 59], [51, 55, 58]],
 [[55, 56, 60], [52, 56, 59], [50, 55, 58]],
 [[53, 57, 60], [52, 56, 59], [50, 55, 58]]]

1つ目(1番外を囲む)の[]が縦、
2つ目(各行を囲む)の[]が横、
3つ目の数字が入っている[]が色
を表現しています。

イメージとしては、こんな感じです。
縦[ 横[ [色], [色], [色] ],
横[ [色], [色], [色] ],
横[ [色], [色], [色] ], ]

各色には、3つの数字が入っています。
色[0] に、Rの要素
色[1] に、Gの要素
色[2] に、Bの要素

Red(赤)だけの配列

赤だけの配列するには、GとBの要素を0に変換します。

色の順序は[R, G, B]で読み込んでいるので、 左上の[55, 56, 60]は、[55, 0, 0]に変換します。

# 加工用にimgをコピー
img_r = img.copy()

# GとBの要素を0に変換
img_r[:, :, 1] = 0  # G
img_r[:, :, 2] = 0  # B

# 画像の表示
io.imshow(img_r)
図2: Rだけ

GとBの要素は、リストにまとめると、コードが簡潔になります。

# GとBの要素を0に変換(1行にまとめて記述)
img_r[:, :, [1, 2]] = 0  # [G, B] 

Green(緑)だけの配列

緑だけの配列するには、RとBの要素を0に変換します。

色の順序は[R, G, B]で読み込んでいるので、 左上の[55, 56, 60]は、[0, 56, 0]に変換します。

# 加工用にimgをコピー
img_g = img.copy()

# RとBの要素を0に変換
img_g[:, :, 0] = 0  # R
img_g[:, :, 2] = 0  # B

# 画像の表示
io.imshow(img_g)
図3: Gだけ

Brue(青)だけの配列

緑だけの配列するには、RとGの要素を0に変換します。

色の順序は[R, G, B]で読み込んでいるので、 左上の[55, 56, 60]は、[0, 0, 60]に変換します。

# 加工用にimgをコピー
img_b = img.copy()

# RとGの要素を0に変換
img_b[:, :, 0] = 0  # R
img_b[:, :, 1] = 0  # G

# 画像の表示
io.imshow(img_b)
図4: 青だけ

ここまでのまとめ

  • カラー画像は、縦×横×色のnumpy配列
  • 配列の色には、[R, G, B]が入っており、numpyで書き換えができる
  • 単色のカラー画像も、配列の色に[R, G, B]の3つの数字をもっている
  • 配列の色[R, G, B]の2つの数字を0にすることを、単色化という

RGBチャンネルの分離

カラー画像には、色の成分を表現する配列があります。
RGBの各成分を取り出すと、白黒の画像になります。

# Rだけをコピー
img_r_gray = img_r[:, :, 0].copy()

# img_r_grayの形状
img_r_gray.shape  #  結果: (180, 180) 

# img_r_grayの表示
io.imshow(img_r_gray)  
図5: 赤のみ白黒化

Rだけをコピーすると、numpy配列が(180, 180, 3)から(180, 180)となりました。
縦180×横180の白黒画像です。

RGBをそれぞれ白黒画像にして、並べて表示します。

# RGBの各要素をコピー
img_r_gray = img_r[:, :, 0].copy()
img_g_gray = img_g[:, :, 1].copy()
img_b_gray = img_b[:, :, 2].copy() 

# 余白を設定
plt.subplots_adjust(wspace=0.5)

# Red
plt.subplot(1,3,1)
plt.imshow(img_r_gray, cmap='gray')

# Green
plt.subplot(1,3,2)
plt.imshow(img_g_gray, cmap='gray')

# Brue
plt.subplot(1,3,3)
plt.imshow(img_b_gray, cmap='gray')
図6: 赤、青、緑の白黒化

まとめ

  • RGBの各要素だけにする単色化ができました
  • カラー画像をRGBの要素に分離することができました
  • RGBを各要素に分離すると、白黒画像になりました

numpyを利用して、カラー画像をRGBに分離する方法がわかりました。

応用として、RGBの各要素をまぜて白黒(グレースケール)画像を作成したり、色の順番をRGBからGBRに変換する画像処理ができます。

関連情報

タイトルとURLをコピーしました