ITや趣味など気軽に投稿しています。

【Python】OpenCVで画像を回転させる

画像処理では、画像を任意の角度に回転させたい場面があります。例えば、傾いて撮影された画像を補正したり、データ拡張(Data Augmentation)で学習データを増やしたりするケースです。

この記事では、OpenCVのアフィン変換を使って画像を回転させる方法を解説します。

画像回転の原理

画像の回転にはアフィン変換という数学的手法を用います。アフィン変換では行列を使って座標を変換するため、回転だけでなく拡大縮小や平行移動も同じ枠組みで実現できます。

画像を角度θだけ回転させるには、以下の回転行列を使用します。

回転行列

この行列を画像の各ピクセルの座標に掛けることで、画像全体を回転させます。

OpenCVで画像を回転させる

サンプルコード

まず、画像回転のコード全体を示します。

import cv2

path = "input/fox.jpg"
img = cv2.imread(path)
height, width = img.shape[:2]
img = cv2.resize(img, (round(width / 4), round(height / 4)))

height, width = img.shape[:2]
center = (width / 2, height / 2)

# アフィン変換行列を作成する
rotate_matrix = cv2.getRotationMatrix2D(center=center, angle=45, scale=1)

# アフィン変換行列を画像に適用する
rotated_image = cv2.warpAffine(src=img, M=rotate_matrix, dsize=(width, height))

cv2.imshow('Rotated image', rotated_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

処理は大きく2つのステップに分かれます。

  1. cv2.getRotationMatrix2D()でアフィン変換行列を作成する
  2. cv2.warpAffine()で変換行列を画像に適用する

変換行列を取得する(cv2.getRotationMatrix2D())

回転を行うには、まず変換行列を取得します。OpenCVではcv2.getRotationMatrix2D()で簡単に取得できます。

引数

引数説明
center画像における回転の中心座標
angle回転角度(正の値で反時計回り、負の値で時計回り)
scaleスケール係数(1.0で等倍)
height, width = img.shape[:2]
center = (width / 2, height / 2)

# アフィン変換行列を作成する
rotate_matrix = cv2.getRotationMatrix2D(center=center, angle=45, scale=1)

取得できる値

cv2.getRotationMatrix2D()は2×3の変換行列を返します。

変換行列
パラメータ

右側の列は画像の平行移動に使用される成分で、CxとCyは回転中心の座標です。

例えば、上記のコードで取得されるrotate_matrixは以下のような値になります。

0.707106780.70710678-109.4915575
-0.707106780.70710678555.66399692

アフィン変換の実行(cv2.warpAffine())

変換行列を取得したら、cv2.warpAffine()で画像に適用します。

# アフィン変換行列を画像に適用する
rotated_image = cv2.warpAffine(src=img, M=rotate_matrix, dsize=(width, height))

引数

引数説明
src変換元の画像
Mcv2.getRotationMatrix2D()で取得した2×3の変換行列
dsize出力画像のサイズ (幅, 高さ)

結果

Rotated image

画像が45°反時計回りに回転していることが確認できます。angleの値を変更することで、任意の角度に回転させることが可能です。

まとめ

今回は、OpenCVで画像を回転させる方法を紹介しました。

  • 画像の回転にはアフィン変換を使用する
  • cv2.getRotationMatrix2D()で変換行列を作成し、cv2.warpAffine()で適用する
  • angleに正の値を指定すると反時計回り、負の値で時計回りに回転する
  • scaleパラメータで回転と同時に拡大・縮小も可能