Подтвердить что ты не робот

OpenCV: получить перспективную матрицу от перевода и вращения

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

По сути, я хочу сделать описанный процесс здесь (см., в частности, изображения к концу), но начиная с известной модели камеры и позиционирования.

Есть ли прямой вызов функции, который принимает внутренние и внешние параметры камеры и вычисляет перспективную матрицу для использования в warpPerspective?

Я вызываю warpPerspective после вызова undistort на изображении.

В принципе, я мог бы найти решение, решая систему уравнений, определенную в верхней части документации по калибровке камеры opencv после указания ограничения Z=0, но Я полагаю, что должна быть законченная программа, которая позволит мне ортотрансформировать мои тестовые изображения.

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

4b9b3361

Ответ 1

На самом деле нет необходимости привлекать орфографическую камеру. Вот как вы можете получить соответствующее преобразование перспективы.

Если вы откалибровали камеру с помощью cv::calibrateCamera, вы получили матрицу камеры K вектор коэффициентов искажения объектива D для вашей камеры и для каждого используемого изображения вектор вращения rvec (который вы можете преобразовать в матрицу 3x3 R с помощью cv::rodrigues, doc) и вектора перевода T. Рассмотрим одно из этих изображений и связанные с ним R и T. После того, как вы вызвали cv::undistort с использованием коэффициентов искажения, изображение будет похоже на то, что оно было получено камерой матрицы проецирования K * [ R | T ].

В принципе (как @DavidNilosek интуитивно) вы хотите отменить поворот и получить изображение, как если бы оно было получено матрицей проекции формы K * [ I | -C ], где C=-R.inv()*T - позиция камеры. Для этого вам необходимо применить следующее преобразование:

Hr = K * R.inv() * K.inv()

Единственная потенциальная проблема заключается в том, что искаженное изображение может выйти за пределы видимой части плоскости изображения. Следовательно, вы можете использовать дополнительный перевод для решения этой проблемы следующим образом:

     [ 1  0  |         ]
Ht = [ 0  1  | -K*C/Cz ]
     [ 0  0  |         ]

где Cz - компонента C вдоль оси Oz.

Наконец, с приведенными выше определениями, H = Ht * Hr является выпрямляющим преобразованием перспективы для рассматриваемого изображения.

Ответ 2

Это набросок того, что я подразумеваю под "решением системы уравнений" (на Python):

import cv2
import scipy  # I use scipy by habit; numpy would be fine too
#rvec= the rotation vector
#tvec = the translation *emphasized text*matrix
#A = the camera intrinsic

def unit_vector(v):
    return v/scipy.sqrt(scipy.sum(v*v))

(fx,fy)=(A[0,0], A[1,1])
Ainv=scipy.array( [ [1.0/fx, 0.0, -A[0,2]/fx],
                     [ 0.0,  1.0/fy, -A[1,2]/fy],
                     [ 0.0,    0.0,     1.0] ], dtype=scipy.float32 )
R=cv2.Rodrigues( rvec )
Rinv=scipy.transpose( R )

u=scipy.dot( Rinv, tvec ) # displacement between camera and world coordinate origin, in world coordinates


# corners of the image, for here hard coded
pixel_corners=[ scipy.array( c, dtype=scipy.float32 ) for c in [ (0+0.5,0+0.5,1), (0+0.5,640-0.5,1), (480-0.5,640-0.5,1), (480-0.5,0+0.5,1)] ]
scene_corners=[]
for c in pixel_corners:
    lhat=scipy.dot( Rinv, scipy.dot( Ainv, c) ) #direction of the ray that the corner images, in world coordinates
    s=u[2]/lhat[2]
    # now we have the case that (s*lhat-u)[2]==0,
    # i.e. s is how far along the line of sight that we need
    # to move to get to the Z==0 plane.
    g=s*lhat-u
    scene_corners.append( (g[0], g[1]) )

# now we have: 4 pixel_corners (image coordinates), and 4 corresponding scene_coordinates
# can call cv2.getPerspectiveTransform on them and so on..