2016-12-01 8 views
3

Ich habe die Disparitätskarte mit dem StereoSGBM-Algorithmus in OpenCV 3.1 berechnet. Ich habe eine Stereokamera mit kleinem RMS-Fehler kalibriert. Und jetzt möchte ich die reale Entfernung in mm für einige Punkte in der Disparitätskarte berechnen.OpenCV - Berechnung der realen Entfernung von der Disparitätskarte

Dies scheint relativ problematisch zu sein. Von dem, was ich verstehe, kann ich einfach Formel

distance = (baseline * focal length)/disparity 

verwenden, wo ich Matrix Q (Ausgabe von StereoRectify) verwenden kann. Q [2] [3] = Brennweite, 1/Q [3] [2] = Grundlinie.

Die berechnete Q-Matrix ist:

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. ] 

Das Problem ist, dass das Ergebnis nicht mit der Realität übereinstimmt. Zum Beispiel für die Kamera, die in der Ferne auf die Raumdecke zielt. 2,5 m (wobei die Disparität korrekt als 12 berechnet wird), wird die tatsächliche Entfernung als 1,3 m berechnet. Für sehr nahe Objekte (z.B. 30 cm) scheint es korrekt zu sein, aber entfernte Objekte sind sehr inkorrekt. Während der Kalibrierung habe ich die genaue Größe des Schachbrettquadrats in Millimetern angegeben.

ich genau folgendes:

// 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; 

Gibt es etwas, was ich falsch machen? Vielen Dank im Voraus.

Antwort

0

Ich weiß, dass die Stereo-Algorithmen für Disparität in OpenCV 2.4 (stereoBM, stereoSGBM) geben Sie die Disparität als Werte 16-mal größer als die tatsächlichen Werte, wie berichtet in the documentation. Ich bin nicht mit C++, openCv3 verwendet und ich finde nicht die Disparitätsmethode SGBM in Ihrem Code angegeben, aber ich denke, es könnte das gleiche sein. Versuchen Sie, jeden Disparitätswert durch 16 zu teilen (das gilt sicherlich auch für OpenCV 2.4, ich weiß 3.0 Version nicht)

+0

Dies ist bereits erledigt. Ich habe gerade vergessen zu spezifizieren float fDisparity = (outputDisparityValue)/(float) StereoMatcher :: DISP_SCALE; in meinem Beitrag. (DISP_SCALE = 16). Ich werde es hinzufügen. – bigmuscle

Verwandte Themen