NumPy配列ndarrayを回転するnp.rot90
numpy.rot90()
を使うとNumPy配列ndarray
を90度間隔(90度、180度、270度)で回転できる。
ここでは以下の内容について説明する。
numpy.rot90()
の基本的な使い方- デフォルトの処理
- 回転する回数を指定: 引数
k
- 一次元配列の場合
- 三次元以上の多次元配列の場合
- デフォルトの処理
- 回転する平面を指定: 引数
axes
- 画像を回転
回転ではなく転置したい場合は以下の記事を参照。
numpy.rot90()の基本的な使い方
デフォルトの処理
numpy.rot90()
の第一引数に回転させたいndarray
を指定する。デフォルトでは反時計回りに90度回転する。
import numpy as np
a_2d = np.arange(6).reshape(2, 3)
print(a_2d)
# [[0 1 2]
# [3 4 5]]
a_2d_rot = np.rot90(a_2d)
print(a_2d_rot)
# [[2 5]
# [1 4]
# [0 3]]
numpy.rot90()
が返すのはビュー(参照)。元の配列とメモリを共有するため、いずれか一方の値を変更するともう一方の値も変わる。
print(np.shares_memory(a_2d, a_2d_rot))
# True
a_2d_rot[0, 0] = 100
print(a_2d_rot)
# [[100 5]
# [ 1 4]
# [ 0 3]]
print(a_2d)
# [[ 0 1 100]
# [ 3 4 5]]
a_2d[0, 2] = 2
print(a_2d)
# [[0 1 2]
# [3 4 5]]
print(a_2d_rot)
# [[2 5]
# [1 4]
# [0 3]]
別々のデータとして処理したい場合はcopy()
を使う。
a_2d_rot_copy = np.rot90(a_2d).copy()
print(a_2d_rot_copy)
# [[2 5]
# [1 4]
# [0 3]]
print(np.shares_memory(a_2d, a_2d_rot_copy))
# False
回転する回数を指定: 引数k
第二引数k
に整数値を指定すると、その回数分、反時計回りに90度回転する。
print(np.rot90(a_2d, 2))
# [[5 4 3]
# [2 1 0]]
print(np.rot90(a_2d, 3))
# [[3 0]
# [4 1]
# [5 2]]
print(np.rot90(a_2d, 4))
# [[0 1 2]
# [3 4 5]]
print(np.rot90(a_2d, 100))
# [[0 1 2]
# [3 4 5]]
負の値でもOK。回転方向が時計回りとなる。
print(np.rot90(a_2d, -1))
# [[3 0]
# [4 1]
# [5 2]]
print(np.rot90(a_2d, -2))
# [[5 4 3]
# [2 1 0]]
一次元配列の場合
一次元配列は回転できない。
a_1d = np.arange(3)
print(a_1d)
# [0 1 2]
# print(np.rot90(a_1d))
# ValueError: Axes must be different.
1行のみの二次元配列として定義すれば回転可能。
a_2d_row = np.arange(3).reshape(1, 3)
print(a_2d_row)
# [[0 1 2]]
print(np.rot90(a_2d_row))
# [[2]
# [1]
# [0]]
三次元以上の多次元配列の場合
三次元以上の多次元配列も回転可能。
デフォルトの処理
デフォルトでは以下のように回転される。
a_3d = np.arange(24).reshape(2, 3, 4)
print(a_3d)
# [[[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
#
# [[12 13 14 15]
# [16 17 18 19]
# [20 21 22 23]]]
print(a_3d.shape)
# (2, 3, 4)
print(np.rot90(a_3d))
# [[[ 8 9 10 11]
# [20 21 22 23]]
#
# [[ 4 5 6 7]
# [16 17 18 19]]
#
# [[ 0 1 2 3]
# [12 13 14 15]]]
print(np.rot90(a_3d).shape)
# (3, 2, 4)
はじめの2つの軸(次元)からなる平面で回転している。
print(a_3d[:, :, 0])
# [[ 0 4 8]
# [12 16 20]]
print(np.rot90(a_3d)[:, :, 0])
# [[ 8 20]
# [ 4 16]
# [ 0 12]]
回転する平面を指定: 引数axes
三次元以上の多次元配列では、第三引数axes
で回転する平面を指定できる。axes
には要素数2
のタプルやリストなどで平面を構成する2つの軸を指定する。
デフォルトはaxes=(0, 1)
で、はじめの2つの軸からなる平面で回転する。上の省略した場合の例と同じ結果になっていることが確認できる。
print(np.rot90(a_3d, axes=(0, 1)))
# [[[ 8 9 10 11]
# [20 21 22 23]]
#
# [[ 4 5 6 7]
# [16 17 18 19]]
#
# [[ 0 1 2 3]
# [12 13 14 15]]]
別の平面で回転する例は以下の通り。axes
に指定する軸の順番が逆になると回転方向が逆になる。
print(np.rot90(a_3d, axes=(1, 2)))
# [[[ 3 7 11]
# [ 2 6 10]
# [ 1 5 9]
# [ 0 4 8]]
#
# [[15 19 23]
# [14 18 22]
# [13 17 21]
# [12 16 20]]]
print(np.rot90(a_3d, axes=(1, 2)).shape)
# (2, 4, 3)
print(np.rot90(a_3d, axes=(2, 1)))
# [[[ 8 4 0]
# [ 9 5 1]
# [10 6 2]
# [11 7 3]]
#
# [[20 16 12]
# [21 17 13]
# [22 18 14]
# [23 19 15]]]
print(np.rot90(a_3d, axes=(2, 1)).shape)
# (2, 4, 3)
第二引数k
と合わせて指定することも可能。
print(np.rot90(a_3d, 2, axes=(1, 2)))
# [[[11 10 9 8]
# [ 7 6 5 4]
# [ 3 2 1 0]]
#
# [[23 22 21 20]
# [19 18 17 16]
# [15 14 13 12]]]
print(np.rot90(a_3d, -1, axes=(1, 2)))
# [[[ 8 4 0]
# [ 9 5 1]
# [10 6 2]
# [11 7 3]]
#
# [[20 16 12]
# [21 17 13]
# [22 18 14]
# [23 19 15]]]
画像を回転
Pillow(PIL)やOpenCVなどのライブラリを利用して、画像ファイルをNumPy配列ndarray
として読み込むことができる。
numpy.rot90()
を使うと画像を回転させることが可能。例はカラー画像(三次元配列)だが、白黒画像(二次元配列)でも特に引数の指定は必要ない。
以下の画像を例とする。
サンプルコードと結果は以下の通り。
import numpy as np
from PIL import Image
img = np.array(Image.open('data/src/lena.jpg'))
print(type(img))
# <class 'numpy.ndarray'>
print(img.shape)
# (225, 400, 3)
Image.fromarray(np.rot90(img)).save('data/dst/lena_np_rot90.jpg')
Image.fromarray(np.rot90(img, 2)).save('data/dst/lena_np_rot90_180.jpg')
Image.fromarray(np.rot90(img, 3)).save('data/dst/lena_np_rot90_270.jpg')
OpenCVの関数で回転することもできる。