Pynote

Python、機械学習、画像処理について

OpenCV - 画像座標系における回転、拡大縮小について

概要

画像座標系における回転、拡大縮小について解説し、OpenCV で回転行列を作成する方法を紹介する。
作成した回転行列で画像を回転させるには、以下の記事を参照されたい。

pynote.hatenablog.com

回転行列を作成する。

OpenCVcv2.getRotationMatrix2D() で拡大縮小も考慮し、指定した点を中心にした回転行列を作成できる。

retval = cv2.getRotationMatrix2D(center, angle, scale)

引数

  • center: 回転の中心
  • angle: 回転角度 (度、反時計回り)
  • scale: スケール

返り値

  • retval: 回転行列

解説

次の4つの変換をまとめた 2 \times 3 のアフィン変換行列を作成する。

同次座標系で考える。回転の中心を center = (c_x, c_y)^T、回転角度を \theta、スケールを s とする。

1 回転の中心が原点となるように、(-c_x, -c_y) だけ平行移動する。

 \displaystyle
T_1 = \begin{pmatrix}
1 & 0 & -c_x \\
0 & 1 & -c_y \\
0 & 0 & 1 \\
\end{pmatrix}

2 原点を中心に反時計回りに \theta だけ回転する。

 \displaystyle
R = \begin{pmatrix}
\cos \theta & \sin \theta & 0 \\
 -\sin \theta & \cos \theta & 0 \\
0 & 0 & 1 \\
\end{pmatrix}

3 s 倍だけ拡大縮小する。

 \displaystyle
S = \begin{pmatrix}
s & 1 & 0 \\
1 & s & 0 \\
0 & 0 & 1 \\
\end{pmatrix}

4 1で平行移動した分を戻すため、(c_x, c_y) だけ平行移動する。

 \displaystyle
T_2 = \begin{pmatrix}
1 & 0 & c_x \\
0 & 1 & c_y \\
0 & 0 & 1 \\
\end{pmatrix}

以上4つのアフィン変換を1つにまとめると、

 \displaystyle
\begin{align}
T_2SRT_1
&=
\begin{pmatrix}
1 & 0 & c_x \\
0 & 1 & c_y \\
0 & 0 & 1 \\
\end{pmatrix}
\begin{pmatrix}
s & 1 & 0 \\
1 & s & 0 \\
0 & 0 & 1 \\
\end{pmatrix}
\begin{pmatrix}
\cos \theta & \sin \theta & 0 \\
 -\sin \theta & \cos \theta & 0 \\
0 & 0 & 1 \\
\end{pmatrix}
\begin{pmatrix}
1 & 0 & -c_x \\
0 & 1 & -c_y \\
0 & 0 & 1 \\
\end{pmatrix} \\
&=
\begin{pmatrix}
1 & 0 & c_x \\
0 & 1 & c_y \\
0 & 0 & 1 \\
\end{pmatrix}
\begin{pmatrix}
s & 1 & 0 \\
1 & s & 0 \\
0 & 0 & 1 \\
\end{pmatrix}
\begin{pmatrix}
\cos \theta & \sin \theta & -c_x \cos \theta - c_y \sin \theta \\
 -\sin \theta & \cos \theta & c_x \sin \theta - c_y \cos \theta \\
0 & 0 & 1 \\
\end{pmatrix} \\
&=
\begin{pmatrix}
1 & 0 & c_x \\
0 & 1 & c_y \\
0 & 0 & 1 \\
\end{pmatrix}
\begin{pmatrix}
s \cos \theta & s \sin \theta & -s c_x \cos \theta -s c_y \sin \theta \\
 - s \sin \theta & s \cos \theta & s c_x \sin \theta -s c_y \cos \theta \\
0 & 0 & 1 \\
\end{pmatrix} \\
&=
\begin{pmatrix}
s \cos \theta & s \sin \theta & -s c_x \cos \theta -s c_y \sin \theta + c_x \\
 - s \sin \theta & s \cos \theta & s c_x \sin \theta -s c_y \cos \theta + c_y \\
0 & 0 & 1 \\
\end{pmatrix}
\end{align}

ここで、\alpha = s \cos \theta, \beta = s \sin \theta とおくと、

 \displaystyle
\begin{pmatrix}
\alpha & \beta & (1 - \alpha) c_x - \beta c_y \\
 -\beta & \alpha & \beta c_x + (1 -  \alpha) c_y \\
0 & 0 & 1 \\
\end{pmatrix}

このうち、3行目を除いた 2 \times 3 の行列が作成される行列である。


サンプルコード

import cv2

# 点 (100, 100) を中心に反時計回りに120度回転し、3倍に拡大するアフィン変換行列を作成する。
M = cv2.getRotationMatrix2D(center=(100, 100), angle=120, scale=3.)
print(M)
[[  -1.5           2.59807621   -9.80762114]
 [  -2.59807621   -1.5         509.80762114]]