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

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

今回はOpenCVで読み込んだ画像を回転させてみる。

お願いします。

画像回転の原理

Pythonでの実装を説明する前に、画像回転の原理を簡単に説明する。

原理?難しそうなので、はやく実装してください。

確かにテック君には難しすぎる内容ではあるが、概要だけなので我慢してくれ。

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

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

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

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

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

うわ、ダイジェスト版の説明になってる。

わしのセリフで説明すると長くなりすぎるだろう。

説明にもあるが、アフィン変換を使えば回転だけでなく拡大縮小や平行移動も可能になる。

なんか便利そうなので、名前だけ覚えておきますよ。

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

パッと見た感じアフィン変換を使ってそうですね。

うむ。では順に解説する。

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

画像読み込みの部分は割愛する。
画像を回転させるには、先ほどの変換行列を取得する必要がある。

行列はどうやって取得するんです?

便利なことに、OpenCVでは変換行列を取得する関数が用意されている。
それがcv2.getRotationMatrix2D()だ。

なんかかっこいい。

引数

引数説明
center画像における回転の中心座標
angle回転角度。正の数を指定すると反時計回り
scale等方性のスケール係数
height, width = img.shape[:2]
center = (width/2, height/2)

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

angleで指定した角度が正の場合は反時計回りに回転する。時計回りに回転させる場合は負の角度を指定する。

負の角度って、-90°みたいな感じですね。

その通り。例の場合は45°だがな。

取得できる値

cv2.getRotationMatrix2D()で取得できる値は、以下の要は配列だ。

\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*}

もう、目が痛いですxx

まあ無理もないな。
右側の長い式の要素は画像の平行移動に用いる。CxとCyは画像を回転させる中心の座標という意味だ。

ちなみに変数rotate_matrixには、以下のような二次元配列が格納される。 

0.707106780.70710678-109.4915575
-0.707106780.70710678555.66399692
rotate_matrix

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

変換行列を取得したので、ここからアフィン変換をやっていく。
アフィン変換はcv2.warpAffine()を使う。

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

引数

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

引数Mには、cv2.getRotationMatrix2D()で取得した変換行列を使うんですね

結果

Rotated image

画像が45°回転してますね!

うむ。このようにして、アフィン変換を使うと任意の角度に画像を回転させることができる。

では今回はここまでにしよう。次回も画像の処理についての続きだ。

ありがとうございました~~