RGB画像のチャンネル分割 cv2.split()


今回はカラー画像をRGB(Red、Green、Blue)の3チャンネルに分割する手法を紹介します。
開発環境はjupyter notebook、言語はpython3系です。

今回使用した画像・コード一式はgoogle driveに保存しておりますので、必要に応じてお使いください。

作成したコード

import cv2
import glob
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import ImageGrid
import numpy as np
%matplotlib inline

filename = glob.glob("img/pure_color.PNG")

for files in filename:
    img = cv2.imread(files)
    Blue,Green,Red = cv2.split(img)
    cv2.imwrite("img/Blue.png",Blue)
    cv2.imwrite("img/Green.png",Green)
    cv2.imwrite("img/Red.png",Red)
このコードを実行することで、トップ画像のように、画像を赤、青、緑の3つのチャンネルに分割することができます。

処理の解説

概要

今回のポイントは、
Blue,Green,Red = cv2.split(img)
です。
この処理では、cv2.split()の括弧内にカラー画像を読み込んだ結果であるimgを代入しています。
これによって引数として画像のR, G, Bの3つの数値が出てくるので、変数Blue, Green, Redに格納しています。

ここで注意したいのは変数の順番をRGBではなくBGRにすることと、imgにはカラー画像を用いるということです。

cv2.cvtColor()等でグレースケールにした画像をcv2.split()に入れると、画像のチャンネル数が1チャンネルしかないため、エラーになります。

RGBへの分割とは

チャンネル分割の処理の基礎知識について紹介します。
デジタル画像では、ピクセル(色の一粒一粒)が数字で表されています。



RGB画像ではRed、Green、Blueの3つのチャンネルに対して、0~255の256諧調の数字があてはめられています。

この256諧調という数字は二進数でいうところの8bit、2^8=256という数値によって決められています。この値は、単にコンピュータが扱いやすいだけでなく、人が識別できる限界の色調でもあるとされているため、256諧調×3chでほぼ全ての色を表現することができると考えられます。
※たまに16bit、65,536諧調の画像もありますが、扱うことはあまりないと思います。

美術の授業等で、光の3原色というのを聞いたことがあるかと思いますが、デジタル画像でも、この原理を活用しています。

光の3原色

要は赤、緑、青の3色の濃淡で白、黒、グレーを含めた全ての色を表現しているわけですね。

またBGRの分割を視覚的に理解していただくため、下図を用意しました。

純色のチャンネル分割

これによって、各色がどのような組み合わせで成り立っているかが分かりますね。

また、赤色のグラデーションの画像で同じようにチャンネル分割すると、次のようになります。

グラデーション画像のチャンネル分割

青と緑のチャンネルでは数値が常に0(黒色)ですが、赤のチャンネルでは右に進むたびに数値が大きくなる(白色になる)ことが確認できます。

cv2.split()を活用した画像処理例

今回はトップ画から、赤いシャツの部分を大まかに取り出す処理を紹介します。
下図を見ていただければ、どのような処理かが分かると思いますが、赤いシャツの領域を取り出すということで、緑と青のチャンネルの値が小さく、赤のチャンネルの値が大きな領域を取り出しています。


図の右側を見ると、周辺に関係のないものも残っていますし、袖の影のところもうまく抽出できていませんが、シャツの部分はあらかた抜粋できていることが確認できます。

Tシャツの領域を画像から取り出しても仕方ありませんが、航空写真から森林の面積を求めるなど、RGBに分割することでできる処理はたくさんありそうですね。

今回使用した画像:私服のオーバーオール

最初はオーバーオールを着ることに恥ずかしさもありましたが、着てみると意外と良いんですよね。
上に白いTシャツを着るだけでもお洒落感が出ますし、ポケットも多くて便利です。

確か大阪はアメリカ村で買ったやつです。
アメリカ村にも、ぜひ行ってみてください!

コメント