PillowのImage.mergeの使い方: 画像のバンドをマージする

60, 2020-09-27

目次

PillowのImage.mergeの使い方

Pythonの画像処理ライブラリであるPillowはImageモジュールを持っています。
Imageモジュールは画像のバンドを合成し、1つの画像として出力できるmergeという関数を持っています。

これを使うと特定のバンドを取り除いたり、異なる画像のバンドを合成することが可能です。

使用する画像

今回使用する画像はこちらです。

【共有】海の中に立つ人

【共有】水没する2人

【共有】火星ウォーカー

バンドとは?

Pillowにおける「バンド」とは画像内の各チャンネルの画像のことです。
たとえば画像がRGBAというチャンネルを持っていれば、この画像はR, G, B, Aそれぞれのバンドに分割することが出来ます。
バンドは元の画像の形を持っていて、それぞれ画像として表示することが可能です。

Image.split()という関数で画像のバンドを分割することが出来ます。

from PIL import Image

# 画像を開く
image_a = Image.open('img/a.png')

# 画像のバンドを分割
r, g, b, a = image_a.split()

# バンド画像を保存
r.save('dst/a_r.png')

出力される画像は↓のようになります。

【0060】a_r.png

Image.split()が返すバンドのタイプは<class 'PIL.Image.Image'>です。
また、単体のバンドを抽出したい場合はImage.getchannel()という関数も使えます。

Image.merge()の構造

Image.merge()は↓のような構造を持っています。

PIL.Image.merge(mode, bands)

modeは戻り値の画像のモードです。
1(1ビット), L(8ビット), RGB, RGBAなどの文字列を指定できます。

bandsは複数の画像を持つリストまたはタプルです。
全てのバンドの画像は同じサイズである必要があります。

戻り値はImageオブジェクトです。

2つの画像のバンドをマージする

異なる2つの画像のバンドをImage.split()で抽出し、Image.merge()で合成します。

from PIL import Image

# 画像を開く
image_a = Image.open('img/a.png')
image_b = Image.open('img/b.png')

# それぞれの画像のバンドを分割し、RGBAそれぞれのバンド画像を得る
ar, ag, ab, aa = image_a.split()
br, bg, bb, ba = image_b.split()

# 画像aのR(赤), G(緑)のバンドと、画像bのB(青)のバンドをマージする
out = Image.merge('RGB', (ar, ag, bb))
out.save('dst/out1.png')

出力される画像は↓のようになります。

【0060】out1.png

3つの画像のバンドをマージする

異なる3つの画像のバンドをImage.split()で抽出し、Image.merge()で合成します。

from PIL import Image

# 画像を開く
image_a = Image.open('img/a.png')
image_b = Image.open('img/b.png')
image_c = Image.open('img/c.png')

# それぞれの画像のバンドを分割し、RGBAそれぞれのバンド画像を得る
ar, ag, ab, aa = image_a.split()
br, bg, bb, ba = image_b.split()
cr, cg, cb, ca = image_c.split()

# 画像aのR(赤)、画像bのR(赤)、画像cのR(赤)のバンドをマージする
out = Image.merge('RGB', (ar, br, cr))
out.save('dst/out2.png')

出力される画像は↓のようになります。

【0060】out2.png

アルファバンドを取り除く

アルファチャンネルを持つ画像からアルファのバンドを取り除きます。
(今までのサンプルはすべてRGBで保存してましたが)

from PIL import Image

# 画像を開く
image_a = Image.open('img/a.png')

# 画像のバンドを分割し、RGBAそれぞれのバンド画像を得る
r, g, b, a = image_a.split()

# 画像aのR(赤)、G(緑)、B(青)のバンドをマージし、A(アルファ)を取り除く
out = Image.merge('RGB', (r, g, b))
out.save('dst/out3.png')

出力される画像は↓のようになります。

【0060】out3.png

特定のバンドのみを残す

画像の特定のバンドを残して新しい画像を生成します。

from PIL import Image

# 画像を開く
image_b = Image.open('img/b.png')

# 画像のバンドを分割し、RGBAそれぞれのバンド画像を得る
r, g, b, a = image_b.split()

# 画像bのR(赤)だけを残す
out = Image.merge('RGB', (r, r, r))
out.save('dst/out4.png')

出力される画像は↓のようになります。

【0060】out4.png

問題

Q1: 複数の画像のバンドをImage.merge()で合成するときに適当な操作を答えよ

  1. Image.split()でバンドを取り出しImage.merge()で合成する

  2. Image.getchannel()でバンドを取り出しImage.merge()で合成する

  3. Image.save()で画像を読み込みImage.merge()で合成する

Q2: Image.split()が返すバンドのタイプは何か答えよ

  1. Image

  2. str

  3. int

Q3: Image.merge()の引数として適当なものを答えよ

  1. str

  2. dict

  3. Image


正解はこちら↓

Q1: 1, 2
Q2: 1
Q3: 3