Ho messo insieme un impianto di riproduzione stereo e sto avendo problemi ad usarlo per produrre una buona mappa di disparità. Ecco un esempio di due immagini raddrizzate e la mappa disparità ho prodotto con loro:Mappa di disparità errata utilizzando StereoBM in OpenCV
Come si può vedere, i risultati sono piuttosto male. Cambiare le impostazioni di StereoBM non cambia molto.
Il setup
- Entrambe le fotocamere sono dello stesso modello e connettono al computer con USB.
- Sono fissati a una tavola di legno rigida in modo che non si muovano. Li ho allineati al meglio, ma ovviamente non è perfetto. Non sono in grado di muoversi, quindi le loro posizioni durante e dopo la calibrazione sono le stesse.
- Ho calibrato la coppia stereo utilizzando OpenCV e sto usando la classe
StereoBM
di OpenCV per produrre la mappa di disparità. - Probabilmente non è rilevante, ma sto codificando in Python.
Problemi potevo immaginare
sto facendo questo per la prima volta, quindi sono ben lungi dall'essere un esperto, ma sto cercando di indovinare il problema è nella calibrazione o nel rettifica stereo, piuttosto che il calcolo della mappa di disparità. Ho provato tutte le permutazioni delle impostazioni per lo StereoBM
e, anche se ottengo risultati diversi, sono tutte come la mappa delle disparità mostrata sopra: Patch in bianco e nero.
Questa idea è ulteriormente supportata dal fatto che, a quanto ho capito, la rettifica stereo dovrebbe allineare tutti i punti su ciascuna immagine in modo che siano collegati da una linea diritta (nel mio caso orizzontale). Se esamino entrambe le immagini rettificate l'una accanto all'altra, è ovvio che non è così. I punti corrispondenti sono molto più alti nell'immagine a destra che a sinistra. Non sono sicuro se la calibrazione o la rettifica sia il problema, però.
Il codice
Il codice attuale è avvolto in oggetti - nel caso in cui siete interessati a vedere nella sua interezza, è disponibile on GitHub. Ecco un esempio semplificato di ciò che è effettivamente eseguito (ovviamente nel codice vero e proprio ho calibrazione utilizzando più di appena 2 foto):
import cv2
import numpy as np
## Load test images
# TEST_IMAGES is a list of paths to test images
input_l, input_r = [cv2.imread(image, cv2.CV_LOAD_IMAGE_GRAYSCALE)
for image in TEST_IMAGES]
image_size = input_l.shape[:2]
## Retrieve chessboard corners
# CHESSBOARD_ROWS and CHESSBOARD_COLUMNS are the number of inside rows and
# columns in the chessboard used for calibration
pattern_size = CHESSBOARD_ROWS, CHESSBOARD_COLUMNS
object_points = np.zeros((np.prod(pattern_size), 3), np.float32)
object_points[:, :2] = np.indices(pattern_size).T.reshape(-1, 2)
# SQUARE_SIZE is the size of the chessboard squares in cm
object_points *= SQUARE_SIZE
image_points = {}
ret, corners_l = cv2.findChessboardCorners(input_l, pattern_size, True)
cv2.cornerSubPix(input_l, corners_l,
(11, 11), (-1, -1),
(cv2.TERM_CRITERIA_MAX_ITER + cv2.TERM_CRITERIA_EPS,
30, 0.01))
image_points["left"] = corners_l.reshape(-1, 2)
ret, corners_r = cv2.findChessboardCorners(input_r, pattern_size, True)
cv2.cornerSubPix(input_r, corners_r,
(11, 11), (-1, -1),
(cv2.TERM_CRITERIA_MAX_ITER + cv2.TERM_CRITERIA_EPS,
30, 0.01))
image_points["right"] = corners_r.reshape(-1, 2)
## Calibrate cameras
(cam_mats, dist_coefs, rect_trans, proj_mats, valid_boxes,
undistortion_maps, rectification_maps) = {}, {}, {}, {}, {}, {}, {}
criteria = (cv2.TERM_CRITERIA_MAX_ITER + cv2.TERM_CRITERIA_EPS,
100, 1e-5)
flags = (cv2.CALIB_FIX_ASPECT_RATIO + cv2.CALIB_ZERO_TANGENT_DIST +
cv2.CALIB_SAME_FOCAL_LENGTH)
(ret, cam_mats["left"], dist_coefs["left"], cam_mats["right"],
dist_coefs["right"], rot_mat, trans_vec, e_mat,
f_mat) = cv2.stereoCalibrate(object_points,
image_points["left"], image_points["right"],
image_size, criteria=criteria, flags=flags)
(rect_trans["left"], rect_trans["right"],
proj_mats["left"], proj_mats["right"],
disp_to_depth_mat, valid_boxes["left"],
valid_boxes["right"]) = cv2.stereoRectify(cam_mats["left"],
dist_coefs["left"],
cam_mats["right"],
dist_coefs["right"],
image_size,
rot_mat, trans_vec, flags=0)
for side in ("left", "right"):
(undistortion_maps[side],
rectification_maps[side]) = cv2.initUndistortRectifyMap(cam_mats[side],
dist_coefs[side],
rect_trans[side],
proj_mats[side],
image_size,
cv2.CV_32FC1)
## Produce disparity map
rectified_l = cv2.remap(input_l, undistortion_maps["left"],
rectification_maps["left"],
cv2.INTER_NEAREST)
rectified_r = cv2.remap(input_r, undistortion_maps["right"],
rectification_maps["right"],
cv2.INTER_NEAREST)
cv2.imshow("left", rectified_l)
cv2.imshow("right", rectified_r)
block_matcher = cv2.StereoBM(cv2.STEREO_BM_BASIC_PRESET, 0, 5)
disp = block_matcher.compute(rectified_l, rectified_r, disptype=cv2.CV_32F)
cv2.imshow("disparity", disp)
cosa sta andando male qui?