Pynote

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

OpenCV - カメラモデル

カメラモデル

3次元空間上の点とカメラで撮影した画像上の点との対応関係を記述するモデルである。
具体的には、3次元空間上の点 (x, y, z)^T から画像上の点 (u, v)^T へ写す写像を求める。


\left( \begin{matrix}
u\\
v\\
1
\end{matrix} \right)
= M
\left( \begin{matrix}
x\\
y\\
z\\
1
\end{matrix} \right)

この行列は M はカメラの内部パラメータ (intrinsic) 及び外部パラメータ (extrinsic) から作られる。

カメラの内部パラメータ

カメラの内部パラメータはカメラ固有のパラメータであり、5種類の変数によって決まる。

焦点距離

カメラの中心を原点とした座標系をカメラ座標系 (camera coordinate system) という。
また、3次元空間を射影する平面を画像平面 (image plane) または焦点面 (focal plane) といい、カメラ座標系の z 軸と直交するように配置する。
カメラ座標系で点 (X_c, Y_c, Z_c)^T に対応する画像平面上の点 (X_i, Y_i)^T を求める。

f:id:nekobean:20170820164828p:plain

カメラ座標系の原点から画像平面までの距離を焦点距離といい、f で表す。
すると、相似の関係より、


\left( \begin{matrix}
X_i\\
Y_i\\
\end{matrix} \right)
=
\left( \begin{matrix}
f \frac{X_c}{Z_c}\\
f \frac{Y_c}{Z_c}\\
\end{matrix} \right)

f:id:nekobean:20170820165106p:plain

カメラ座標と画像座標

画像平面の左下を原点とした座標系を画像座標系 (image coordinate system) という。
カメラ座標系の単位は物理量 (例: メートル) だが、画像座標系の単位はピクセルである。
通常、ピクセルは離散的な値をとるが、ここでは連続値とする。

f:id:nekobean:20170820211942p:plain

画像座標系で光軸 (カメラ座標系の z 軸) が通る点を主点 (principle point) といい、(c_u, c_v)^T とする。

また、水平方向、垂直方向のピクセルの物理的な間隔をそれぞれ k_u, k_v とする。
例えば、カメラ座標系の単位がメートルならば、k_u, k_v の単位は pixel / m であり、1メートルあたりのピクセル数を表す。水平方向と垂直方向でそれぞれ別であるのは、1ピクセルの大きさが水平方向と垂直方向で違う場合を考慮しているからである。

すると、画像平面上のカメラ座標系で (X_i, Y_i) の点は画像座標系で (U, V) となる。


\left( \begin{matrix}
U\\
V\\
\end{matrix} \right)
=
\left( \begin{matrix}
k_u f \frac{X_c}{Z_c} + c_u\\
k_v f \frac{Y_c}{Z_c} + c_v\\
\end{matrix} \right)

Skew

画像平面が長方形でなく、以下のように平行四辺形に歪んでる (skew) 場合を考慮する。

f:id:nekobean:20170820171542p:plain

すでに求めた軸が直交する場合の画像座標系の点 (U, V)^T から軸が角度 \theta で交わる場合の画像座標系への変換を考える。

f:id:nekobean:20170820172658p:plain

すると変換後の点 (U', V')^T

 V' \sin \theta = V \Leftrightarrow V' = \frac{V}{sin \theta}
 U' = U - V' \cos \theta = U - V \frac{\cos \theta}{\sin \theta} = U - V \cot \theta

であるから、


[\begin{array}{c}
\left( {\begin{array}{*{20}{l}}
{U'}\\
{V'}
\end{array}} \right)
=
\left( {\begin{array}{*{20}{c}}
{{k_u}f\frac{{{X_c}}}{{{Z_c}}} - {k_v}f\frac{{{Y_c}}}{{{Z_c}}}\cot \theta  + ({c_u} - {c_v}\cot \theta )}\\
{{k_v}f\frac{{{Y_c}}}{{{Z_c}}}\frac{1}{{sin\theta }} + {c_v}\frac{1}{{sin\theta }}}
\end{array}} \right)
\end{array}]

ここで、光軸の通る点を c'_u = c_u - c_v \cot \thetac'_v = c_v \frac{1}{\sin \theta} とし、\alpha = k_u f, \beta = k_v f, s = -k_v f \cot \theta と置くと、


{Z_c}\left( {\begin{array}{*{20}{c}}
{U'}\\
{V'}\\
1
\end{array}} \right)
=
\left( {\begin{array}{*{20}{c}}
\alpha &s&{{{c'}_u}}\\
0&\beta &{{{c'}_v}}\\
0&0&1
\end{array}} \right)\left( {\begin{array}{*{20}{c}}
{{X_c}}\\
{{Y_c}}\\
{{Z_c}}
\end{array}} \right)

この 3x3 行列をカメラ行列 (camera matrix) という。

カメラの外部パラメータ

これまでカメラ座標系のある点からの画像座標系への変換を求めた。
対象の点が世界座標系で表される場合、カメラ行列による変換を行う前に、対象の点をカメラ座標系から見た座標値に変換する必要がある。
この変換行列 T は、世界座標系におけるカメラ座標系の原点の姿勢及び位置がわかれば構築できる。
これらのパラメータを外部パラメータという。


T = \left( {\begin{array}{*{20}{c}}
{{r_{11}}}&{{r_{12}}}&{{r_{13}}}&{{t_1}}\\
{{r_{21}}}&{{r_{22}}}&{{r_{23}}}&{{t_2}}\\
{{r_{31}}}&{{r_{32}}}&{{r_{33}}}&{{t_3}}
\end{array}} \right)

射影変換

内部パラメータから成るカメラ行列及び外部パラメータから成るアフィン変換行列を合わせることで、世界座標系の点 (X_c, Y_c, Z_c)^T を画像座標系に写す射影変換行列が作成できる。


{Z_c}\left( {\begin{array}{*{20}{c}}
{U'}\\
{V'}\\
1
\end{array}} \right) = \left( {\begin{array}{*{20}{c}}
\alpha &s&{{{c'}_u}}\\
0&\beta &{{{c'}_v}}\\
0&0&1
\end{array}} \right)\left( {\begin{array}{*{20}{c}}
{{r_{11}}}&{{r_{12}}}&{{r_{13}}}&{{t_1}}\\
{{r_{21}}}&{{r_{22}}}&{{r_{23}}}&{{t_2}}\\
{{r_{31}}}&{{r_{32}}}&{{r_{33}}}&{{t_3}}
\end{array}} \right)\left( {\begin{array}{*{20}{c}}
{{X_c}}\\
{{Y_c}}\\
{{Z_c}}\\
1
\end{array}} \right)