ユーニックス総合研究所

  • home
  • archives
  • python-pillow-image-getchannel

PythonのPillowのImage.getchannel()の使い方: 画像のチャンネルを取り出し加工する

  • 作成日: 2020-10-11
  • 更新日: 2023-12-26
  • カテゴリ: Python

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のチャンネルを取得できます。
これはRRGBA0番目だからです。
したがって整数で2を渡すとBのチャンネルを取得できます。

channelが文字列または整数でなかった場合はImage.getchannel()は例外TypeErrorを送出します。
また、存在しないチャンネルの文字列や整数を指定した場合はImage.getchannel()は例外ValueErrorを送出します。

返り値

返り値はモードがLImageオブジェクトです。

検証に使用する画像

今回検証に使用する画像は↓の画像です。
この画像はモードRGBAの横幅500px, 高さ500pxPNG画像です。

Image.getchannel()の返り値を確認

Image.getchannel()の返り値を確認します。
まずImage.open()関数に画像のパスを指定して画像(Imageオブジェクト)を開きます。
そのImageImage.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'>  

スポンサーリンク

style="display:block; text-align:center;"
data-ad-layout="in-article"
data-ad-format="fluid"
data-ad-client="ca-pub-7784936884151491"
data-ad-slot="3798407571">

画像から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引数として適当なものを答えよ

  1. str
  2. list
  3. int

Q2: Image.getchannel()で画像のRチャンネルを取り出したい場合に適当な操作を答えよ

  1. 第1引数に整数1を渡す
  2. 第2引数に文字列'R'を渡す
  3. 第1引数に整数0を渡す

Q3: Image.getchannel()の返り値として適当なものを答えよ

  1. dict
  2. list
  3. Image

出題の正解はこちら↓

Q1: 1, 3
Q2: 3
Q3: 3