よちよちpython

独習 python/Qpython/Pydroid3/termux/Linux

【Numpy】np.tile()で作る禰豆子の帯の柄

鬼滅の刃』の竈門禰豆子の帯の柄を、Numpyのnp.tile()を使って作ってみる。

作業環境


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



【参考】
NumPy配列ndarrayをタイル状に繰り返し並べるnp.tile | note.nkmk.me



np.tile()の使い方の確認


配列.repeat(回数, axis=軸)np.tile(配列, (1次元倍率, 2次元倍率,3次元倍率))は元の配列を次元軸に数倍拡大できるが、違いを確認しておく。

import numpy as np
import matplotlib.pyplot as plt
# 元の配列を生成
nry = np.arange(3)

# repeatで拡大
nry_repeat = nry.repeat(3)

# tileで拡大
nry_tile = np.tile(nry, 3)

# 表示
print("元の配列", nry)
print("repeat", nry_repeat)
print("tile", nry_tile)
元の配列 [0 1 2]
repeat [0 0 0 1 1 1 2 2 2]
tile [0 1 2 0 1 2 0 1 2]

各要素が繰り返すか、塊で繰り返すかの違いがある。



次は次元を増やした配列で試してみます。

# 元の配列を生成
ndry = np.arange(1,10).reshape(3,3)

print("元の配列 2次元\n\n", ndry)
print("="*40)
print("repeat, 軸0\n\n", ndry.repeat(2,axis=0))
print("="*40)
print("repeat, 軸1\n\n", ndry.repeat(2,axis=1))
print("="*40)


print("tile 2\n\n", np.tile(ndry, 2))
print("="*40)
print("tile (2,3)\n\n", np.tile(ndry,(2,3)))
print("="*40)


print("tile (1,2)\n\n", np.tile(ndry, (1,2)))
      
      
元の配列 2次元

 [[1 2 3]
 [4 5 6]
 [7 8 9]]
========================================
repeat, 軸0

 [[1 2 3]
 [1 2 3]
 [4 5 6]
 [4 5 6]
 [7 8 9]
 [7 8 9]]
========================================
repeat, 軸1

 [[1 1 2 2 3 3]
 [4 4 5 5 6 6]
 [7 7 8 8 9 9]]
========================================
tile 2

 [[1 2 3 1 2 3]
 [4 5 6 4 5 6]
 [7 8 9 7 8 9]]
========================================
tile (2,3)

 [[1 2 3 1 2 3 1 2 3]
 [4 5 6 4 5 6 4 5 6]
 [7 8 9 7 8 9 7 8 9]
 [1 2 3 1 2 3 1 2 3]
 [4 5 6 4 5 6 4 5 6]
 [7 8 9 7 8 9 7 8 9]]
========================================
tile (1,2)

 [[1 2 3 1 2 3]
 [4 5 6 4 5 6]
 [7 8 9 7 8 9]]

np.tile(配列, 2)np.tile(配列, (1,2)) と等しい。



画像作成


竈門禰豆子の帯の市松模様np.tile()で作っていきます。

手順


  1. 単色で色違いの2枚の画像を互い違いに4枚使って正方形に組んだブロックを作る
  2. np.tile()で倍増させて拡大する



単色の色


禰豆子の帯は2色の市松模様です。

  • 白:RGB(251, 242, 239)
  • 赤茶:RGB(154, 49, 72)

この2色を使います。



単色の画像サイズ


基となるゼロ配列の生成


2色を互い違いに4枚組み合わせたブロックを基本配列とします。

# 単色の一辺サイズ
p=15 
# ゼロ配列生成
np_block = np.zeros((p*2) * (p*2), dtype=int).reshape(p*2, p*2)
#np_block



2*2のブロック生成


上で作成した基本ブロックを、互い違いになるように色の値を変更していきます。
それをRGBの3つ作ります。

白R=251に変更

# コピー
np_block_r = np_block.copy()

# 値を変更
np_block_r[0:15, 0:15] = 251
np_block_r[15:30, 15:30] = 251
#np_block_r

白G=242に変更

# コピー
np_block_g = np_block.copy()

np_block_g[0:15, 0:15] = 242
np_block_g[15:30, 15:30] = 242
#np_block_g

白B=239に変更

# コピー
np_block_b = np_block.copy()

np_block_b[0:15, 0:15] = 239
np_block_b[15:30, 15:30] = 239
#np_block_b

赤茶R=154に変更

#
np_block_r[0:15, 15:30] = 154
np_block_r[15:30, 0:15] = 154
#np_block_r

赤茶G=49に変更

# 
np_block_g[0:15, 15:30] = 49
np_block_g[15:30, 0:15] = 49
#np_block_g

赤茶B=72に変更

#
np_block_b[0:15, 15:30] = 72
np_block_b[15:30, 0:15] = 72
#np_block_b



三次元方向に結合


RGBの3つの配列を、三次元方向に結合します。

np_nezu_block = np.stack([np_block_r, np_block_g, np_block_b], axis=2)
plt.imshow(np_nezu_block)

f:id:chayarokurokuro:20201229080602j:plain

これが基の配列でできた基本ブロックになる。

次は、この基本ブロックを繰り返すことで画像を拡大させていく。



np.tile()で繰り返し


np_Nezuko = np.tile(np_nezu_block, (5,7,1))
plt.imshow(np_Nezuko)

f:id:chayarokurokuro:20201229080644j:plain

できました。



コードをまとめる


import numpy as np
import matplotlib.pyplot as plt


### 設定 ###
# 各色の一辺のサイズ(ピクセル)
p=15


### 基のブロック生成
# 2色を互い違いにした4枚のブロックのゼロ配列
np_block = np.zeros((p*2) * (p*2), dtype=int).reshape(p*2, p*2)



### 色の変更 ###
## 白R=251に変更
# コピー
np_block_r = np_block.copy()
# 値を変更
np_block_r[0:p, 0:p] = 251
np_block_r[p:p+p, p:p+p] = 251



## 白G=242
# コピー
np_block_g = np_block.copy()
# 色の変更
np_block_g[0:p, 0:p] = 242
np_block_g[p:p+p, p:p+p] = 242



## 白B=239
# コピー
np_block_b = np_block.copy()
# 色の変更
np_block_b[0:p, 0:p] = 239
np_block_b[p:p+p, p:p+p] = 239



## 赤茶R=154
# 色の変更
np_block_r[0:p, p:p+p] = 154
np_block_r[p:p+p, 0:p] = 154



## 赤茶G=49
# 色の変更
np_block_g[0:p, p:p+p] = 49
np_block_g[p:p+p, 0:p] = 49



## 赤茶B=72
# 色の変更
np_block_b[0:p, p:p+p] = 72
np_block_b[p:p+p, 0:p] = 72



### RGBを三次元方向に結合 ###
np_nezu_block = np.stack([np_block_r, np_block_g, np_block_b], axis=2)
#plt.imshow(np_nezu_block)



### ブロックを繰り返す ###
np_Nezuko = np.tile(np_nezu_block, (5,7,1))
# 画像の表示
plt.imshow(np_Nezuko)
# 画像の保存
plt.axis("off")
plt.savefig("禰豆子の帯.jpg")

f:id:chayarokurokuro:20201229080716j:plain



今回は以上です。

前回の炭治郎の羽織の柄と少し作り方を変えた。
しかし色の変更の方法はだいぶんアホっぽい。もっと簡単にできるはず…



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