OpenCVでステレオ画像処理(その3)
いろいろ順序が前後していますが、キャリブレーションボードを使ったいわゆる普通のステレオキャリブレーションをOpenCVでやる方法を確認します。OpenCV3.0以降ではcv::Matが標準として扱われるようになり、cvMatやIplImageは使われなくなっていく流れのようですので、OpenCVのc++版exampleのstereo_calibを参考にすることにします。
ソースコードの場所は、
C:\opencv248\sources\samples\cpp\stereo_calib.cpp
です。OpenCVのプロジェクトのビルドには一晩ぐらい時間がかかってしまいますので、新しいプロジェクトを作って、ソースコードをコピーしてきて自分でビルドした方がてっとり早いです。
同じフォルダにある
・left01.jpg~left14.jpg、
・right01.jpg~right14.jpg、
・stereo_calib.xml
もコピーして持ってきます。
入力は、左右同時に撮影したキャリブレーションボードの画像です。xmlファイルに対応するペアの画像リストが記されています。出力は、内部パラメータintrinsics.ymlと外部パラメータextrinsics.ymlです。キャリブデータの例を見てみましょう。
intrinsics.yml
%YAML:1.0
M1: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 5.3471330014109185e+002, 0., 3.3513862534045768e+002, 0.,
5.3471330014109185e+002, 2.4020611211645166e+002, 0., 0., 1. ]
D1: !!opencv-matrix
rows: 1
cols: 8
dt: d
data: [ -2.7456948643916240e-001, -1.8313659599039273e-002, 0., 0.,
0., 0., 0., -2.4476896026105649e-001 ]
M2: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 5.3471330014109185e+002, 0., 3.3401539789706163e+002, 0.,
5.3471330014109185e+002, 2.4159046721727415e+002, 0., 0., 1. ]
D2: !!opencv-matrix
rows: 1
cols: 8
dt: d
data: [ -2.8073637368771431e-001, 9.3010333965398026e-002, 0., 0., 0.,
0., 0., 1.6329629641388992e-002 ]
M1: 1台目のカメラ行列 [fx, 0, cx,
0, fy, cy,
0, 0, 1]
fx, fyは焦点距離、cx,cyは画像中心
D1: 1台目のレンズ歪み
k1 , k2 , k3 , k4 , k5 , k6 は半径方向の歪み係数, p1 , p2 は円周方向の歪み係数
M2: 2台目のカメラ行列
D2: 2台目のレンズ歪み
extrinsics.yml
%YAML:1.0
R: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 9.9975845099223370e-001, 5.2938875802891888e-003,
-2.1331067106374762e-002, -4.9129099555727165e-003,
9.9982819095220643e-001, 1.7873217197994926e-002,
2.1422021038591057e-002, -1.7764102328165273e-002,
9.9961269183774204e-001 ]
T: !!opencv-matrix
rows: 3
cols: 1
dt: d
data: [ -3.3385294685465094e+000, 4.8752222149133176e-002,
-1.0621612775973460e-001 ]
R1: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 9.9989926261613005e-001, -9.8656327048122546e-003,
1.0204602444634284e-002, 9.7747186679340847e-003,
9.9991243188225976e-001, 8.9209552329390027e-003,
-1.0291719714510178e-002, -8.8203094412328143e-003,
9.9990813710394366e-001 ]
R2: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 9.9938783533139086e-001, -1.4593963665815494e-002,
3.1795767267948229e-002, 1.4875488104129789e-002,
9.9985206173729635e-001, -8.6356524560469196e-003,
-3.1665035059203130e-002, 9.1033435724789738e-003,
9.9945707996416788e-001 ]
P1: !!opencv-matrix
rows: 3
cols: 4
dt: d
data: [ 4.2656306659615905e+002, 0., 3.2185713195800781e+002, 0., 0.,
4.2656306659615905e+002, 2.4122907447814941e+002, 0., 0., 0., 1.,
0. ]
P2: !!opencv-matrix
rows: 3
cols: 4
dt: d
data: [ 4.2656306659615905e+002, 0., 3.2185713195800781e+002,
-1.4249656816691422e+003, 0., 4.2656306659615905e+002,
2.4122907447814941e+002, 0., 0., 0., 1., 0. ]
Q: !!opencv-matrix
rows: 4
cols: 4
dt: d
data: [ 1., 0., 0., -3.2185713195800781e+002, 0., 1., 0.,
-2.4122907447814941e+002, 0., 0., 0., 4.2656306659615905e+002, 0.,
0., 2.9934971212534872e-001, 0. ]
R: 1番目と2番目のカメラ座標系間の回転行列
T: 出力される,それぞれのカメラ座標系間の並進ベクトル
R2 (R1) : 1番目と2番目のカメラに対する の平行化変換(回転行列).
P2 (P1) : 新しい(平行化された)座標系における の射影行列.
Q: の視差-デプス間のマッピング行列. reprojectImageTo3D() を参照
opencvのstereo_calib.cppのフローチャートを書き起こしてみます。通常8枚以上、セッティングを変更してないステレオカメラで撮影した左右ペアのキャリブボードが写った画像を入力とします。内部パラメータ、外部パラメータと求めていって、校正マップを作ります。
普段のステレオ画像処理に必要なのは、赤線以下の部分で、校正マップと新しい入力画像を関数remapに渡すと、校正された画像を出力してくれます。それを、stereo_matchに渡してやれば良いわけです。
[1]http://opencv.jp/opencv-2svn/cpp/camera_calibration_and_3d_reconstruction.html