OpenCVでカラー画像をRGB画像に分離して表示する

# はじめに

OpenCV(Open Source Computer Vision Library)はBSDライセンスの映像/画像処理ライブラリ集です。画像のフィルタ処理、テンプレートマッチング、物体認識、映像解析、機械学習などのアルゴリズムが多数用意されています。

OpenCVを使った動体追跡の例 (OpenCV Google Summer of Code 2015)
[https://www.youtube.com/watch?v=OUbUFn71S4s](https://www.youtube.com/watch?v=OUbUFn71S4s)

インストールと簡単な使い方はこちら
[http://qiita.com/olympic2020/items/d5d475a446ec9c73261e](http://qiita.com/olympic2020/items/d5d475a446ec9c73261e)

静止画像のフィルター処理についてはこちら
[OpenCVでエッジ検出してみる](http://qiita.com/olympic2020/items/2c3a2bfefe73ab5c86a4)

動画ファイルの処理についてはこちら
[OpenCVで動画をリアルタイムに変換してみる](http://qiita.com/olympic2020/items/ce00fab38d829965db3b)
[OpenCVでWebカメラ/ビデオカメラの動画をリアルタイムに変換してみる](http://qiita.com/olympic2020/items/12a2eceaf65f142ec3df)

どのような動画処理をするにしても、１枚の画像をフィルタ処理することが基本になります。
今回は、画像処理の基本として、カラー画像をＲＧＢ画像に分離し表示してみます。

# ＲＧＢ分離アルゴリズム
カラー画像をＲＧＢに分離するアルゴリズムについて説明しておきます。
まず、カラー画像をＲＧＢに分離します。これは、cv2.split()で簡単にできます。
分離した画像は１チャンネル分のため、これをそのまま表示するとグレースケールとしての表示になります。
ＲＧＢに分離したあとに、それぞれの色で表示するためには、他の色をゼロ埋めの画像で補ったカラー画像を作ってあげる必要があります。
ゼロ埋めの画像を作るのは、numpy.zeros()で、３チャンネルを１画像にまとめるのは、cv2.merge()で行います。

ＲＧＢを分離して、それぞれの色で表示する流れを模式図にしてみました。プログラムを理解する際に参考にしてください。

![separate.png](https://qiita-image-store.s3.amazonaws.com/0/107056/bb405d3d-58cd-353b-2d24-9e53c22ad24f.png)


# プログラム

```channels.py
import cv2
import numpy as np

# 定数定義
FILE_PREFIX = "google"
ORG_FILE_NAME = "google_org.png"

BLUE_FILE_NAME = FILE_PREFIX + "_b.png"
GREEN_FILE_NAME = FILE_PREFIX + "_g.png"
RED_FILE_NAME = FILE_PREFIX + "_r.png"

ORG_WINDOW_NAME = "org"
BLUE_WINDOW_NAME = "blue"
GREEN_WINDOW_NAME = "green"
RED_WINDOW_NAME = "red"

# 元の画像を読み込む
org_img = cv2.imread(ORG_FILE_NAME, cv2.IMREAD_COLOR)

# ゼロ埋めの画像配列
if len(org_img.shape) == 3:
    height, width, channels = org_img.shape[:3]
else:
    height, width = org_img.shape[:2]
    channels = 1
zeros = np.zeros((height, width), org_img.dtype)

# RGB分離
img_blue_c1, img_green_c1, img_red_c1 = cv2.split(org_img)

img_blue_c3 = cv2.merge((img_blue_c1, zeros, zeros))
img_green_c3 = cv2.merge((zeros, img_green_c1, zeros))
img_red_c3 = cv2.merge((zeros, zeros, img_red_c1))

# ウィンドウを作成
cv2.namedWindow(ORG_WINDOW_NAME)
cv2.namedWindow(BLUE_WINDOW_NAME)
cv2.namedWindow(GREEN_WINDOW_NAME)
cv2.namedWindow(RED_WINDOW_NAME)

# ウィンドウに表示
cv2.imshow(ORG_WINDOW_NAME, org_img)
cv2.imshow(BLUE_WINDOW_NAME, img_blue_c3)
cv2.imshow(GREEN_WINDOW_NAME, img_green_c3)
cv2.imshow(RED_WINDOW_NAME, img_red_c3)

# ファイルに保存
cv2.imwrite(BLUE_FILE_NAME, img_blue_c3)
cv2.imwrite(GREEN_FILE_NAME, img_green_c3)
cv2.imwrite(RED_FILE_NAME, img_red_c3)

# 終了処理
cv2.waitKey(0)
cv2.destroyAllWindows()
```

cv2.imread()にcv2.IMREAD_UNCHANGEDを指定するとαプレーンありの４チャンネルの情報を取得することができます。一方、cv2.imread()にcv2.IMREAD_COLORを指定するとＲＧＢプレーンのみの３チャンネルの情報を取得することができます。
今回は、ＲＧＢのみ取得するようにcv2.IMREAD_COLORを指定しました。

# 実行結果
Googleのホームページの白い部分を黒に加工した元画像をスクリプトでＲＧＢの画像に分離してみました。

![google_org.png](https://qiita-image-store.s3.amazonaws.com/0/107056/ef3e2e33-0c83-7f27-655f-5faab7f7e96d.png)
　　　　　　　　　　　　**元画像**

![google_b.png](https://qiita-image-store.s3.amazonaws.com/0/107056/a7a2214a-ee14-f45a-42cf-359c4a8158b7.png)
　　　　　　　　　　　　**Blue**

![google_g.png](https://qiita-image-store.s3.amazonaws.com/0/107056/feae872e-1446-80de-949f-814a35ab4fd0.png)
　　　　　　　　　　　　**Green**

![google_r.png](https://qiita-image-store.s3.amazonaws.com/0/107056/9cbc8672-2c7d-c115-f693-0cafe5fddeb5.png)
　　　　　　　　　　　　**Red**