PythonのPillowのImage.getchannel()の使い方: 画像のチャンネルを取り出し加工する
目次
- PillowのImage.getchannelの使い方
- Image.getchannel()の構造
- 検証に使用する画像
- Image.getchannel()の返り値を確認
- 画像からRのチャンネルを取り出す
- 画像からR, G, Bのチャンネルを取り出す
- 抜き出したチャンネルにフィルターを適用する
- 出題
PillowのImage.getchannelの使い方
Pythonの画像処理ライブラリであるPillowは画像を管理するImage
モジュールを持っています。
Image
モジュールには画像の指定のチャンネルを取り出すImage.getchannel()
があります。
この関数を使うとたとえばRGBA
の画像からR
のチャンネルを取り出したり、G
のチャンネルを取り出すことが出来ます。
取り出したチャンネルは画像として処理できるので、Pillowを使って各種加工を行うことも出来ます。
たとえばチャンネルを画像として取り出し、フィルターなどをチャンネルごとに適用し、再び1つの画像として合成する・・・ということも可能です。
こういったことができるのは、Image.getchannel()
の返り値がImage
オブジェクトなので、他の関数でこの画像を使いまわすことが出来るからです。
Image.getchannel()の構造
Image.getchannel()
は↓のような構造を持っています。
Image.getchannel()
は1つの引数を取り、1つの返り値を返します。
Image.getchannel(channel)
↓は引数と返り値の説明です。
channel(第1引数)
第1引数は文字列(str
)のチャンネル名か、整数(int
)のインデックスを渡します。
たとえば画像がRGBA
の画像だった場合で、R
のチャンネルを取り出したいとします。
その場合、第1引数に文字列で'R'
を渡すとチャンネルを取得することが出来ます。
'B'
であればB
のチャンネルを取得できます。
また、整数では0
を渡すことでR
のチャンネルを取得できます。
これはR
がRGBA
の0
番目だからです。
したがって整数で2
を渡すとB
のチャンネルを取得できます。
channel
が文字列または整数でなかった場合はImage.getchannel()
は例外TypeError
を送出します。
また、存在しないチャンネルの文字列や整数を指定した場合はImage.getchannel()
は例外ValueError
を送出します。
返り値
返り値はモードがL
のImage
オブジェクトです。
検証に使用する画像
今回検証に使用する画像は↓の画像です。
この画像はモードRGBA
の横幅500px
, 高さ500px
のPNG
画像です。
Image.getchannel()の返り値を確認
Image.getchannel()
の返り値を確認します。
まずImage.open()
関数に画像のパスを指定して画像(Image
オブジェクト)を開きます。
そのImage
のImage.getchannel()
に文字列'R'
を指定して画像のR
のチャンネルを取得し、変数r
に保存します。
そしてその変数r
のタイプを出力します。
from PIL import Image im = Image.open('img/a.png') # 画像を開く r = im.getchannel('R') # 画像からRチャンネルを取得 print(type(r)) # 返り値のタイプを出力
出力結果は↓のようになります。
<class 'PIL.Image.Image'>
スポンサーリンク
画像からRのチャンネルを取り出す
画像からR
チャンネルを取り出し画像として保存します。
Image.open()
で画像を開き、Image.getchannel()
で画像のR
チャンネルを取得します。
あとはr.save()
, つまりImage.save()
に保存先の画像のパスを指定し、実行すれば画像を保存できます。
from PIL import Image im = Image.open('img/a.png') # 画像を開く r = im.getchannel('R') # 画像からRチャンネルを取得 r.save('dst/out1.png') # 画像を保存
dst/out1.png
を開くと↓のような画像が表示されます。
画像からR, G, Bのチャンネルを取り出す
画像からR
, G
, B
のチャンネルを取り出し、それらの画像をImage.merge()
で再合成し新しい画像を生成します。
Image.merge()
は第1引数に画像のモード、第2引数にバンド(チャンネル)のタプルを取ります。
from PIL import Image im = Image.open('img/a.png') # 画像を開く # R, G, Bのチャンネルを取り出す r = im.getchannel('R') g = im.getchannel('G') b = im.getchannel('B') # R, G, BのチャンネルをマージしてRGBの画像を生成 merged = Image.merge('RGB', (r, g, b)) # 画像を保存 merged.save('dst/out2.png')
保存した画像は↓のようになります。
元の画像との違いは、こちらの画像はA
チャンネルが取り除かれている点です。
抜き出したチャンネルにフィルターを適用する
画像から抜き出したG
チャンネルにフィルターを適用し、Image.merge()
で再合成してみます。
from PIL import Image, ImageFilter im = Image.open('img/a.png') # 画像を開く # R, G, Bのチャンネルを取り出す r = im.getchannel('R') g = im.getchannel('G') b = im.getchannel('B') # Gチャンネルにブラーフィルターを適用 g = g.filter(ImageFilter.BLUR) # R, G, BのチャンネルをマージしてRGBの画像を生成 merged = Image.merge('RGB', (r, g, b)) # 画像を保存 merged.save('dst/out3.png')
G
チャンネルのみにImage.filter()
を使い、ブラー(ImageFilter.BLUR
)を適用しています。
Image.filter()
についての詳細は↓の記事をご覧ください。
この結果の画像は↓のようになります。
G
チャンネルをImage.effect_noise()
で作成したノイズ画像にします。
Image.effect_noise()
についての詳細は↓の記事をご覧ください。
from PIL import Image, ImageFilter im = Image.open('img/a.png') # 画像を開く # R, Bのチャンネルを取り出す r = im.getchannel('R') b = im.getchannel('B') # Rチャンネルにブラーフィルターを適用 r = r.filter(ImageFilter.BLUR) # Gチャンネルをノイズ画像で作成 g = Image.effect_noise(im.size, 50) # R, G, BのチャンネルをマージしてRGBの画像を生成 merged = Image.merge('RGB', (r, g, b)) # 画像を保存 merged.save('dst/out4.png')
結果は↓のようになります。
出題
Q1: Image.getchannel()
の第1引数として適当なものを答えよ
str
list
int
Q2: Image.getchannel()
で画像のR
チャンネルを取り出したい場合に適当な操作を答えよ
第1引数に整数1を渡す
第2引数に文字列'R'を渡す
第1引数に整数0を渡す
Q3: Image.getchannel()
の返り値として適当なものを答えよ
dict
list
Image
出題の正解はこちら↓
Q1: 1, 3
Q2: 3
Q3: 3