Loading [MathJax]/extensions/tex2jax.js

[matplotlib] 95. subplot_mosaicによる年賀状

matplotlib

はじめに

アスキーアート的に図を複数個作成できるmatplotlibのsubplot_mosaicにより、年賀状を作成する方法について説明する。

コード

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import rcParams
import random
rcParams['font.family'] = 'sans-serif'
rcParams['font.sans-serif'] = ['Hiragino Maru Gothic Pro', 'Yu Gothic', 'Meirio', 'Takao', 'IPAexGothic', 'IPAPGothic', 'VL PGothic', 'Noto Sans CJK JP']
pass_m=["https://2.bp.blogspot.com/-T5ghBsMLQBs/XAY6ZV9gC3I/AAAAAAABQj4/lmhmkfVjNGkSLhTDGOUmdsEwcvYz6dS3QCLcBGAs/s800/ushi_texas_tornado.png",
"https://1.bp.blogspot.com/-GqLUdOkIoGE/Xy4eavz7mtI/AAAAAAABafk/ZGMsLH0IZmQtHJBZqTtu4oHKNVqtHY4UwCNcBGAsYHQ/s1600/eto_ushi_family.png",
"https://1.bp.blogspot.com/-buq-kHmE_kQ/WKFjB3MpkbI/AAAAAAABBsk/bC-QFYDPiBsW6HoADGdZFyC5bZhEbD_7ACLcB/s800/food_gyudon_takeout.png",
"https://3.bp.blogspot.com/-38ePZs54nsY/W1vg4jd5EmI/AAAAAAABNsI/3ALa8sVaFxoKXw0ldbd8K-X9oR_zPTjKACLcBGAs/s800/animal_chara_donburi_ushi.png",
"https://1.bp.blogspot.com/-TwX-D3wcDg8/Xy4eZ5hYMbI/AAAAAAABafc/UM6sgP4I4vUW4ufBaS-3jq4ROXpoC9hFQCNcBGAsYHQ/s1600/eto_ushi_daruma.png",
"https://3.bp.blogspot.com/-Gs5qEJcCS6s/XJB5dmZ2XRI/AAAAAAABR_Y/Jcoaa3dWclw-vd0WH8Yvce530h9ArL8ygCLcBGAs/s800/ushi_highland_cattle.png",
"https://2.bp.blogspot.com/-b7uT5EaQca0/WlGngB9g3WI/AAAAAAABJbo/ROuBp-BBuxg3bf75kfuE24AgEC0Qz8U6wCLcBGAs/s800/animal_ushi_aurochs.png",
"https://1.bp.blogspot.com/-9J4XYBgVDJg/Xy4eav0DFdI/AAAAAAABafg/BuusJ5x5sIw64NN77NI25-ybKcV8-NA1ACNcBGAsYHQ/s1600/eto_ushi_kakizome.png",
"https://1.bp.blogspot.com/-Inw0ULxLWFQ/Xy4ebLP0DsI/AAAAAAABafs/8l6bFLORZQUWxIRW6ZVao3TDvnXkivsUQCNcBGAsYHQ/s1600/eto_ushi_kataguruma.png",
"https://4.bp.blogspot.com/-OvqTTiAK1sc/Vn-CpKKjrsI/AAAAAAAA2MY/Y_IAu9aeGMc/s800/eto_remake_ushi.png",
"https://1.bp.blogspot.com/-9J4XYBgVDJg/Xy4eav0DFdI/AAAAAAABafg/BuusJ5x5sIw64NN77NI25-ybKcV8-NA1ACNcBGAsYHQ/s1600/eto_ushi_kakizome.png"]
pass_t=["https://1.bp.blogspot.com/--R3PJRI_b-w/XvcI5TatI2I/AAAAAAABZt4/LPy_kF8BYtgYy7R76I2C2N_hVWW6Bw2dwCNcBGAsYHQ/s1600/osyougatsu_text_2021.png",
"https://4.bp.blogspot.com/-cBbI81Sjh50/Uq7llauZBII/AAAAAAAAbq8/N2JmRmjmiDI/s800/osyougatsu_akemashite_omedetou.png",
"https://4.bp.blogspot.com/-ZqO-sQIaJFw/T3K7nIiq3eI/AAAAAAAAFAg/mrcYdCdRzak/s1600/gashi_kingasinnen.png",
"https://4.bp.blogspot.com/-oJ_xHU1Zomw/T3K7iKmsQOI/AAAAAAAAFAI/lTcf6SmwEY4/s1600/gashi_happy_new_year.png",
"https://1.bp.blogspot.com/-7XP-NmNNGCM/Ul6CrK3GYFI/AAAAAAAAZJg/GKiiCO9sQJU/s800/happynewyear_2.png"]
adress="〒123-4567\n##県##市!!町1-1-1\nsabopy.com"
layout1="""
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
bbbbbbbb
bbbbbbbb
bbbbbbbb
bbbbbbbb
cccccccc
"""
fig = plt.figure(tight_layout=True,figsize=(3.94,5.83),dpi=120)
axd = fig.subplot_mosaic(layout1)
im_m = plt.imread(np.random.choice(pass_m))
im_t = plt.imread(np.random.choice(pass_t))
axd["a"].imshow(im_m)
axd["b"].imshow(im_t)
axd["c"].text(1, 0.5, adress,
ha='right', va='center', fontsize=8,
color='k')
for k, ax in axd.items():
ax.axis("off")
plt.subplots_adjust(wspace=0, hspace=0)
plt.savefig("nengajyou2021.png",dpi=120)
#plt.savefig("nengajyou2021.png",dpi=300)
plt.show()
コードをダウンロード(.pyファイル)

