OpenCV, NumPyで画像を回転・上下左右反転(rotate, flipなど)
PythonのOpenCVでは画像をNumPy配列ndarray
として扱う。画像(= ndarray
)を回転または上下左右に反転(ミラー反転)するための関数はOpenCVにもNumPyにもあり、どちらを使ってもよい。
ここでは以下の内容について説明する。
- OpenCVで画像を回転:
cv2.rotate()
- OpenCVで画像を上下左右に反転:
cv2.flip()
- NumPyで画像を回転:
np.rot90()
- NumPyで画像を上下左右に反転:
np.flip()
NumPyでの画像処理についての基本は以下の記事を参照。OpenCVを使わずにPillow(PIL)で画像ファイルを読み込んでndarray
に変換する方法や、ndarray
を画像ファイルとして保存する方法などもこちら。
OpenCVでの画像ファイルの読み書きについては以下の記事を参照。
また、Pillow(PIL)を使って画像の回転・反転をすることもできる。単純に既存の画像ファイルを読み込んで回転・反転して保存するだけならPillowが一番シンプルで簡単。90度刻みではなく任意の角度で回転可能。
サンプルコードでは以下の画像を例として使う。
OpenCVで画像を回転: cv2.rotate()
OpenCVで画像(= ndarray
)を回転する関数はcv2.rotate()
第一引数に元のndarray
、第二引数rotateCode
に回転の角度と方向を定数で指定する。
rotateCode
に指定できる定数は以下の三種類。
cv2.ROTATE_90_CLOCKWISE
: 時計回りに90度cv2.ROTATE_90_COUNTERCLOCKWISE
: 反時計回りに90度cv2.ROTATE_180
: 180度
サンプルコードと結果は以下の通り。
import cv2
img = cv2.imread('data/src/lena.jpg')
print(type(img))
# <class 'numpy.ndarray'>
print(img.shape)
# (225, 400, 3)
img_rotate_90_clockwise = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)
cv2.imwrite('data/dst/lena_cv_rotate_90_clockwise.jpg', img_rotate_90_clockwise)
# True
img_rotate_90_counterclockwise = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)
cv2.imwrite('data/dst/lena_cv_rotate_90_counterclockwise.jpg', img_rotate_90_counterclockwise)
# True
img_rotate_180 = cv2.rotate(img, cv2.ROTATE_180)
cv2.imwrite('data/dst/lena_cv_rotate_180.jpg', img_rotate_180)
# True
90度刻みではなく任意の角度で回転したい場合はアフィン変換cv2.warpAffine()
を使う。
上述のように、Pillowでは任意の角度で回転できる。こちらのほうが簡単。
OpenCVで画像を上下左右に反転: cv2.flip()
OpenCVで画像(= ndarray
)を上下左右に反転する関数はcv2.flip()
第一引数に元のndarray
、第二引数flipCode
に反転方向を示す値を指定する。
flipCode
の値によって以下のように反転する。
flipcode = 0
: 上下反転flipcode > 0
: 左右反転flipcode < 0
: 上下左右反転
サンプルコードと結果は以下の通り。
import cv2
img = cv2.imread('data/src/lena.jpg')
print(type(img))
# <class 'numpy.ndarray'>
print(img.shape)
# (225, 400, 3)
img_flip_ud = cv2.flip(img, 0)
cv2.imwrite('data/dst/lena_cv_flip_ud.jpg', img_flip_ud)
# True
img_flip_lr = cv2.flip(img, 1)
cv2.imwrite('data/dst/lena_cv_flip_lr.jpg', img_flip_lr)
# True
img_flip_ud_lr = cv2.flip(img, -1)
cv2.imwrite('data/dst/lena_cv_flip_ud_lr.jpg', img_flip_ud_lr)
# True
NumPyで画像を回転: np.rot90()
NumPyでndarray
を回転する関数はnp.rot90()
。
第一引数に元のndarray
、第二引数に何回90度回転するかの値を指定する。
第二引数を省略した場合はデフォルトの反時計回りに90度回転となり、第二引数を2
, 3
とすると反時計回りに180度回転、270度回転となる。詳細は以下の記事を参照。
サンプルコードと結果は以下の通り。
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')
なお、ここではPillow(PIL)を使って画像ファイルを読み書きしているが、あくまでもndarray
を回転しているだけなので、上の例のようにOpenCVで読み書きする場合にOpenCVの関数ではなくNumPyの関数を使って回転の処理を行うこともできる。次の反転の例でも同様。
NumPyで画像を上下左右に反転: np.flip()
NumPyでndarray
を上下左右に反転する関数はnp.flip()
。さらに、上下に反転するnp.flipud()
、左右に反転するnp.fliplr()
もある。
np.flip()
の引数を指定すれば上下反転も左右反転も可能だが、np.flipud()
, np.fliplr()
を使ったほうが簡単。上下左右どちらも反転したい場合はnp.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')