よちよちpython

独習 python/Qpython/Pydroid3/termux

【Numpy】竈門炭治郎の柄の画像を作る

鬼滅の刃』の竈門炭治郎が着ている緑と黒の羽織の柄をNumpyで画像作成してみるテスト。

Numpyによる簡単な配列の結合や画像の作成方法が分かるかと思います。



作業環境


  • Androidスマホ
  • Python3.8
  • JupyterNotebook
  • 外部ライブラリ
    • Numpy
    • matplotlib



目次




参考
【エクセルマクロ】鬼滅の刃の羽織柄を作ってみた_背景色を塗る | kirinote.com



色の指定


参考のサイトでは「公式の色ではないが」と断ってありますが、

  • 緑:RGB(79, 172, 135)
  • 黒:RGB(41, 37, 34)

に指定されており良い感じの色ですのでこれを使わさせてもらいました。

サイズの指定


緑と黒はそれぞれ

とし、それを互い違いに組み合わせて大きな画像にしていきます。

画像作成方法の手順


Numpyで行います。
手順としては、

  1. 基になる一辺15の正方行列を作成
  2. 緑・黒のRGBに合わせて6パターンの二次元配列の数値を変更
  3. RGB二次元配列をnp.stackで三次元方向に結合し緑と黒のブロック画像作成
  4. ブロック画像を結合し大きな画像を作成



画像作成


手順1. 基となる配列の作成

15×15の正方行列を作る。
np.zeros()で値がゼロ、shape(15,15)

import numpy as np
import matplotlib.pyplot as plt

np_roots = np.zeros(15*15, dtype=int).reshape(15,15)


np_roots
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

とりあえずゼロだけの正方行列ができた。



手順2. 緑の配列作成


手順1で作成した二次元配列を、RGB(79, 172, 135)に合わせて数値を変更し合計3つの二次元配列を作る。

緑のR

# 基をコピー
np_Green_r = np_roots.copy()
# r=79に数値変更
np_Green_r[:,:] = 79

