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