2016-12-01 8 views
3

OpenCV 3.1でStereoSGBMアルゴリズムを使用して視差マップを計算しました。私は小さなRMSエラーでステレオカメラを較正しました。そして今、視差マップのいくつかの点について、実際の距離をmmで計算したいと思います。OpenCV - 視差マップから実距離を計算する

これは比較的簡単な問題のようです。私が理解していることから、私は単に式を使うことができます。

distance = (baseline * focal length)/disparity 

ここでは、行列Q(stereoRectifyからの出力)を使用できます。 Q [2] [3] =焦点距離、1/Q [3] [2] =ベースライン。

計算Q行列である:

Q: !!opencv-matrix 
    rows: 4 
    cols: 4 
    dt: d 
    data: [ 
    1., 0., 0., -1.5668458938598633e+02, 
    0., 1., 0., -1.1948609733581543e+02, 
    0., 0., 0., 2.3598119491957863e+02, 
    0., 0., 1.6254073321947445e-02, 0. ] 

問題は結果が現実に対応していないことです。たとえば、部屋の天井を望むカメラの場合、 (不均衡が12として正確に計算される)2,5メートルの場合、実際の距離は1,3mと計算されます。非常に近いオブジェクト(例えば、30cm)の場合、正しいと思われるが遠いオブジェクトは非常に間違っている。校正中に、チェス盤の正方形の大きさをミリメートルで指定しました。

私は正確に次のようにします。

// compute rectification transforms from calibration data 
stereoRectify(M1, D1, M2, D2, Size(FRAME_WIDTH, FRAME_HEIGHT), R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, 0.0, Size(FRAME_WIDTH, FRAME_HEIGHT), &roi1, &roi2); 

// compute the undistortion and rectification transformation maps for each camera 
initUndistortRectifyMap(M1, D1, R1, P1, Size(FRAME_WIDTH, FRAME_HEIGHT), CV_16SC2, map11, map12); 
initUndistortRectifyMap(M2, D2, R2, P2, Size(FRAME_WIDTH, FRAME_HEIGHT), CV_16SC2, map21, map22); 

... 

// get images from camera (VideoCapture) 
camLeft.read(_frameLeft); 
camRight.read(_frameRight); 

// remap images using the calibration data 
remap(_frameLeft, frameLeft, map11, map12, INTER_LINEAR); 
remap(_frameRight, frameRight, map21, map22, INTER_LINEAR); 

// compute disparity from undistorted images 
stereo->compute(frameLeft, frameRight, disparityMap); 

... 

// compute the real-world distance [mm] 
float fMaxDistance = static_cast<float>((1./Q.at<double>(3, 2)) * Q.at<double>(2, 3)); 

// outputDisparityValue is single 16-bit value from disparityMap 
// DISP_SCALE = 16 
float fDisparity = outputDisparityValue/(float)StereoMatcher::DISP_SCALE; 
float fDistance = fMaxDistance/fDisparity; 

は、私が間違って行うものがありますか? ありがとうございます。

答えて

0

OpenCV 2.4(stereoBM、stereoSGBM)の視差のステレオアルゴリズムは、報告されているように、実際の値の16倍の値であることを示しています。in the documentation私はC++、openCv3には使用されていませんが、あなたのコードで指定された視差メソッドSGBMが見つかりませんでしたが、同じことができると思います。すべての視差値を16で割ってみてください(これはOpenCV 2.4では確かですが、3.0バージョンは分かりません)

+0

これはすでに完了しています。 floatを指定するのを忘れてしまったfDisparity =(outputDisparityValue)/(float)StereoMatcher :: DISP_SCALE;私のポストで。 (DISP_SCALE = 16)。私はそれを追加します。 – bigmuscle