np_Green_r
array([[79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
       [79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
       [79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
       [79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
       [79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
       [79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
       [79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
       [79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
       [79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
       [79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
       [79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
       [79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
       [79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
       [79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],
       [79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79]])

ゼロの正方行列の要素の値をRGBのRの値である79に全て変更した。
GとBも同じようにやっていく。



緑のGとB

同様に、G=172、B=135に数値を変更する。

# 基をコピー
np_Green_g = np_roots.copy()
np_Green_b = np_roots.copy()

# b=172に数値変更
np_Green_g[:,:] = 172

# g=135に数値変更
np_Green_b[:,:] = 135

これで緑のRGBそれぞれの二次元配列が合計3つできました。
同様に、黒も作っていきます。

黒のR,G,B

# 基をコピー
np_Black_r = np_roots.copy()
np_Black_g = np_roots.copy()
np_Black_b = np_roots.copy()

# RGB(41,37,34)

# r=41に数値変更
np_Black_r[:,:] = 41

# g=37に数値変更
np_Black_g[:,:] = 37

# b=34に数値変更
np_Black_b[:,:] = 34



手順3. np.stackでRGB二次元配列を三次元方向に結合


緑と黒でそれぞれのRGB二次元配列を三次元方向に結合し、2色の画像を作ります。

緑の画像作成

np_Green = np.stack([np_Green_r, np_Green_g, np_Green_b], axis=2)

print(np_Green)

plt.imshow(np_Green)
[[[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]

 [[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]

 [[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]

 [[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]

 [[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]

 [[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]

 [[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]

 [[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]

 [[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]

 [[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]

 [[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]

 [[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]

 [[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]

 [[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]

 [[ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]
  [ 79 172 135]]]


20201229020629



黒の画像作成

np_Black = np.stack([np_Black_r, np_Black_g, np_Black_b], axis=2)

#print(np_Black) #表示省略

plt.imshow(np_Black)

f:id:chayarokurokuro:20201229012237j:plain



手順4. 画像組み合わせ


2色の画像ができましたので、これを組み合わせて大きな画像にしていきます。

黒緑の横連結

# 黒緑の横連結
np_BG = np.hstack([np_Black, np_Green])

plt.imshow(np_BG)

f:id:chayarokurokuro:20201229012602j:plain

緑黒の横連結

# 緑黒の横連結
np_GB = np.hstack([np_Green, np_Black])

plt.imshow(np_GB)

f:id:chayarokurokuro:20201229012736j:plain

黒緑を横に10回連結

i =10

np_BG10 = np.hstack([np_BG]*i)

plt.imshow(np_BG10)

f:id:chayarokurokuro:20201229012850j:plain

緑黒を横に10回連結

i =10

np_GB10 = np.hstack([np_GB]*i)

plt.imshow(np_GB10)

f:id:chayarokurokuro:20201229013043j:plain

黒緑10と緑黒10を縦に連結

np_BG10_GB10 = np.vstack([np_BG10, np_GB10])

plt.imshow(np_BG10_GB10)

f:id:chayarokurokuro:20201229013212j:plain



黒緑10緑黒10を縦に10倍連結(完成)

i = 10
np_Tanjiro = np.vstack([np_BG10_GB10]*i)

plt.imshow(np_Tanjiro)

f:id:chayarokurokuro:20201229013310j:plain



コードまとめ


上記のコードをまとめます。

import numpy as np
import matplotlib.pyplot as plt


### 設定 (サイズ変更用)###
# 各色パネルのサイズ(ピクセル)
p = 25
# 連結する倍数(30ピクセル×i倍の画像ができる)
i =4


### 手順1 基となる配列の生成 ###
np_roots = np.zeros(p*p, dtype=int).reshape(p, p)


### 手順2と3 緑の作成 ###
# 基をコピー
np_Green_r = np_roots.copy()
np_Green_g = np_roots.copy()
np_Green_b = np_roots.copy()

# r=79に数値変更
np_Green_r[:,:] = 79
# b=172に数値変更
np_Green_g[:,:] = 172
# g=135に数値変更
np_Green_b[:,:] = 135

# 緑画像作成
np_Green = np.stack([np_Green_r, np_Green_g, np_Green_b], axis=2)


### 手順2と3 黒の作成 ###
# 基をコピー
np_Black_r = np_roots.copy()
np_Black_g = np_roots.copy()
np_Black_b = np_roots.copy()

# r=41に数値変更
np_Black_r[:,:] = 41
# g=37に数値変更
np_Black_g[:,:] = 37
# b=34に数値変更
np_Black_b[:,:] = 34

# 黒画像作成
np_Black = np.stack([np_Black_r, np_Black_g, np_Black_b], axis=2)



### 手順4 連結 ###
# 黒緑の横連結
np_BG = np.hstack([np_Black, np_Green])
# 緑黒の横連結
np_GB = np.hstack([np_Green, np_Black])

# 黒緑の横i倍連結
np_BG10 = np.hstack([np_BG]*i)
# 緑黒のi倍横連結
np_GB10 = np.hstack([np_GB]*i)

# 黒緑と緑黒の縦連結
np_BG10_GB10 = np.vstack([np_BG10, np_GB10])

# 縦にi倍連結(完成)
np_Tanjiro = np.vstack([np_BG10_GB10]*i)

plt.imshow(np_Tanjiro)

f:id:chayarokurokuro:20201229013429j:plain

まとめたコードはサイズが変更できるようにした。
一辺が2*p*iの長さの正方形の画像ができます。

連結する倍数iの値を小さくし、 np.zeros(p*p)のpの値で、緑と黒の小さな画像サイズを拡大して実行した。

なお、画像の保存については書いておりませんので、plt.savefig(保存名.jpg)などを適当に追記してください。

以上です。もっと簡単な方法…



【関連】
【Numpy】np.tile()で作る禰豆子の帯の柄 - よちよちpython
もう少し簡単に作れた。



さらに改良した。
【Numpy】np.tile()で市松模様を作る - よちよちpython