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?
Во-вторых, есть ли у кого-нибудь какие-либо предложения для меня, чтобы получить полезное исправление двух видов сцены?
Цель состоит в том, чтобы триангулировать трехмерные мировые позиции объектов из наблюдений парных объектов в видах камеры. Исправление является обязательным условием. Любая помощь приветствуется! Я сделаю все возможное, чтобы уточнить все, что неясно.