OpenCV стерео выпрямление не удается, но я думаю, что стереокалибровка успешна

У меня есть такой набор калибровочных изображений, из которого я получил точки изображения (угловые положения шахматной доски) на левых изображениях, 'imp1', точки изображения на правых изображениях, 'imp2' и точки объекта в рамке мира, 'objp ". Позиции шахматной доски в серии изображений охватывают не менее 80% сцены. Они взяты тщательно, с одновременными снимками с высококачественных научных камер. Единственное осложнение состоит в том, что они находятся под водой, поэтому есть колебания освещения и, возможно, небольшие вибрации.

Сначала я выполнил калибровку камеры с помощью cv2.calibrateCamera отдельно для каждого вида. Я получаю ошибки перепроектирования около 0,3 пикселей. Видимо, очень мало искажений. Удаление изображений с помощью cv2.undistort приводит к изображениям, на которых прямые линии выглядят прямыми. Конечно, прямые линии на исходных изображениях выглядят прямыми. Код калибровки камеры

flags = cv2.CALIB_FIX_PRINCIPAL_POINT | cv2.CALIB_FIX_K3 | cv2.CALIB_ZERO_TANGENT_DIST

cam1 = cv2.calibrateCamera(objp,imp1,shape,None,None,flags=flags)
cam2 = cv2.calibrateCamera(objp,imp2,shape,None,None,flags=flags)

# store the output 
keys = ['retval','cameraMatrix','distCoeffs','rvecs','tvecs']
Lcam = {k:v for k,v in zip(keys,cam1)}
Rcam = {k:v for k,v in zip(keys,cam2)}

Во-вторых, я выполнил стереокалибровку с использованием cv2.stereoCalibrate следующим образом

# do the stereo calibration
flags =  cv2.CALIB_USE_INTRINSIC_GUESS | cv2.CALIB_FIX_FOCAL_LENGTH | cv2.CALIB_FIX_PRINCIPAL_POINT | cv2.CALIB_FIX_INTRINSIC | cv2.CALIB_FIX_K1 | cv2.CALIB_FIX_K2 | cv2.CALIB_FIX_K3 
stereocalib = cv2.stereoCalibrate(objp,imp1,imp2,Lcam['cameraMatrix'],Lcam['distCoeffs'],Rcam['cameraMatrix'],Rcam['distCoeffs'],shape,flags=flags)

#store the output
keys = ['retval', 'cameraMatrix1', 'distCoeffs1', 'cameraMatrix2', 'distCoeffs2', 'R', 'T', 'E', 'F']
stereo = {k:v for k,v in zip(keys,stereocalib)}

При этом получается ошибка перепроецирования 0,8, и когда я вычисляю отклонения от эпиполярного ограничения x'Fx для всех парных точек x и x', я нахожу, что они всегда меньше 1 пикселя и обычно больше похожи на 0,2 пикселя.

На следующем рисунке три угловые точки шахматной доски указаны на левом изображении, а соответствующие эпилины - на правом изображении.

Эти два теста, вычисление остаточного эпиполярного ограничения и соответствующая визуализация эпилина, дают мне уверенность в результате калибровки стерео.

Мой первый вопрос появляется здесь: я не знаю, как проверить матрицы вращения и перевода. Полученная матрица перевода (то есть стерео ['T'])

array([[-94.35664281],
   [  1.45841307],
   [  6.63416548]])

Полученный вектор вращения (то есть стерео ['R'])

array([[ 8.42562933e-01,  1.53811356e-02,  5.38378236e-01],
   [-1.31180579e-02,  9.99881661e-01, -8.03622020e-03],
   [-5.38438131e-01, -2.91455620e-04,  8.42664995e-01]])

что не так далеко от личности. На мой взгляд, это небольшое вращение вокруг оси y, что имеет смысл, так как камеры слегка изогнуты друг к другу.

Единицы здесь в сантиметрах. Точки крепления камеры, несколько выше и позади объективов, были разнесены на ~100 см, так что это кажется довольно разумным. Один корпус камеры был длиннее другого, и, возможно, примерно на 6 см. Одно крепление было немного ниже другого, и, вероятно, примерно на 2 см. Я смущен отрицательным знаком на координате х. Как проверить матрицы вращения и перевода?

В-третьих, и теперь, перейдя ко второй проблеме, я пытаюсь сгенерировать матрицы проекций для стереофонического выпрямления из cv2.stereoRectify следующим образом:

alpha = 1
rect = cv2.stereoRectify(stereo['cameraMatrix1'],stereo['distCoeffs1'],stereo['cameraMatrix2'],stereo['distCoeffs2'],shape,stereo['R'],stereo['T'],alpha,flags=cv2.CALIB_ZERO_DISPARITY)

# store the rectification parameters
keys = ['R1','R2','P1','P2','Q','validPixROI1','validPixROI2'] 
rectify = {k:v for k,v in zip(keys,rect)}

Затем я вычисляю карты репроекции для исправления как

lmaps = cv2.initUndistortRectifyMap(stereo["cameraMatrix1"], stereo["distCoeffs1"], rectify['R1'], rectify['P1'], shape, cv2.CV_16SC2)
rmaps = cv2.initUndistortRectifyMap(stereo["cameraMatrix2"], stereo["distCoeffs2"], rectify['R2'], rectify['P2'], shape, cv2.CV_16SC2)

и я переназначаю каждое изображение "л" в левом представлении как

interpolate = cv2.INTER_LANCZOS4 
lr = cv2.remap(l, lmaps[0], lmaps[1], interpolate)

и каждое изображение 'r' в правильном виде как

 rr = cv2.remap(r, rmaps[0], rmaps[1], interpolate)

Результат:

from matplotlib import pyplot as plt
plt.imshow(np.hstack((lr,rr)))
plt.show()

Это верно для всех значений альфа. Карты репроекции имеют отрицательные значения и значения, которые не лежат на изображении, поэтому выпрямление дает бессмыслицу.

У меня есть два вопроса:

Во-первых, как мне проверить матрицу вращения и вектор перевода, выходящие из cv2.stereoCalibrate?

Во-вторых, есть ли у кого-нибудь какие-либо предложения для меня, чтобы получить полезное исправление двух видов сцены?

Цель состоит в том, чтобы триангулировать трехмерные мировые позиции объектов из наблюдений парных объектов в видах камеры. Исправление является обязательным условием. Любая помощь приветствуется! Я сделаю все возможное, чтобы уточнить все, что неясно.

0 ответов

Другие вопросы по тегам