Вращение 3D-изображения в python

У меня есть следующее изображение I1. Я не захватил его. Я загрузил его из Google

введите описание изображения здесь

Я применяю известную гомографию h к I1, чтобы получить следующее изображение I2.

введите описание изображения здесь

Я хочу предположить, что камера сделала это над выстрелом I2. Я нашел матрицу камеры этой "камеры". Пусть эта матрица камеры k. Теперь я хочу повернуть это изображение I2 относительно оси камеры. Согласно объяснению в принятом ответе в этом вопросе, мне нужно установить матрицу поворота R, а затем выполнить k*R*inv(k)*h на изображении I1, чтобы получить требуемое повернутое изображение I3,

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

Чтобы проверить свой код, я сначала попытался повернуть изображение вокруг оси z на 10 градусов, но я не получил правильный вывод.

Мой частичный код Python:

theta_in_degrees = 10
theta_in_radians = theta_in_degrees*math.pi/180
ux=0.0 
uy=0.0 
uz=1.0 
vector_normalize_factor = math.sqrt(ux*ux+uy*uy+uz*uz)
ux=ux/vector_normalize_factor
uy=uy/vector_normalize_factor
uz=uz/vector_normalize_factor
print "ux*ux+uy*uy+uz*uz = ", ux*ux+uy*uy+uz*uz 
rotation_matrix = np.zeros([3,3])
c1 = math.cos(theta_in_radians)
c2 = 1-c1
s1 = math.sin(theta_in_radians)
rotation_matrix[0][0] = c1+ux*ux*c2
rotation_matrix[0][1] = ux*uy*c2-uz*s1
rotation_matrix[0][2] = ux*uz*c2+uy*s1
rotation_matrix[1][0] = uy*ux*c2+uz*s1
rotation_matrix[1][1] = c1+uy*uy*c2
rotation_matrix[1][2] = uy*uz*c2-ux*s1
rotation_matrix[2][0] = uz*ux*c2-uy*s1
rotation_matrix[2][1] = uz*uy*c2+ux*s1
rotation_matrix[2][2] = c1+uz*uz*c2
print "rotation_matrix = ", rotation_matrix
R = rotation_matrix
#Calculate homography H1 between reference top view and rotated frame
k_inv = np.linalg.inv(k)
Hi = k.dot(R)
Hii = k_inv.dot(h)
H1 = Hi.dot(Hii)
print "H1 = ", H1
im_out = cv2.warpPerspective(im_src, H1, (im_dst.shape[1],im_dst.shape[0]))

Здесь img_src является источником I1.

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

0,00003

введите описание изображения здесь

0.00006

введите описание изображения здесь

0,00009

введите описание изображения здесь

Почему вращение работает только для таких малых значений theta_in_degrees? Кроме того, вращение, видимое на изображениях, фактически не происходит вокруг оси z. Почему изображение не вращается вокруг оси z? Где я ошибаюсь и как я могу исправить эти проблемы?

h matrix:

[[  1.71025842e+00  -7.51761942e-01   1.02803446e+02]
 [ -2.98552735e-16   1.39232576e-01   1.62792482e+02]
 [ -1.13518150e-18  -2.27094753e-03   1.00000000e+00]]

k matrix:

[[  1.41009391e+09   0.00000000e+00   5.14000000e+02]
 [  0.00000000e+00   1.78412347e+02   1.17000000e+02]
 [  0.00000000e+00   0.00000000e+00   1.00000000e+00]]

Edit:

После включения предложения Тоби Коллинза я установил верхнее левое значение k таким же, как k[1][1]. Когда я теперь выполняю вращение вокруг оси z, я получаю правильные повернутые изображения для всех значений theta_in_degrees от 0 до 360. Однако, когда я пытаюсь повернуть изображение вокруг оси y, изменив ux, uy и uz в приведенном выше коде к следующему, я получаю абсурдные результаты вращения:

ux=0.0 
uy=1.0 
uz=0.0 

Ниже приведены примеры для разных значений theta_in_degrees и соответствующие результаты для вращения вокруг оси y:

