今回は、OpenCVに実装されているカメラキャリブレーションの概要についてご紹介します。カメラキャリブレーションは、レンズ焦点距離などの内部パラメータ、カメラの位置・姿勢を表す外部パラメータ、レンズの歪収差係数を求め、画像を補正する処理です(図1)。Zhangの手法が有名で、OpenCVに実装されていることもあり、世界で最も用いられています。ライブラリ化されているため誰でも簡単に利用することができますが、その反面キャリブレーションの処理について知らなくても実装できてしまいます。本記事では、そのOpenCVに実装されているZhangの手法の理解を深めていただければと思います。
内部パラメータ(Intrinsic parameters)、外部パラメータ(Extrinsic parameters)、歪収差係数(distortion coefficients)については、ここでは説明を割愛しますので、Wikipedia「Camera resectioning」「Distortion(optics)」などを参考にしてください。
カメラキャリブレーションの概要
まず、カメラキャリブレーション処理のフローを示します。
ステップ1:既知の平面パターン(OpenCVの場合、スクエアグリッド、サークルグリッド)を最低2方向から撮影します(図1)。
ステップ2:次に、撮影した画像から特徴点(直線の交点、または円の重心)を検出し、画像座標系での特徴点の座標を求めます。
ステップ3:ステップ2で検出した特徴点の座標を用いて、カメラの内部パラメータの初期値を求めます。この時点では、レンズの歪収差係数はゼロです。
ステップ4:バンドル調整と呼ばれている非線形最適化処理で、カメラの内部パラメータ、外部パラメータ、歪収差係数を求めます。
ステップ5:求めた内部パラメータ、歪収差係数を用いて、歪みのない画像に補正します。
ステップ2の処理は、cv::findChessboardCorners()とcv::cornerSubPix()、あるいはcv::findCirclesGrid()です。ステップ3、4は、cv::calibrateCamera()で、魚眼レンズの場合はcv::fisheye::calibrate()です。ステップ5は、cv::undistort()、あるいはcv::initUndistortRectifyMap()とcv::remap()の組み合わせで処理できます。魚眼レンズの場合は、cv::fisheye::undistortImage()、またはcv::fisheye::initUndistortRectifyMap()とcv::remap()です。コーディングについては、OpenCVのカメラキャリブレーションのサンプルコードが公開されているので、そちらを参考にしてください。
ステップ3で求める初期値は、かなり大雑把にしか求まりません。カメラの設計値がわかっている場合は、calibrateCamera( )のフラグCV_CALIB_USE_INTRINSIC_GUESSをセットして、内部パラメータの初期値に設計値を与えるとよいでしょう。外部パラメータも求めることができます。このキャリブレーションで求まる外部パラメータは、平面パターン上の3次元座標系とカメラ座標系間の外部パラメータです。
平面パターンの撮像例
異なる視点から撮像した画像が最低2枚必要と書きましたが、図2のとおり、正面、左斜め、右斜め、上斜め、下斜めから見た5枚があるとベターです。さらに異なる距離で各方向から撮像した5枚を加えた計10枚を用いるとさらによいと思います。似たような視点の映像ばかりが多数含まれないようにしましょう。
スクエアグリッドとサークルグリッドどっちを使うべき?
結論から言うとサークルグリッドを使った方がよいです。理由は単純で、ステップ2の特徴点の座標の算出精度がサークルグリッドの方が高いからです。楕円(円を含む)は、斜めから見ても楕円という特性があるため、重心を特徴点とすることで特徴点の座標を精度良く求めることができます。一方、スクエアグリッドの場合は、直線と直線の交点を特徴点とします。斜めから見ると正方形の形状が歪んでしまい、安定して座標を求めることができません。
スクエアグリッドとサークルグリッドの性能を比較した結果が図4です。各パラメータ、特徴点の座標の真値が既知の合成画像(図3)を用いて比較した結果です。
fx、fy、u0、v0が内部パラメータ、k1、k2、p1、p2が歪収差係数、RMSE(Root Mean Squared Error)はステップ4のバンドル調整時の誤差、一番右は特徴点の座標の算出誤差です(赤色の縦の点線は真値)。平面パターンを撮像する視点を変えてカメラキャリブレーションを15回試行した結果です。特徴点の座標の算出精度がサークルグリッドの方が高い(誤差が小さい)ため、すべてのパラメータを安定に制度良く求めることができます。
カメラキャリブレーションについて、理解は深まったでしょうか? OpenCVのカメラキャリブレーションを用いる場合は、サークルグリッドの平面パターンを利用しましょう! また、魚眼レンズの場合は、魚眼レンズ用の関数を用いるようにしましょう。
著者プロフィール
樋口未来(ひぐち・みらい)
日立製作所 日立研究所に入社後、自動車向けステレオカメラ、監視カメラの研究開発に従事。2011年から1年間、米国カーネギーメロン大学にて客員研究員としてカメラキャリブレーション技術の研究に携わる。
現在は、日立製作所を退職し、東京大学大学院博士課程に在学中。一人称視点映像(First-person vision, Egocentric vision)の解析に関する研究を行っている。具体的には、頭部に装着したカメラで撮影した一人称視点映像を用いて、人と人のインタラクション時の非言語コミュニケーション(うなずき等)を観測し、機械学習の枠組みでカメラ装着者がどのような人物かを推定する技術の研究に取り組んでいる。また、大学院での研究の傍ら、フリーランスとしてコンピュータビジョン技術の研究開発に従事している。
専門:コンピュータビジョン、機械学習