Я пытаюсь откалибровать и исправить набор стереокамер. Для каждой камеры у меня есть 50 кадров шахматной доски в разных местах вокруг рамки изображения, например:
Сначала я калибрую каждую камеру индивидуально, находя углы шахматной доски с помощью
def find_cb_corners(images, pattern_size=(9, 6), wait_time=500, show_img=False):
# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((np.prod(pattern_size), 3), np.float32)
objp[:, :2] = np.indices(pattern_size).T.reshape(-1, 2)
objpoints = []
imgpoints = []
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Implement findChessboardCorners here
ret, corners = cv2.findChessboardCorners(gray, patternSize=pattern_size)
# If found, add object points, image points (after refining them)
if ret is True:
objpoints.append(objp)
cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
imgpoints.append(corners)
if show_img is True:
# Draw and display the corners
img = cv2.drawChessboardCorners(img, pattern_size, corners, ret)
cv2.imshow("img", img)
cv2.waitKey(wait_time)
return objpoints, imgpoints
Найдя objpoints
и imgpoints
для левой и правой камеры, я калибрую каждую в отдельности с помощью
retval, mtx[0], dist[0], _, _ = cv2.calibrateCamera(
objpoints, imgpoints[0], frame_left.shape[::-1], None, None, criteria=criteria
)
. При этом возвращаются среднеквадратичные ошибки повторного проецирования 0,23 и 0,24. что, как я понимаю, приемлемо. После этого я передаю найденные матрицы камеры и коэффициенты искажения в stereoCalibrate
retval, mtx_new[0], dist_new[0], mtx_new[1], dist_new[1], R, T, E, F, = cv2.stereoCalibrate(
objpoints,
imgpoints[0],
imgpoints[1],
mtx[0],
dist[0],
mtx[1],
dist[1],
frame_left.shape[::-1],
criteria=criteria,
flags=cv2.CALIB_USE_INTRINSIC_GUESS + cv2.CALIB_FIX_PRINCIPAL_POINT,
)
, что возвращает среднеквадратичную ошибку повторного проецирования 78, что, очевидно, является проблематичным c. Кроме того, матрицы камер, найденные из cv2.stereoCalibrate
для левой камеры, не имеют смысла:
mtx[0] = [[1.20941916e+03 0.00000000e+00 6.21956811e+02]
[0.00000000e+00 6.53373036e+02 3.72723914e+02]
[0.00000000e+00 0.00000000e+00 1.00000000e+00]] # Left camera
mtx[1] = [[947.26614045 0. 647.57411009]
[ 0. 735.81086121 372.87329114]
[ 0. 0. 1. ]] # Right camera
Мне трудно понять, что калибровка работает нормально для каждой камеры отдельно, но при попытке при объединении камеры получается плохо, примерно то же самое происходит, если я пытаюсь вызвать cv2.getOptimalNewCameraMatrix
, то же самое происходит, то есть roi=[0, 0, 0, 0]
. Я читал в Интернете, что для камер с экстремальными радиальными искажениями процедуры калибровки opencv могут дать сбой, но я не уверен, что это так.
Есть ли что-то, что я неправильно понял?