-10

введите описание изображения здесь

-40

введите описание изображения здесь

-90

введите описание изображения здесь

-110

введите описание изображения здесь

Где я все еще ошибаюсь? Кроме того, почему существует такое огромное падение длины и ширины последовательных желтых полос во вращающемся изображении? И почему часть изображения обтекает (например, результаты вращения на -90 и -110 градусов)?

Вторая часть моего вопроса такова: векторное уравнение моей оси вращения (320, 0, -10)+t(0, 1, 0). Чтобы использовать этот метод, чтобы вычислить матрицу вращения, мне нужно определить ux, uy и uz ось поворота такая, что ux^2+uy^2+uz^2=1. Это было бы просто, если поворот необходимо сделать вокруг одной из осей координат (как я сейчас делаю для целей тестирования). Но как мне получить эти значения ux, uy и uz, если переменная t в векторном уравнении моей оси вращения является переменной? Я также открыт для предложений относительно любых других подходов к поиску подходящей матрицы поворота R, так что вращение происходит вокруг упомянутой оси (например, x градусов).

Ответ 1

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

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

Техническая цель

Итак, давайте проясним техническую цель. У вас есть изображение сверху вниз плоской поверхности (также называемое выпрямленным видом). Обычно вы назовете эту поверхность моделью, определенной на плоскости z = 0. Вы хотите отобразить эту модель. В частности, вы хотите сделать следующее:

  • Создается виртуальная перспективная камера, которая смотрит на модель с определенной точки зрения. Мы определяем жесткое преобразование модели с камерой с помощью R 1, t 1 с внутренней матрицей K.
  • Камера перемещается, поворачивая ее по центру ее проекции. Обозначим это вращение на R 2.
  • Модель визуализируется с использованием представления из 2. Мы будем называть это изображение I2

Для простоты я буду использовать T (R, t) для обозначения однородного жесткого преобразования 4x4 для некоторого вращения R и перевод t. Следовательно, преобразование модели к камере на этапе 3 задается T= T ( R2, (0,0,0)) x T ( R1, t 1).

Параметры рендеринга

Есть два хороших способа создания I2

  • Использовать механизм рендеринга, например OpenGL или Ogre. Преимущество этого заключается в том, что может быть легко сделать графический интерфейс для изменения точки обзора камеры, и могут быть добавлены другие сложные эффекты рендеринга.

  • Определите матрицу гомографии модели для изображения и выполните рендеринг с помощью OpenCV с помощью warpPerspective. Преимущество этого в том, что это можно сделать в нескольких строках, не врываясь в программное обеспечение для рендеринга. Недостатком является то, что вы можете получить некоторые странные эффекты, если у гомографии есть точка схода в рендеринг (как вы наблюдаете). Подробнее об этом позже.

Определение гомографии модели для изображения

Чтобы использовать подход OpenCV, мы определяем гомографию модели для изображения как H 2. Это можно определить с точки зрения параметров камеры. Рассмотрим точку p= (x, y, 1) на плоскости модели в однородных координатах. Его положение q в I2 в однородных координатах дается выражением q= K M p, где M. Матрица 3x3, заданная M= (T00, T01, T03; T10, T11, T13; T20, T21, T23). Это можно получить с помощью перспективной модели камеры. Следовательно, теперь мы имеем H 2 = K M.

Произвести создание матрицы гомографии

Теперь нам нужно создать экземпляр гомографии, в отличие от вашего предлагаемого подхода, я бы определил его с использованием конкретной конфигурации камеры, указав K, R 1, t 1, R 2. Выбор остается за вами! Чтобы упростить определение K, вы можете использовать простую форму с одним свободным параметром (фокусное расстояние) и установить главную точку в центр изображения. Для типичных камер f колеблется между 0,5 и 2 раза шириной изображения, но это зависит от вас. Затем вам нужно установить R 1 и t 1 в зависимости от угла обзора/расстояния, которое вы хотите для своей точки обзора.

Как это отличается от вашего текущего подхода

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