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

前回はOpenCVで画像の任意の箇所の切り出す方法を紹介しました。今回は、画像を回転させる方法を紹介していきます。

回転にはアフィン変換を用いる

画像変換にはアフィン変換という原理を用いています。

アフィン変換では行列を用いて座標を変換します。なので、アフィン変換によって画像の回転だけでなく拡大縮小や平行移動といったことも実現できます。

画像の回転させるためには、回転させる角度θを以下の行列で定義します。

\begin{equation*} M = \begin{bmatrix} cos\theta & -sin\theta \\ sin\theta & cos\theta \end{bmatrix} \end{equation*}

この行列を画像のベクトルに掛けることで画像を回転させます。

画像左下端を回転中心とした場合

Pythonで実装する

使用する画像

今回も、この素敵なキツネの画像を使っていきます。

画像サイズが大きいのでリサイズして使用します。読み込みまでのコードは以下の通りです。

import cv2

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


#画像のリサイズ(1/4に)
img = cv2.resize(img,(round(width/4), round(height/4)))

変換行列を取得する

次に、画像を回転させるための変換行列を取得します。

変換行列取得には、cv2.getRotationMatrix2D()を用います。構文は以下の通りです。

cv2.getRotationMatrix2D(center, angle, scale)

  • center:回転中心
  • angle:回転させたい角度
  • scale:回転させた際の等方的な画像スケールの係数

angleで指定した角度が正の場合は反時計回りに回転します。時計回りに回転させる場合は負の角度を与えます。コードを書いてみます。

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

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

これで得られる行列は次のようなものです。

\begin{equation*} \begin{bmatrix} \alpha & \beta & (1- \alpha ) \cdot c_x - \beta \cdot c_y \\ - \beta & \alpha & \beta \cdot c_x + (1- \alpha ) \cdot c_y \end{bmatrix} \end{equation*}
\begin{equation*} \begin{array}{l} \alpha = scale \cdot \cos \theta  \\ \beta = scale \cdot \sin \theta \end{array} \end{equation*}

右側の長い式の要素は平行移動に用います。CxとCyは画像を回転させる中心の座標です。Pythonでの実際の値は以下のようになりました。

アフィン変換の実行

変換行列を取得したら、実際に変換します。変換はcv2.warpAffine()で行います。

cv2.warpAffine(src, M, dsize)

  • src:変換元の画像
  • M:変換行列
  • dsize:出力画像のサイズ

実際にコードを書きます。

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

この結果得られた画像は

45°回転したものになりました。アフィン変換では、任意の角度に画像を回転させることができます。

コード全体

ここまでのコードをまとめます。

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

OpenCVの学習におすすめ書籍

PythonでOpenCV始めてみようという方におすすめなのが以下書籍です。実装例も豊富なので、1からコードを書かずとも学習を進めることができます。

オライリーの1冊は読み物というより辞書としての利用におすすめです。お値段結構しますが、細かい情報までしっかりと詰め込まれています。

まとめ

OpenCVで画像を回転させる方法を紹介しました。原理は難しそうですが、コード自体は簡単に実装できます。

アフィン変換で画像を回転させる手順を最後にまとめておきます。

  1. 回転中心を決める
  2. getRotationMatrix2D()で二次元の変換行列を作成する
  3. warpAffine()で変換行列をもとにアフィン変換を実行する

OpenCVの基礎を身につけるためのロードマップは以下を参考にしてください。

ではでは👋