note.nkmk.me

Python, Pillowで二枚の画像をマスク画像に従って合成

Date: 2017-12-01 / tags: Python, Pillow, 画像処理

Pythonの画像処理ライブラリPillow(PIL)のImageモジュールに、二枚の画像をマスク画像に従って合成するメソッドcomposite()が用意されている。

ここでは以下の内容について説明する。

  • Image.composite()の引数
  • Image.composite()のコード例
    • 全面を一律の割合で合成
    • 図形描画でマスク画像を作成
    • 既存の画像をマスク画像として使用

Pillow(PIL)のインストール、基本的な使い方などは以下の記事参照。

なお、composite()は同じサイズの2枚の画像を合成するメソッド。サイズの異なる画像を合成する場合はpaste()メソッドを使う。小さい画像をマスクして大きい画像の任意の場所に貼り付けることができる。

PillowではなくOpenCVやNumPyでも合成処理が可能。以下の記事を参照。

スポンサーリンク

Image.composite()の引数

composite()の引数は3つ。3つともImageオブジェクトですべて同じサイズでなければならない。

image1, image2

合成する二枚の画像。

mask

マスク画像。

modeは以下の三種類のいずれか。

  • 1: 1bit画像(二値画像)
  • L: 8bitグレースケール画像
  • RGBA: アルファチャンネルを持った画像

maskの値によって画像1, 2がアルファブレンドされる。

# 1bitの場合
result = mask * image1 + (1 - mask) * image2

# 8bitの場合
result = mask / 255 * image1 + (1 - mask / 255 ) * image2

Image.composite()のコード例

PILからImageをインポートして画像を2枚読み込む。

ImageDrawImageFilterは図形を描画してマスク画像を作成する際に使用する。画像ファイルを読み込んでマスク画像とする場合は省略してOK。

from PIL import Image, ImageDraw, ImageFilter

im1 = Image.open('data/src/lena.jpg')
im2 = Image.open('data/src/rocket.jpg').resize(im1.size)

lena

rocket

今回はサイズを合わせるために2枚目の画像をresize()で縮小している。画像の一部を切り出してサイズを合わせる場合はcrop()を使えばよい。以下の記事参照。

全面を一律の割合で合成

マスク画像としてベタ画像を使うと、画像全面が一律の割合で合成される。

例として、Image.new()で階調が128のベタ画像を作成してマスク画像とする。

mask = Image.new("L", im1.size, 128)
im = Image.composite(im1, im2, mask)
# im = Image.blend(im1, im2, 0.5)

Python Pillow composite solid

全面を一律の割合で合成する場合、blend()メソッドも使える。引数maskの代わりに0.0〜1.0の定数を引数alphaとして指定する。

図形描画でマスク画像を作成

円や四角など単純な形状でマスクして合成したい場合は、ImageDrawモジュールでの図形描画が便利。図形描画についての詳細は以下の記事参照。面倒だけど多角形とかも描画できる。

黒背景に白い円を描画してマスク画像とする。

mask = Image.new("L", im1.size, 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((140, 50, 260, 170), fill=255)
im = Image.composite(im1, im2, mask)

Python Pillow composite circle

さらに、ImageFilterでマスク画像をぼかすと境界が滑らかに合成できる。

mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
im = Image.composite(im1, im2, mask_blur)

Python Pillow composite circle blur

既存の画像をマスク画像として使用

既存の画像を読み込んでマスク画像とすることもできる。ImageDrawモジュールでは難しい複雑な形状で合成することが可能。

白黒の馬の形の画像(scikit-imageのサンプル: skimage.data.horse())を使ってみる。

Pyhton Pillow composite mask horse

open()で画像を読み込んだあと、convert()でモードを'L'(グレースケール)に変換し、resize()で画像のサイズを合わせる。

mask = Image.open('data/src/horse.png').convert('L').resize(im1.size)
im = Image.composite(im1, im2, mask)

Python Pillow composite horse

違う例として、グラデーション画像を使って空間的に徐々に変化していくように合成。グラデーション画像はPillowのImageDrawだと難しいのでNumPyを使用して生成した。

mask = Image.open('data/src/gradation_h.jpg').convert('L').resize(im1.size)
im = Image.composite(im1, im2, mask)

Python Pillow composite gradation

スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事