コードをダウンロード(.ipynbファイル)

解説

モジュールのインポートなど

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import rcParams
import random
rcParams['font.family'] = 'sans-serif'
rcParams['font.sans-serif'] = ['Hiragino Maru Gothic Pro', 'Yu Gothic', 'Meirio', 'Takao', 'IPAexGothic', 'IPAPGothic', 'VL PGothic', 'Noto Sans CJK JP']

rcParamsのfontの設定を変更して、日本語を使えるようにする。

バージョン

#version
import matplotlib
print(matplotlib.__version__)
3.3.3
print(np.__version__)
1.19.4

画像のパスのリスト

pass_m=["https://2.bp.blogspot.com/-T5ghBsMLQBs/XAY6ZV9gC3I/AAAAAAABQj4/lmhmkfVjNGkSLhTDGOUmdsEwcvYz6dS3QCLcBGAs/s800/ushi_texas_tornado.png",
"https://1.bp.blogspot.com/-GqLUdOkIoGE/Xy4eavz7mtI/AAAAAAABafk/ZGMsLH0IZmQtHJBZqTtu4oHKNVqtHY4UwCNcBGAsYHQ/s1600/eto_ushi_family.png",
"https://1.bp.blogspot.com/-buq-kHmE_kQ/WKFjB3MpkbI/AAAAAAABBsk/bC-QFYDPiBsW6HoADGdZFyC5bZhEbD_7ACLcB/s800/food_gyudon_takeout.png",
"https://3.bp.blogspot.com/-38ePZs54nsY/W1vg4jd5EmI/AAAAAAABNsI/3ALa8sVaFxoKXw0ldbd8K-X9oR_zPTjKACLcBGAs/s800/animal_chara_donburi_ushi.png",
"https://1.bp.blogspot.com/-TwX-D3wcDg8/Xy4eZ5hYMbI/AAAAAAABafc/UM6sgP4I4vUW4ufBaS-3jq4ROXpoC9hFQCNcBGAsYHQ/s1600/eto_ushi_daruma.png",
"https://3.bp.blogspot.com/-Gs5qEJcCS6s/XJB5dmZ2XRI/AAAAAAABR_Y/Jcoaa3dWclw-vd0WH8Yvce530h9ArL8ygCLcBGAs/s800/ushi_highland_cattle.png",
"https://2.bp.blogspot.com/-b7uT5EaQca0/WlGngB9g3WI/AAAAAAABJbo/ROuBp-BBuxg3bf75kfuE24AgEC0Qz8U6wCLcBGAs/s800/animal_ushi_aurochs.png",
"https://1.bp.blogspot.com/-9J4XYBgVDJg/Xy4eav0DFdI/AAAAAAABafg/BuusJ5x5sIw64NN77NI25-ybKcV8-NA1ACNcBGAsYHQ/s1600/eto_ushi_kakizome.png",
"https://1.bp.blogspot.com/-Inw0ULxLWFQ/Xy4ebLP0DsI/AAAAAAABafs/8l6bFLORZQUWxIRW6ZVao3TDvnXkivsUQCNcBGAsYHQ/s1600/eto_ushi_kataguruma.png",
"https://4.bp.blogspot.com/-OvqTTiAK1sc/Vn-CpKKjrsI/AAAAAAAA2MY/Y_IAu9aeGMc/s800/eto_remake_ushi.png",
"https://1.bp.blogspot.com/-9J4XYBgVDJg/Xy4eav0DFdI/AAAAAAABafg/BuusJ5x5sIw64NN77NI25-ybKcV8-NA1ACNcBGAsYHQ/s1600/eto_ushi_kakizome.png"]
pass_t=["https://1.bp.blogspot.com/--R3PJRI_b-w/XvcI5TatI2I/AAAAAAABZt4/LPy_kF8BYtgYy7R76I2C2N_hVWW6Bw2dwCNcBGAsYHQ/s1600/osyougatsu_text_2021.png",
"https://4.bp.blogspot.com/-cBbI81Sjh50/Uq7llauZBII/AAAAAAAAbq8/N2JmRmjmiDI/s800/osyougatsu_akemashite_omedetou.png",
"https://4.bp.blogspot.com/-ZqO-sQIaJFw/T3K7nIiq3eI/AAAAAAAAFAg/mrcYdCdRzak/s1600/gashi_kingasinnen.png",
"https://4.bp.blogspot.com/-oJ_xHU1Zomw/T3K7iKmsQOI/AAAAAAAAFAI/lTcf6SmwEY4/s1600/gashi_happy_new_year.png",
"https://1.bp.blogspot.com/-7XP-NmNNGCM/Ul6CrK3GYFI/AAAAAAAAZJg/GKiiCO9sQJU/s800/happynewyear_2.png"]

