よちよちpython

独習 python/Qpython/Pydroid3/termux

【Pillow】画像に別の画像を重ねて貼り付ける方法

画像に別の画像を重ねて貼り付けを行います。

画像処理用ライブラリのPillowを使用。



目次




実行環境


  • Androidスマホ
  • termux
  • Python3.8
  • JupyterNotebook
  • 外部ライブラリPillow
    • pip install pillowなどでインストールしておく
  • 貼り付ける画像を2枚準備



画像に別の画像を重ねて貼り付ける


画像の準備

次の2枚の画像を使います。

※作業中の画像確認のためJupyterNotebookに表示させています。特にその必要はありません。
尚、IPython.displayとPILの両方にImageクラスがあって紛らわしいので、表示の度にインポート文を書いています。

# JupyterNotebookに画像表示
from IPython.display import Image

image_list = ["jinja.JPG","noumen.JPG"]
Image(image_list[0])

f:id:chayarokurokuro:20200814063357j:plain

佐賀県嬉野市(うれしの)の八天(はってん)神社八天狗社とも呼ばれる。カグツチスサノオ、火の神々を祀る。嬉野は美肌効果で有名な温泉地です。地理とこの一帯で採れる鉱物と日本神話、八天狗社という神社名を考えるととても意味のある神社だと思う。ナイスです。

Image(image_list[1])

f:id:chayarokurokuro:20200814063603j:plain

顔面蒼白な面白い顔のこちらの女性に、今回は手伝って頂きます。



画像のサイズ確認


Pillowで画像サイズを確認しておきます。

Image.open(画像ファイルパス)で画像ファイルをオブジェクトとして開き、そのsize属性でサイズを取り出す。

# pillowをインポート
from PIL import Image

# 画像オブジェクトに変換
gazou_1 = Image.open(image_list[0])
gazou_2 = Image.open(image_list[1])

# サイズ表示
print("神社", gazou_1.size)
print("能面",gazou_2.size)
print("タイプ", type(gazou_1))
print("モード", gazou_1.mode)
神社 (1584, 2817)
能面 (320, 320)
タイプ <class 'PIL.JpegImagePlugin.JpegImageFile'>
モード RGB



大きい画像(神社)のコピー


注意
貼り付ける際には
背景画像オブジェクト.paste(貼り付け画像オブジェクト)
のメソッドを使います。これは背景画像を上書きするそうなので、背景画像のコピーを使用します。
元画像オブジェクト.copy()
メソッドでコピーできます。

# 神社の画像オブジェクトをコピー
gazou_1_2 = gazou_1.copy()

画像オブジェクトがコピーされました。



画像の貼り付け合わせ


コピーした神社画像オブジェクトに、能面のオブジェクトを貼り付けます。

# paste()で貼り付け
gazou_1_2.paste(gazou_2)



貼り付け合わせた画像の保存

# 画像を保存
gazou_1_2.save("gazou_1_2_1.JPG")

gazou_1_2_1.JPGという画像ファイル名で保存しました。見てみます。

# 貼り付け合わせた画像を表示
from IPython.display import Image
Image("gazou_1_2_1.JPG")

f:id:chayarokurokuro:20200814063727j:plain

学校の記念撮影を休んだ子みたいになりました。

画像ファイルの座標は左上が原点になる。横軸は右にプラス、縦軸は下にプラス。

背景画像となる神社の原点と、能面の原点が合わさるように貼り付けられています。



貼り付け位置の指定


paste()メソッドの第2引数にタプルで(x,y)の座標を指定することで貼り付け位置を変更出来ます。
(指定なしのデフォルトで原点に貼り付け)

# 背景画像オブジェクトのコピー
gazou_1_2 = gazou_1.copy()

# 適当に貼り付け座標を指定し貼り付け
gazou_1_2.paste(gazou_2, (500,1000))

# 画像の保存
gazou_1_2.save("gazou_1_2_2.JPG")
#  画像の表示
from IPython.display import Image
Image("gazou_1_2_2.JPG")

f:id:chayarokurokuro:20200814063938j:plain

真ん中あたりに移動しました。ノーメンクラツーラの出世街道に乗った。

はみ出すとカットされる


背景画像からはみ出すような座標に貼り付けた場合は、はみ出した部分はカットされます。

# 神社画像オブジェクトのコピー
gazou_1_2 = gazou_1.copy()

# はみ出すような座標指定して貼り付け
gazou_1_2.paste(gazou_2, (1584-int(320/2), 1500))

# 画像を保存
gazou_1_2.save("gazou_1_2_3.JPG")

# 画像の表示
from IPython.display import Image
Image("gazou_1_2_3.JPG")

f:id:chayarokurokuro:20200814064044j:plain

ノーメンクラツーラのはみ出し者に…

一応、↑の座標指定部分の説明。

画像サイズは神社(1584, 2817)能面(320, 320)だったので、座標

  • 横軸は(神社-能面の半分)
  • 縦軸は適当

で指定することで半分はみ出させた。320を2で割るとfloat型で返り実行エラーが出た為、int()で整数に変換。

座標の指定はint型で。



背景と貼り付け画像を逆にするとどうなるか


これまでは大きい画像(神社)に小さい画像(能面)を貼りましたが、逆にするとどうなるか。最初から一気にやってみます。

from PIL import Image

# 画像取り込み
im1 = Image.open("jinja.JPG")
im2 = Image.open("noumen.JPG")

# 画像サイズなど表示
print("神社 サイズ", im1.size)
print("能面 サイズ", im2.size)

# 背景画像(能面)オブジェクトをコピー
im2_1 = im2.copy()

# 能面背景に神社を原点で貼り付け
im2_1.paste(im1)

# 貼り付け後のサイズ表示
print("貼り付け後 サイズ", im2_1.size)

# 貼り付け画像の保存
im2_1.save("noumen_jinja.JPG")

# 画像の表示
from IPython.display import Image
Image("noumen_jinja.JPG")
神社 サイズ (1584, 2817)
能面 サイズ (320, 320)
貼り付け後 サイズ (320, 320)

f:id:chayarokurokuro:20200814064213j:plain

はみ出した部分がカットされた小さな画像が出来ました。能面の上に神社の画像が貼られるので、能面はお隠れ遊ばされている。



【参考】



以上です。