Python, Pillowで透過png画像を作成するputalpha
Pythonの画像処理ライブラリPillow(PIL)のImage
モジュールに、画像にアルファチャンネルを追加するputalpha()
が用意されている。
ここでは以下の内容について説明する。
Image.putalpha()
の使い方- 全面に一律の透過率を設定
- 図形描画でアルファチャンネルを作成
- 既存の画像をアルファチャンネルとして使用
Pillow(PIL)のインストール、基本的な使い方などは以下の記事参照。
PIL
からImage
をインポートして元となる画像を読み込む。
ImageDraw
とImageFilter
は図形を描画してアルファチャンネルを作成する際に使用する。画像ファイルを読み込んで使う場合は省略してOK。
from PIL import Image, ImageDraw, ImageFilter
im_rgb = Image.open('data/src/lena.jpg')
Image.putalpha()の使い方
putalpha()
の引数はalpha
ひとつだけ。文字通り、元画像にアルファチャンネルのレイヤーalpha
をputする。
元画像がRGB
(8bit x 3: フルカラー)またはL
(8bit x 1: 白黒)の場合は新たにアルファチャンネルが追加され、RGBA
またはLA
の場合は元のアルファチャンネルが更新される。
定数で指定
alpha
に8bit(0〜255)の整数値を指定すると、全面にその値に応じた透過率が設定される。
0は100%透過、255は0%透過(不透過)。
Imageオブジェクトで指定
alpha
にmode='L'
(8bitグレースケール)で元画像と同じサイズのImage
オブジェクトを指定すると、様々な形状にアルファチャンネルを設定できる。
定数の場合と同じく、0は100%透過、255は0%透過(不透過)。
全面に一律の透過率を設定
引数alpha
に整数値を指定すると全面にその値に応じた透過率が設定される。
なお、putalpha()
メソッドは元画像自体を上書きして変更するため、元画像をそのまま残しておきたい場合はcopy()
メソッドで複製したものを使う。
im_rgba = im_rgb.copy()
im_rgba.putalpha(128)
im_rgba.save('data/dst/pillow_putalpha_solid.png')
この例では128/255
なのでおおよそ50%の透過率となる。
図形描画でアルファチャンネルを作成
円や四角など単純な形状のアルファチャンネルを追加したい場合は、ImageDraw
モジュールでの図形描画が便利。図形描画についての詳細は以下の記事参照。面倒だけど多角形とかも描画できる。
黒背景に白い円を描画してアルファチャンネルとする。
im_a = Image.new("L", im_rgb.size, 0)
draw = ImageDraw.Draw(im_a)
draw.ellipse((140, 50, 260, 170), fill=255)
im_rgba = im_rgb.copy()
im_rgba.putalpha(im_a)
im_rgba_crop = im_rgba.crop((140, 50, 260, 170))
im_rgba_crop.save('data/dst/pillow_putalpha_circle.png')
さらに、ImageFilter
ぼかすと境界を滑らかにできる。
im_a_blur = im_a.filter(ImageFilter.GaussianBlur(4))
im_rgba = im_rgb.copy()
im_rgba.putalpha(im_a_blur)
im_rgba_crop = im_rgba.crop((135, 45, 265, 175))
im_rgba_crop.save('data/dst/pillow_putalpha_circle_blur.png')
いずれの例も、円形に残した部分の周りをcrop()
メソッドで矩形にトリミングしている。crop()
メソッドについては以下の記事参照。
既存の画像をアルファチャンネルとして使用
既存の画像を読み込んでアルファチャンネルとして与えることも可能。ImageDraw
モジュールでは難しい複雑な形状で合成できる。
白黒の馬の形の画像(scikit-imageのサンプル: skimage.data.horse())を使ってみる。
ここでは馬形に残したいので、馬が白で背景は黒となるようにネガポジ反転した画像を使う。
open()
で画像を読み込んだあと、convert()
でモードを'L'
(グレースケール)に変換し、resize()
で画像のサイズを合わせる。
im_a = Image.open('data/src/horse_r.png').convert('L').resize(im_rgb.size)
im_rgba = im_rgb.copy()
im_rgba.putalpha(im_a)
im_rgba.save('data/dst/pillow_putalpha_horse.png')