下記サイトから来年度の干支である牛関連の画像のurlのリストを作成する。

かわいいフリー素材集
いらすとやは季節のイベント・動物・子供などのかわいいイラストが沢山見つかるフリー素材サイトです。

住所の作成

adress="〒123-4567\n##県##市!!町1-1-1\nsabopy.com"

レイアウトの作成

layout1="""
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
aaaaaaaa
bbbbbbbb
bbbbbbbb
bbbbbbbb
bbbbbbbb
cccccccc
"""

図はアスキーアート的に文字列で設定する事になる。

基本的な年賀状の作成

fig = plt.figure(tight_layout=True,figsize=(3.94,5.83),dpi=120)
axd = fig.subplot_mosaic(layout1)
im_m = plt.imread(np.random.choice(pass_m))
im_t = plt.imread(np.random.choice(pass_t))
axd["a"].imshow(im_m)
axd["b"].imshow(im_t)
axd["c"].text(1, 0.5, adress,
ha='right', va='center', fontsize=8,
color='k')
for k, ax in axd.items():
ax.axis("off")
plt.subplots_adjust(wspace=0, hspace=0)
plt.savefig("nengajyou2021.png",dpi=120)
#plt.savefig("nengajyou2021.png",dpi=300)
plt.show()

figsizeは年賀はがきのサイズとする。
fig.subplot_mosaic(layout1)により、先ほどのレイアウトをfigに適用する。

