Rotación de imágenes 3D en python.

Tengo la siguiente imagen I1. No lo capturé. Lo descargué de Google

introduzca la descripción de la imagen aquí

Aplico una homografía conocida h a I1 para obtener la siguiente imagen I2.

introduzca la descripción de la imagen aquí

Quiero asumir que una cámara ha tomado esta foto anterior de I2. He encontrado la matriz de la cámara de esta “cámara”. Deje que esta matriz de cámara sea k . Ahora, quiero rotar esta imagen I2 sobre el eje de la cámara. De acuerdo con la explicación en la respuesta aceptada en esta pregunta , debo configurar la matriz de rotación R y luego realizar k*R*inv(k)*h en la imagen I1 para obtener la imagen I3 girada requerida.

He estado enfrentando problemas cuando trato de configurar esta matriz de rotación R. He usado este método para configurar la matriz R.

Para probar mi código, inicialmente intenté girar la imagen alrededor del eje z en 10 grados pero no estaba obteniendo la salida correcta.

Mi código parcial de 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])) 

Aquí, img_src es la fuente de I1.

El resultado que obtuve cuando probé el código anterior es una imagen en negro sin ninguna parte de la imagen visible. Sin embargo, cuando cambié el valor de theta_in_degrees a los siguientes valores, estos fueron mis resultados:

0.00003

introduzca la descripción de la imagen aquí

0.00006

introduzca la descripción de la imagen aquí

0.00009

introduzca la descripción de la imagen aquí

¿Por qué la rotación funciona solo para valores tan pequeños de theta_in_degrees ? Además, la rotación visible en las imágenes no está sucediendo realmente alrededor del eje z. ¿Por qué la imagen no gira sobre el eje z? ¿A dónde me voy mal y cómo puedo solucionar estos problemas?

matriz de h

 [[ 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 matriz:

 [[ 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]] 

Editar:

Después de incorporar la sugerencia de Toby Collins, establecí que el valor superior izquierdo de k es el mismo que k[1][1] . Cuando ahora realizo la rotación sobre el eje z, obtengo las imágenes rotadas correctas para todos los valores de theta_in_degrees de 0 a 360. Sin embargo, cuando bash rotar la imagen sobre el eje y cambiando ux, uy y uz in El código anterior al siguiente, obtengo resultados de rotación absurdos:

 ux=0.0 uy=1.0 uz=0.0 

A continuación se muestran algunas muestras de diferentes valores de theta_in_degrees y los resultados correspondientes para la rotación alrededor del eje y:

-10

introduzca la descripción de la imagen aquí

-40

introduzca la descripción de la imagen aquí

-90

introduzca la descripción de la imagen aquí

-110

introduzca la descripción de la imagen aquí

¿Dónde me voy mal? Además, ¿por qué hay una caída tan grande en la longitud y el ancho de las sucesivas franjas amarillas en una imagen girada? ¿Y por qué una parte de la imagen se envuelve (por ejemplo, los resultados de la rotación en -90 y -110 grados)?

La segunda parte de mi pregunta es la siguiente: la ecuación vectorial de mi eje de rotación es (320, 0, -10)+t(0, 1, 0) . Para utilizar este método , para calcular la matriz de rotación, debo definir los ux , uy y uz del eje de rotación de manera que ux^2+uy^2+uz^2=1 . Esto sería sencillo si la rotación debe realizarse alrededor de uno de los ejes de coordenadas (como lo estoy haciendo actualmente con fines de prueba). Pero, ¿cómo obtengo estos valores de ux , uy y uz si la t en la ecuación vectorial de mi eje de rotación es variable? También estoy abierto a sugerencias con respecto a cualquier otro enfoque para encontrar una matriz de rotación R tal que la rotación ocurra alrededor del eje que he mencionado (por ejemplo, x grados).

La dificultad que tiene es que su matriz de homografía h no se corresponde bien con una proyección obtenida con una cámara de perspectiva sensible . Creo que hay un enfoque más simple.

Fundamentalmente, necesitaba tener muy claro su objective técnico y separarlo de su enfoque para resolverlo. Siempre haga esto cada vez que aborde cualquier problema de visión.

Objetivo técnico

Así que seamos claros sobre el objective técnico. Tiene una imagen de arriba abajo de una superficie plana (también llamada vista rectificada ). Normalmente llamaría a esta superficie el modelo , definido en el plano z = 0. Quieres renderizar este modelo. Específicamente quieres hacer lo siguiente;

  1. Se crea una cámara de perspectiva virtual que mira el modelo desde un punto de vista particular. Definimos esta transformación rígida de modelo a cámara por R 1, t 1, con una matriz intrínseca K.
  2. La cámara se mueve girándola sobre su centro de proyección. Denotemos esta rotación por R 2.
  3. El modelo se representa utilizando la vista desde 2. Llamaremos a esta imagen I2.

Para simplificar, voy a utilizar T ( R , t ) para denotar la transformada rígida homogénea 4×4 para cierta rotación R y traslación t . Por lo tanto , la transformación modelo a cámara en la etapa 3 viene dada por T = T ( R2 , (0,0,0)) x T ( R1 , t 1).

Opciones de renderizado

Hay dos buenas maneras de crear I2

  1. Utilice un motor de renderizado como OpenGL u Ogre. La ventaja de esto es que puede ser fácil hacer una GUI para cambiar el punto de vista de la cámara y se pueden agregar otros efectos de representación complejos.

  2. Determine la matriz de homografía de modelo a imagen y procese con OpenCV usando warpPerspective . La ventaja de esto es que se puede hacer en unas pocas líneas sin romper el software de renderizado. La desventaja es que puede obtener algunos efectos extraños si la homografía tiene un punto de fuga en el render (como está observando). Más sobre ese punto más adelante.

Definición de homografía modelo a imagen.

Para utilizar el enfoque OpenCV definimos la homografía modelo a imagen como H 2. Esto se puede definir en términos de los parámetros de la cámara. Considere un punto p = (x, y, 1) en el plano del modelo en coordenadas homogéneas. Su posición q en I2 en coordenadas homogéneas está dada por q = KM p , donde M es. Matriz 3×3 dada por M = (T00, T01, T03; T10, T11, T13; T20, T21, T23). Esto es fácil de obtener utilizando el modelo de cámara en perspectiva. En consecuencia, ahora tenemos que H 2 = KM .

Instanciar la matriz de homografía

Ahora tenemos que crear una instancia de la homografía, a diferencia de su enfoque propuesto, lo definiría utilizando una configuración de cámara particular, especificando K , R 1, t 1, R 2. ¡La elección es suya! Para simplificar la definición de K , puede utilizar un formulario simple con un parámetro libre (distancia focal) y establecer el punto principal en el centro de la imagen. Para las cámaras típicas, f varía entre 0,5 y 2 veces el ancho de la imagen, pero depende de usted. A continuación, debe configurar R 1 y t 1 según el ángulo de visión / distancia que desee para su punto de vista.

¿Cómo es esto diferente a su enfoque actual

Quiero enfatizar que esto no contradice ninguna de las respuestas anteriores que he dado. Es simplemente un enfoque diferente que puede ser más fácil de manejar. Esencialmente, aquí propongo que definas tu homografía directamente usando los parámetros de la cámara (que configuras como quieras). Esto garantiza que está utilizando una matriz intrínseca sensible (porque la configura usted mismo). Es diferente a su enfoque en el que primero crea una homografía y luego desea encontrar los parámetros de la cámara (que pueden o no ser físicamente sensibles).