NumPy配列ndarrayを上下左右に反転するnp.flip, np.flipud, np.fliplr
numpy.flip()
を使うとNumPy配列ndarray
を上下左右に反転できる。上下反転に特化したnumpy.flipud()
、左右反転に特化したnumpy.fliplr()
もある。
ここでは以下の内容について説明する。
- 配列
ndarray
を上下反転:np.flipud()
- 配列
ndarray
を左右反転:np.fliplr()
- 配列
ndarray
を任意の軸(次元)で反転:np.flip()
- デフォルトの処理
- 反転する軸を指定: 引数
axis
- 画像を上下左右に反転
適宜説明するが、これらの関数を使わずに、スライス::-1
で反転させることも可能。
配列ndarrayを上下反転: np.flipud()
配列ndarray
を上下反転するにはnumpy.flipud()
を使う。ud
はUp
/ Down
の意味。
numpy.flipud()
が返すのはビュー(参照)。元の配列とメモリを共有するため、いずれか一方の値を変更するともう一方の値も変わる。
import numpy as np
a_2d = np.arange(6).reshape(2, 3)
print(a_2d)
# [[0 1 2]
# [3 4 5]]
a_2d_flipud = np.flipud(a_2d)
print(a_2d_flipud)
# [[3 4 5]
# [0 1 2]]
print(np.shares_memory(a_2d, a_2d_flipud))
# True
別々のデータとして処理したい場合はcopy()
を使う。
a_2d_flipud_copy = np.flipud(a_2d).copy()
print(a_2d_flipud_copy)
# [[3 4 5]
# [0 1 2]]
print(np.shares_memory(a_2d, a_2d_flipud_copy))
# False
numpy.flipud()
はスライス[::-1]
と同等。最初の軸(次元)が反転する。
print(a_2d[::-1])
# [[3 4 5]
# [0 1 2]]
一次元配列や三次元以上の多次元配列に対しても同様。最初の軸が反転する。特に一次元配列の場合は「上下反転」というイメージと異なる結果なので注意。
a_1d = np.arange(3)
print(a_1d)
# [0 1 2]
print(np.flipud(a_1d))
# [2 1 0]
print(a_1d[::-1])
# [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(np.flipud(a_3d))
# [[[12 13 14 15]
# [16 17 18 19]
# [20 21 22 23]]
#
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]]
print(a_3d[::-1])
# [[[12 13 14 15]
# [16 17 18 19]
# [20 21 22 23]]
#
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]]
三次元以上の多次元配列で任意の軸を反転させたい場合は後述のnumpy.flip()
を使う。
配列ndarrayを左右反転: np.fliplr()
配列ndarray
を左右反転するにはnumpy.fliplr()
を使う。lr
はLeft
/ Right
の意味。
numpy.fliplr()
が返すのはビュー(参照)。別々のデータとして処理したい場合はnumpy.flipud()
の例と同様にcopy()
を使えばよい。
import numpy as np
a_2d = np.arange(6).reshape(2, 3)
print(a_2d)
# [[0 1 2]
# [3 4 5]]
a_2d_fliplr = np.fliplr(a_2d)
print(a_2d_fliplr)
# [[2 1 0]
# [5 4 3]]
print(np.shares_memory(a_2d, a_2d_fliplr))
# True
numpy.fliplr()
はスライス[:, ::-1]
と同等。二番目の軸(次元)が反転する。
print(a_2d[:, ::-1])
# [[2 1 0]
# [5 4 3]]
一次元配列や三次元以上の多次元配列に対しても同様。二番目の軸が反転する。一次元配列の場合は二番目の軸が存在しないためエラーになるので注意。
a_1d = np.arange(3)
print(a_1d)
# [0 1 2]
# print(np.fliplr(a_1d))
# ValueError: Input must be >= 2-d.
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(np.fliplr(a_3d))
# [[[ 8 9 10 11]
# [ 4 5 6 7]
# [ 0 1 2 3]]
#
# [[20 21 22 23]
# [16 17 18 19]
# [12 13 14 15]]]
print(a_3d[:, ::-1])
# [[[ 8 9 10 11]
# [ 4 5 6 7]
# [ 0 1 2 3]]
#
# [[20 21 22 23]
# [16 17 18 19]
# [12 13 14 15]]]
配列ndarrayを任意の軸(次元)で反転: np.flip()
配列ndarray
を上下左右を含む任意の軸(次元)で反転するにはnumpy.flip()
を使う。複数の軸で同時に反転することも可能。
デフォルトの処理
デフォルトではすべての軸が反転する。二次元配列の場合、上下左右に反転する。
numpy.flip()
が返すのはビュー(参照)。別々のデータとして処理したい場合はnumpy.flipud()
の例と同様にcopy()
を使えばよい。
import numpy as np
a_2d = np.arange(6).reshape(2, 3)
print(a_2d)
# [[0 1 2]
# [3 4 5]]
a_2d_flip = np.flip(a_2d)
print(a_2d_flip)
# [[5 4 3]
# [2 1 0]]
print(np.shares_memory(a_2d, a_2d_flip))
# True
スライスですべての軸を反転するのと同等。
print(a_2d[::-1, ::-1])
# [[5 4 3]
# [2 1 0]]
一次元配列や三次元以上の多次元配列に対しても同様。デフォルトではすべての軸が反転する。
a_1d = np.arange(3)
print(a_1d)
# [0 1 2]
print(np.flip(a_1d))
# [2 1 0]
print(a_1d[::-1])
# [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(np.flip(a_3d))
# [[[23 22 21 20]
# [19 18 17 16]
# [15 14 13 12]]
#
# [[11 10 9 8]
# [ 7 6 5 4]
# [ 3 2 1 0]]]
print(a_3d[::-1, ::-1, ::-1])
# [[[23 22 21 20]
# [19 18 17 16]
# [15 14 13 12]]
#
# [[11 10 9 8]
# [ 7 6 5 4]
# [ 3 2 1 0]]]
反転する軸を指定: 引数axis
反転する軸を第二引数axis
で指定可能。axis=0
はflipud()
、axis=1
はfliplr()
と同等。
print(np.flip(a_3d, 0))
# [[[12 13 14 15]
# [16 17 18 19]
# [20 21 22 23]]
#
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]]
print(a_3d[::-1])
# [[[12 13 14 15]
# [16 17 18 19]
# [20 21 22 23]]
#
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]]
print(np.flipud(a_3d))
# [[[12 13 14 15]
# [16 17 18 19]
# [20 21 22 23]]
#
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]]
print(np.flip(a_3d, 1))
# [[[ 8 9 10 11]
# [ 4 5 6 7]
# [ 0 1 2 3]]
#
# [[20 21 22 23]
# [16 17 18 19]
# [12 13 14 15]]]
print(a_3d[:, ::-1])
# [[[ 8 9 10 11]
# [ 4 5 6 7]
# [ 0 1 2 3]]
#
# [[20 21 22 23]
# [16 17 18 19]
# [12 13 14 15]]]
print(np.fliplr(a_3d))
# [[[ 8 9 10 11]
# [ 4 5 6 7]
# [ 0 1 2 3]]
#
# [[20 21 22 23]
# [16 17 18 19]
# [12 13 14 15]]]
print(np.flip(a_3d, 2))
# [[[ 3 2 1 0]
# [ 7 6 5 4]
# [11 10 9 8]]
#
# [[15 14 13 12]
# [19 18 17 16]
# [23 22 21 20]]]
print(a_3d[:, :, ::-1])
# [[[ 3 2 1 0]
# [ 7 6 5 4]
# [11 10 9 8]]
#
# [[15 14 13 12]
# [19 18 17 16]
# [23 22 21 20]]]
axis
にはタプルやリストで複数の軸を指定することもできる。
print(np.flip(a_3d, (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(a_3d[:, ::-1, ::-1])
# [[[11 10 9 8]
# [ 7 6 5 4]
# [ 3 2 1 0]]
#
# [[23 22 21 20]
# [19 18 17 16]
# [15 14 13 12]]]
まとめると以下のようになる。公式ドキュメントより引用。
flip(m, 0) is equivalent to flipud(m).
flip(m, 1) is equivalent to fliplr(m).
flip(m, n) corresponds to m[...,::-1,...] with ::-1 at position n.
flip(m) corresponds to m[::-1,::-1,...,::-1] with ::-1 at all positions.
flip(m, (0, 1)) corresponds to m[::-1,::-1,...] with ::-1 at position 0 and position 1.
numpy.flip — NumPy v1.16 Manual
画像を上下左右に反転
Pillow(PIL)やOpenCVなどのライブラリを利用して、画像ファイルをNumPy配列ndarray
として読み込むことができる。
numpy.flip()
などを使うと画像を上下左右に反転させることが可能。例はカラー画像(三次元配列)だが、白黒画像(二次元配列)でも特に引数の指定は変わらない。
以下の画像を例とする。
サンプルコードと結果は以下の通り。
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.flipud(img)).save('data/dst/lena_np_flipud.jpg')
Image.fromarray(np.fliplr(img)).save('data/dst/lena_np_fliplr.jpg')
Image.fromarray(np.flip(img, (0, 1))).save('data/dst/lena_np_flip_ud_lr.jpg')
OpenCVの関数で反転することもできる。