takminの書きっぱなし備忘録 @はてなブログ

主にコンピュータビジョンなど技術について、たまに自分自身のことや思いついたことなど

OpenCVで魚眼カメラのキャリブレーション

はまったのでメモ


OpenCV魚眼カメラのキャリブレーションは、calib3dモジュールのcv::calibrateCamera()とは微妙に使い方が違うので、下手するとドハマリします。


通常のカメラキャリブレーションの方法は、calibration.cppというサンプルコードが用意されているので、そちらを参考にして下さい。



魚眼カメラのキャリブレーションの流れは、チェッカーパターンを印刷して、カメラで様々な位置、角度から撮影し、cv::findChessboardCorners()でコーナー検出を行い、更にcv::cornerSubPix()でサブピクセル精度まで補正するというところまでは通常の方法と一緒です。

詳しくはカメラキャリブレーションチュートリアルページを参照して下さい。
http://docs.opencv.org/doc/tutorials/calib3d/camera_calibration/camera_calibration.html


ここから、魚眼カメラ用のキャリブレーション関数cv::fisheye::calibrate()を使ってカメラパラメータを取得します。関数の説明は以下のページにあります。
http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#fisheye-calibrate


が、これだけでは実際どうパラメータ指定して良いかわからないためサンプルコードを探したのですが、OpenCVをインストールしただけではどこにも見つからなかったので色々調べました。

	std::vector> object_points;
	/***************
	object_pointsにチェスボードのコーナー座標(三次元)を各画像ごとに入れる。
	通常は世界座標系の原点をチェスボード上のどこかに固定してZ軸をボードの法線方向にするため、どの画像にも同一のコーナー座標群が入る。
	****************/

	std::vector> image_points;
	/***************
	findChessboardCorners()で検出した画像上のコーナー座標(サブピクセル精度)を入れる。
	コーナーの並び順はobject_pointsと対応している必要
	****************/

	cv::Size img_size;
	/***************
	チェスボードを撮影した画像のサイズ
	****************/

	cv::Mat camera_matrix;
	cv::Mat distortion;
	double rms_err = calibrate(object_points, image_points, img_size, camera_matrix, distortion,
		cv::noArray(), cv::noArray(), CALIB_RECOMPUTE_EXTRINSIC | CALIB_CHECK_COND | CALIB_FIX_SKEW);
	


これにより、カメラの焦点や光軸座標等を格納したカメラ行列camera_matrixと歪み係数を格納したdistortionを得ることができます。
もし各画像撮影時におけるチェスボードに対するカメラの相対位置が知りたい場合は、第6引数と第7引数にそれぞれ回転行列、並進ベクトルを格納するためのstd::vector型のインスタンスを入れてあげて下さい。


最後の引数のフラグは必ず指定して下さい。このうち1つでもないとうまくキャリブレーションしてくれません(私はCALIB_RECOMPUTE_EXTRINSICを指定しなかったためはまりました)。


これを実行してカメラパラメータとレンズ歪を取得すると、cv::fisheye::undistortImage()により魚眼カメラの画像の歪みを取ることができます。


入力画像:


cv::fisheye::calibrate()で補正


cv::calibrateCamera()で補正