Определение трехмерных локаций из двух изображений с использованием единиц opencv - traingulatePoints - PullRequest
1 голос
/ 24 октября 2019

Учитывая набор соответствующих точек для двух произвольных (т. Е. Не параллельных) изображений (например, найденных SURF), я использовал следующее, чтобы извлечь 3D-точки точек.

def triangulate(pts1,pts2):
    cameraMatrix = np.array([[1, 0,0],[0,1,0],[0,0,1]])        
    F,m1 = cv2.findFundamentalMat(pts1, pts2) # apparently not necessary

    # using the essential matrix can get you the rotation/translation bet. cameras, although there are two possible rotations: 
    E,m2 = cv2.findEssentialMat(pts1, pts2, cameraMatrix, cv2.RANSAC, 0.999, 1.0)
    Re1, Re2, t_E = cv2.decomposeEssentialMat(E)

    # recoverPose gets you an unambiguous R and t. One of the R's above does agree with the R determined here. RecoverPose can already triangulate, I check by hand below to compare results. 
    K_l = cameraMatrix
    K_r = cameraMatrix
    retval, R, t, mask2, triangulatedPoints = cv2.recoverPose(E,pts_l_norm, pts_r_norm, cameraMatrix,distanceThresh=0.5)

    # given R,t you can  explicitly find 3d locations using projection 
    M_r = np.concatenate((R,t),axis=1)
    M_l = np.concatenate((np.eye(3,3),np.zeros((3,1))),axis=1)
    proj_r = np.dot(cameraMatrix,M_r)
    proj_l = np.dot(cameraMatrix,M_l)
    points_4d_hom = cv2.triangulatePoints(proj_l, proj_r, np.expand_dims(pts1, axis=1), np.expand_dims(pts2, axis=1))
    points_4d = points_4d_hom / np.tile(point_s4d_hom[-1, :], (4, 1))
    points_3d = points_4d[:3, :].T
    return points_3d

Я предположил, что матрицы моей внутренней камеры примерно равны I в приведенном выше. R, t, как определено двумя методами (findEssentialMat-> декомпозировать, EssentialMat vs recoveryPose), согласуются, и точки триангуляции, определенные двумя методами (recoverPose vs triangulatePoints), также согласуются. Мой вопрос касается значений, которые я вижу, которые для points_3d обычно находятся в диапазоне 0-50 для x, y и 0-0.03 для z. Насколько я знаю, эти значения должны быть в пикселях;мой выбор матрицы камеры = я повлиял на масштаб?

Ответы [ 2 ]

1 голос
/ 04 ноября 2019

Да, выбор матрицы камеры напрямую влияет на масштаб. Матрица камеры в OpenCV должна содержать значения для fx и fy, которые относятся к фокусному расстоянию камеры (главному расстоянию), выраженному в пиксельных единицах - см. Модель камеры OpenCV .
Если установить оба значения на 1вы получите «меньшие значения» в пикселях для ваших 3D-точек. Обычно (явно зависит от камеры) значения fx, fy составляют, например, около 1000. Здесь вы можете найти хороший пример для оценки фокусного расстояния веб-камеры, используя только разрешение и приблизительное полепросмотр (FOV).

0 голосов
/ 25 октября 2019

Вы должны использовать откалиброванную камеру. Вы можете найти учебник по калибровке камеры в OpenCV, он дает вам код и объясняет, как калибровать вашу камеру.

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

Обычно вычисленный перевод камеры представляет собой единичный вектор, поэтому ваши 3D-точки будут использовать это смещение в качестве единицы измерения масштаба. Допустим, ваши два изображения были сделаны камерой на расстоянии 1 метра, 3D-точки будут в метрах. 3D масштаб никогда не в пикселях.

Заключительные комментарии:

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

2- Если вы не откалибруете свою камеру, вы можете приблизить матрицу камеры (ухудшить результаты, но лучше, чем ничего), предполагая: - cx и cy находятся в серединеimage - fx = fy = половинное горизонтальное разрешение (например, 1920/2 px) в предположении, что у вашей камеры апертура 90 градусов. В противном случае вы должны нарисовать равнобедренный треугольник и выполнить некоторую геометрию.

...