NumPy配列ndarrayをシフト(スクロール)させるnp.roll

Posted: | Tags: Python, NumPy, 画像処理

NumPyの関数np.roll()を使うとNumPy配列ndarrayをシフト(スクロール)させることができる。配列の開始位置をずらすときなどに使う。

ここでは以下の内容について説明する。

  • np.roll()の基本的な使い方
  • 二次元配列(多次元配列)の場合
  • 画像処理への応用(画像をスクロール)

np.roll()の基本的な使い方

一次元配列を例とする。

import numpy as np

a = np.arange(10)
print(a)
# [0 1 2 3 4 5 6 7 8 9]

np.roll()の第一引数aに元のndarray、第二引数shiftにシフトさせる要素数を指定する。新たな配列が返され、元の配列自体は変更されない。

a_roll = np.roll(a, 3)
print(a_roll)
# [7 8 9 0 1 2 3 4 5 6]

print(a)
# [0 1 2 3 4 5 6 7 8 9]

ビューではなくコピーを返すので新たな配列の要素を変更しても元の配列の要素はそのまま。

a_roll[0] = 100
print(a_roll)
# [100   8   9   0   1   2   3   4   5   6]

print(a)
# [0 1 2 3 4 5 6 7 8 9]

第二引数shiftには負の値や全体の要素数を超える値も指定可能。整数intでないとエラーになる。

print(np.roll(a, -3))
# [3 4 5 6 7 8 9 0 1 2]

print(np.roll(a, 12))
# [8 9 0 1 2 3 4 5 6 7]

# print(np.roll(a, 0.5))
# TypeError: slice indices must be integers or None or have an __index__ method

二次元配列(多次元配列)の場合

多次元配列の場合、デフォルトでは一次元化されてからシフトされ元の形状に戻される。

二次元配列を例とすると以下の通り。

a_2d = np.arange(12).reshape(3, 4)
print(a_2d)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

print(np.roll(a_2d, 2))
# [[10 11  0  1]
#  [ 2  3  4  5]
#  [ 6  7  8  9]]

print(np.roll(a_2d, 5))
# [[ 7  8  9 10]
#  [11  0  1  2]
#  [ 3  4  5  6]]

第三引数axisに軸を指定すると、その軸に沿ってシフトされる。

print(np.roll(a_2d, 1, axis=0))
# [[ 8  9 10 11]
#  [ 0  1  2  3]
#  [ 4  5  6  7]]

print(np.roll(a_2d, 2, axis=1))
# [[ 2  3  0  1]
#  [ 6  7  4  5]
#  [10 11  8  9]]

第二引数shiftと第三引数axisにタプルで複数の値を指定すると、複数の軸に沿ってシフトさせることも可能。

print(np.roll(a_2d, (1, 2), axis=(0, 1)))
# [[10 11  8  9]
#  [ 2  3  0  1]
#  [ 6  7  4  5]]

さらに次元数が多い場合も同様。以下は三次元配列の例。

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.roll(a_3d, 3))
# [[[21 22 23  0]
#   [ 1  2  3  4]
#   [ 5  6  7  8]]
# 
#  [[ 9 10 11 12]
#   [13 14 15 16]
#   [17 18 19 20]]]

print(np.roll(a_3d, 2, axis=2))
# [[[ 2  3  0  1]
#   [ 6  7  4  5]
#   [10 11  8  9]]
# 
#  [[14 15 12 13]
#   [18 19 16 17]
#   [22 23 20 21]]]

画像処理への応用(画像をスクロール)

np.roll()を利用するとNumPy配列ndarrayとして読み込んだ画像をスクロールさせることができる。

画像の読み込みや保存などNumPyを使った画像処理の基礎については以下の記事を参照。

縦・横にスクロールさせる例を以下に示す。ここではPillowを使って画像ファイルを読み込んでいるが、ndarrayとして読み込むのであればOpenCVなど他のライブラリを使っても同じ。

import numpy as np
from PIL import Image

img = np.array(Image.open('data/src/lena.jpg'))

print(img.shape)
# (225, 400, 3)

img_scroll = np.roll(img, (50, 100), axis=(0, 1))

Image.fromarray(img_scroll).save('data/dst/lena_numpy_roll.jpg')

元の画像。

lena

スクロールさせた画像。

np.roll image

関連カテゴリー

関連記事