【画像処理】道路標示を用いたカメラ焦点距離の推定

はじめに

 カメラの焦点距離を推定する方法として、2つの消失点を使用する方法がある。消失点は平行の関係にある複数の直線が画像上で交わる点である。実空間上では平行する直線が交わることはなく、画像上にある消失点は実空間上においては遥か彼方に存在している点ということになる。透視投影モデルにおいて、カメラ光学中心から画像上の消失点に対して張ったベクトルは、消失点を成す平行の関係にある実空間上の直線と平行の関係にある。つまり、透視投影モデルにおいて、カメラ光学中心から画像上の二つの消失点に対して張った2つのベクトルの成す角度は、各消失点を成す平行線の成す角度と同じになる。

算出方法

 消失点A,Bの内積の関係から、
A\cdot B=|A||B|cos(\theta)
 両辺を二乗し、絶対値を外し、左辺にまとめると
cos^{2}(\theta) \left(Ax^{2} + Ay^{2} + f^{2}\right) \left(Bx^{2} + By^{2} + f^{2}\right) - \left(Ax Bx + Ay By + f^{2}\right)^{2}=0
 これをf^{2}について解くと
f^{2}=\frac{- Ax^{2} cos^{2}(\theta) + 2 Ax Bx - Ay^{2} cos^{2}(\theta) + 2 Ay By - Bx^{2} cos^{2}(\theta) - By^{2} cos^{2}(\theta) \pm \sqrt{cos^{2}(\theta) \left(Ax^{4} cos^{2}(\theta) - 4 Ax^{3} Bx + 2 Ax^{2} Ay^{2} cos^{2}(\theta) - 4 Ax^{2} Ay By - 2 Ax^{2} Bx^{2} cos^{2}(\theta) + 8 Ax^{2} Bx^{2} - 2 Ax^{2} By^{2} cos^{2}(\theta) + 4 Ax^{2} By^{2} - 4 Ax Ay^{2} Bx + 8 Ax Ay Bx By - 4 Ax Bx^{3} - 4 Ax Bx By^{2} + Ay^{4} cos^{2}(\theta) - 4 Ay^{3} By - 2 Ay^{2} Bx^{2} cos^{2}(\theta) + 4 Ay^{2} Bx^{2} - 2 Ay^{2} By^{2} cos^{2}(\theta) + 8 Ay^{2} By^{2} - 4 Ay Bx^{2} By - 4 Ay By^{3} + Bx^{4} cos^{2}(\theta) + 2 Bx^{2} By^{2} cos^{2}(\theta) + By^{4} cos^{2}(\theta)\right)}}{2 \left(cos^{2}(\theta) - 1\right)}
 が得られる。焦点距離は常に正の実数なので、解候補は最大で2つ得られる。(クソ長数式自動で改行する方法知りたい)

消失点角度について

実装

  • 画像を読み込む。(場合によっては歪曲収差係数ファイルも読み込む。)
  • 平行線群を2グループ作成し、消失点を2つ計算する。
  • 平行線の角度を与える。(初期値90度)
  • 焦点距離を計算する。

github.com

実験

 シミュレーションによる検証と実機(ドラレコ)を用いた実験を行った。

シミュレーション検証

 シミュレーション環境は以下の記事で紹介したソフトを使用して、既知の焦点距離のカメラを模擬して生成した画像に対して焦点距離の推定を行った。被写体は路面標示の「横断歩道又は自転車横断帯あり」(以後ダイヤマーク)を模擬した菱形の頂点を散布図として描画した。
jonajiro.hatenablog.com

検証1 焦点距離:1047.7(FOV:85 deg.)
検証2 焦点距離:1047.7(FOV:85 deg.)
検証3 焦点距離:1506.9(FOV:65 deg.)
検証4 焦点距離:1506.9(FOV:65 deg.)

 検証1,2ではFOV85 deg.のカメラを使用した。双方で解は1候補のみ計算され(片方は虚数解)、最大9pixel以下の誤差があった。
 検証3,4ではFOV:65 deg.のカメラを使用し、双方で解は2候補計算されたが、片方候補が110と異常に小さく、FOVに換算すると167 deg.と異常に大きくなることから候補からは除外される。候補と考えられる解は、最大で4pixel以下の誤差があった。

実機(ドラレコ)実験

 ドラレコに対して焦点距離推定を行った。使用する画像は、自車走行路面に表示されたダイヤマークが最も大きく映ったフレームを使用した。

実機(ドラレコ)画像解析の様子

 推定の結果、1258.46と推定された。チェッカーボードを用いた手法で焦点距離を推定した結果はf_x=1263.96,f_y=1273.21であり、最大で15pixel以下のズレがあった。誤差率でいうと1.2%ではあるが、この推定焦点距離P3Pに適用したときの誤差伝播がどのようになるか気になる。というかチェッカーボードを用いた手法による推定結果の誤差がどんなもんかわからないので何とも言えないところではあり、これもカメラシミュレータで検証してみたいところではある。

【画像処理】カメラシミュレータの作成

 写真の歪曲収差係数や内部パラメータの推定方法を検討するときに実機を使用すると、その真値がわからないという問題がある。センササイズのカタログスペックやExifを参照する方法などあるが、これらの情報が正確である保証はないしどうしてもズレは生じてくる。
 そこでpyqtgraphの3D描画機能を使用して、既知の焦点距離のカメラをシミュレートして任意位置のプロットを描画し画像として出力するソフトを作成した。プロットしたい位置やカメラ画角(FOV)はソースコード中に入力して、カメラ位置・姿勢は実行後表示されるGUIでぐりぐりして調整する。キーボード「c」キー押下で「cap+焦点距離の数値.png」をファイル名として上書き保存される。

保存された画像「cap1506.8981540327907.png

github.com

【画像処理】歪曲収差を取り除いた画像を生成する

はじめに

jonajiro.hatenablog.com
 上記記事で歪曲収差の補正係数を算出したので、この補正係数に基づいて補正画像を生成する。

基本的な考え方

 補正された画像のRGB値は、その画素に対応する補正前の画像の画素位置のRGB値を参照すればよい。つまり、補正後画像の画素位置に対応する補正前画像の画素位置を計算する必要がある。しかし、この計算は代数的には求まらず、繰り返し計算が必要なことが知られており、以下の計算を繰り返すことで徐々に近づいていく。なお、添字aは補正後画像、bは補正前画像、iは繰り返し回数を表している。
  r_i = \sqrt{x_{a,i}^2+y_{a,i}^2}
  x_{a,i} = x_b \dfrac{ 1 + \kappa_3 r ^ 2 + \kappa_4 r ^ 4 }{1 + \kappa_1 r ^ 2 + \kappa_2 r ^ 4}
  y_{a,i} = y_b \dfrac{ 1 + \kappa_3 r ^ 2 + \kappa_4 r ^ 4 }{1 + \kappa_1 r ^ 2 + \kappa_2 r ^ 4}

ソースコート

github.com
 上記のソースコードで、歪曲収差を取り除きたい画像と補正係数のcsvファイルを選択すると、歪曲収差を取り除いた画像を生成できる。画像サイズが1920x1080だと5分くらいかかるので注意。

補正前
補正後