note.nkmk.me

NumPy配列ndarrayを回転するnp.rot90

Date: 2019-06-20 / tags: Python, NumPy

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()を使うと画像を回転させることが可能。例はカラー画像(三次元配列)だが、白黒画像(二次元配列)でも特に引数の指定は必要ない。

以下の画像を例とする。

lena

サンプルコードと結果は以下の通り。

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')

numpy rot90 image

numpy rot90 180 image

numpy rot90 270 image

OpenCVの関数で回転することもできる。

スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事