plt.imread(np.random.choice(pass_m))により、リスト内にランダムな値を選択して、画像を読み込み、imshowで表示する。axd[“a”].imshow(im_m)でレイアウトのaの位置に画像im_mが表示される。
axd[“c”]には.textで住所を表示する。右端揃えにするため、haを”right”とした。

ax.axis(“off”)により、図の枠を非表示とした。

plt.subplots_adjust(wspace=0, hspace=0)により、図間の間隔を横方向、縦方向ともに0とした。

メイン画像を2 × 2で表示した年賀状

layout2="""
aaaabbbb
aaaabbbb
aaaabbbb
ccccdddd
ccccdddd
ccccdddd
eeeeeeee
eeeeeeee
eeeeeeee
eeeeeeee
ffffffff
"""
fig = plt.figure(tight_layout=True,figsize=(3.94,5.83),dpi=120)
axd = fig.subplot_mosaic(layout2)
im_m = plt.imread(np.random.choice(pass_m))
axd["a"].imshow(im_m)
im_m = plt.imread(np.random.choice(pass_m))
axd["b"].imshow(im_m)
im_m = plt.imread(np.random.choice(pass_m))
axd["c"].imshow(im_m)
im_m = plt.imread(np.random.choice(pass_m))
axd["d"].imshow(im_m)
im_t = plt.imread(np.random.choice(pass_t))
axd["e"].imshow(im_t)
axd["f"].text(1, 0.5, adress,
ha='right', va='center', fontsize=8,
color='k')
for k, ax in axd.items():
ax.axis("off")
plt.subplots_adjust(wspace=0, hspace=0)
plt.savefig("nengajyou2021_2x2.png",dpi=120)
#plt.savefig("nengajyou2021_2x2.png",dpi=300)
plt.show()

メイン画像を3 × 3で表示した年賀状

layout3="""
aaabbbccc
aaabbbccc
aaabbbccc
dddeeefff
dddeeefff
dddeeefff
ggghhhiii
ggghhhiii
ggghhhiii
jjjjjjjjj
jjjjjjjjj
jjjjjjjjj
kkkkkkkkk
"""
random.shuffle(pass_m)
fig = plt.figure(tight_layout=True,figsize=(3.94,5.83),dpi=120)
axd = fig.subplot_mosaic(layout3)
for i, name in enumerate(list("abcdefghi")):
im_m = plt.imread(pass_m[i])
axd[name].imshow(im_m)
im_t = plt.imread(np.random.choice(pass_t))
axd["j"].imshow(im_t)
axd["k"].text(1, 0.5, adress,
ha='right', va='center', fontsize=8,
color='k')
for k, ax in axd.items():
ax.axis("off")
plt.subplots_adjust(wspace=0, hspace=0)
plt.savefig("nengajyou2021_3x3.png",dpi=120)
#plt.savefig("nengajyou2021_3x3.png",dpi=300)
plt.show()

向きが横の年賀状

layout4="""
aaaaabbbbb
aaaaabbbbb
aaaaabbbbb
aaaaabbbbb
cccccccccc
cccccccccc
dddddddddd
"""
fig = plt.figure(tight_layout=True,figsize=(5.84,3.94),dpi=120)
axd = fig.subplot_mosaic(layout4)
im_m = plt.imread(np.random.choice(pass_m))
axd["a"].imshow(im_m)
im_m = plt.imread(np.random.choice(pass_m))
axd["b"].imshow(im_m)
im_m = plt.imread(np.random.choice(pass_m))
im_t = plt.imread(np.random.choice(pass_t))
axd["c"].imshow(im_t)
axd["d"].text(1, 0.5, adress,
ha='right', va='center', fontsize=8,
color='k')
for k, ax in axd.items():
ax.axis("off")
plt.subplots_adjust(wspace=0, hspace=0)
plt.savefig("nengajyou2021_yoko.png",dpi=120)
#plt.savefig("nengajyou2021_yoko.png",dpi=300)
plt.show()

参考

Complex and semantic figure composition — Matplotlib 3.3.0 documentation

コメント