ユーニックス総合研究所

  • home
  • archives
  • python-pillow-paste

PythonのPillowのpasteで画像をマスクして貼り付ける

  • 作成日: 2020-09-25
  • 更新日: 2023-12-24
  • カテゴリ: Python

Pillowのpasteメソッドの使い方

Pythonには画像処理を行うPillowライブラリがあります。

Pillowの画像オブジェクトには画像に画像を貼り付けることができるpasteメソッドがあります。
これを使うと異なる画像同士を合成することが出来ます。

使用する画像

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

まず背景となるロッカー画像。

それから少女の肖像。

これらの画像の著作権はユーニックス総合研究所が保持しています。
練習で使う以外の用途(商用とか2次配布はダメ)では使わないでください。

pasteの詳細

Imageオブジェクトのpaste()メソッドは↓のような構造になっています。

Image.paste(im, box=None, mask=None)  

imにはImageオブジェクトを指定します。
boxには貼り付け位置をタプル((x, y))で指定します。
maskは貼り付ける画像にかけるマスク画像を指定します。

返り値はありません。

背景に肖像を貼り付ける

先ほどの背景画像に少女の肖像を貼り付けてみます。

from PIL import Image  

# 背景と肖像の画像を開く  
bg = Image.open('img/bg.png')  
face = Image.open('img/face.png')  

# 背景に肖像を貼り付け  
bg.paste(face)  

# 結果を保存  
bg.save('dst/out00.png')  

出力結果は↓のようになります。

背景の指定の位置に肖像を貼り付ける

背景画像の指定した位置に肖像を貼り付けます。

from PIL import Image  

# 背景と肖像の画像を開く  
bg = Image.open('img/bg.png')  
face = Image.open('img/face.png')  

# 背景画像の横から100px, 上から100pxの位置に肖像を貼り付け  
bg.paste(face, (100, 100))  

# 結果を保存  
bg.save('/dst/out01.png')  

出力結果は↓のようになります。

マスク画像を使って貼り付け

paste()メソッドの第3引数であるmaskに画像(マスク画像)を指定することによって、貼り付け画像を色々な形に切り抜いて貼り付けることが出来ます。
このマスク画像が指定されている場合、paste()はマスク画像によって示される領域のみに作用します。
マスク画像は貼り付ける画像と同じサイズである必要があります。
また、modeが↓の3種類のどれかである必要があります。

  • 1 - 1ビット画像(白黒の2値画像)
  • L - 8ビットのグレースケール画像
  • RGBA - アルファチャンネルが有効な画像

Lの場合は0でベース画像の取り込みが100%, 255の場合は貼り付ける画像の取り込みが100%になります。
1~254の中間値の場合は、ベース画像と貼り付ける画像が値によってブレンドされます。
これは黒い部分(0)にベース画像が取り込まれ、白い部分(255)に貼り付け画像が取り込まれるということです。
つまり、貼り付け画像の形を指定したい場合はこの白い部分をマスク画像で指定し、他は黒にします。

マスク画像の作成

ImageDrawモジュールを使って↓のように円形のマスク画像を作成します。
このマスク画像は肖像の画像と同じサイズにします。

from PIL import Image, ImageDraw  

# 肖像の画像からマスク画像を生成  
face = Image.open('img/face.png')  
mask_circle = Image.new('L', face.size, 0)  
draw = ImageDraw.Draw(mask_circle)  
draw.ellipse((150, 100, 340, 290), fill=255)  
mask_circle.save('img/mask_circle.png')  

出力結果。

マスクを実行する

paste()の第3引数に先ほどのマスク画像を指定します。
すると肖像の画像がマスクで切り抜かれ、背景画像に合成されます。

from PIL import Image  

# 背景と肖像、マスク画像を開く  
bg = Image.open('img/bg.png')  
face = Image.open('img/face.png')  
mask_circle = Image.open('img/mask_circle.png')  

# 背景画像の横から0px, 上から0pxの位置に肖像をマスクして貼り付け  
bg.paste(face, (0, 0), mask_circle)  

# 結果を保存  
bg.save('dst/out02.png')  

出力結果。

マスク画像にフィルターをかける

Imageオブジェクトのfilterメソッドを使ってマスク画像にフィルター(ブラー)をかけます。
そしてそのフィルターがかかったマスク画像で肖像を合成します。
白と黒の中間値はそれぞれの画像をブレンドするので、結果的に肖像の周りにグラデーションがかかったような効果になります。

from PIL import Image, ImageFilter  

# 背景と肖像、マスク画像を開く  
bg = Image.open('img/bg.png')  
face = Image.open('img/face.png')  
mask_circle = Image.open('img/mask_circle.png')  

# マスク画像にブラーをかける  
mask_circle_blur = mask_circle.filter(ImageFilter.GaussianBlur(8))  

# 背景画像の横から0px, 上から0pxの位置に肖像をマスクして貼り付け  
bg.paste(face, (0, 0), mask_circle_blur)  

# 結果を保存  
bg.save('dst/out03.png')  

出力結果。

マスク画像を反転させてフィルターをかける

マスク画像のネガポジを反転させるにはImageOpsモジュールのinvertメソッドを使います。

from PIL import Image, ImageOps, ImageFilter  

# 背景と肖像、マスク画像を開く  
bg = Image.open('img/bg.png')  
face = Image.open('img/face.png')  
mask_circle = Image.open('img/mask_circle.png')  

# マスク画像を反転する  
mask_circle_inv = ImageOps.invert(mask_circle)  

# マスク画像にブラーをかける  
mask_circle_blur = mask_circle_inv.filter(ImageFilter.GaussianBlur(8))  

# 背景画像の横から0px, 上から0pxの位置に肖像をマスクして貼り付け  
bg.paste(face, (0, 0), mask_circle_blur)  

# 結果を保存  
bg.save('dst/out04.png')  

出力結果。

出題

Q1: paste()メソッドの第1引数として適当なものを答えよ

  1. 画像オブジェクト
  2. ファイルオブジェクト
  3. パス

Q2: paste()メソッドを使って画像の任意の位置に画像を貼り付けたい場合に適当な操作を答えよ

  1. paste()メソッドの第2引数にパスを指定する
  2. paste()メソッドの第2引数にタプルを指定する
  3. paste()メソッドの第3引数にタプルを指定する

Q3: paste()メソッドに指定するマスク画像として適当なものを答えよ

  1. 2ビットの2値画像
  2. 8ビットのグレースケール画像
  3. 8ビットのカラー画像

正解はこちら↓

Q1: 1
Q2: 2
Q3: 1, 2

参考