Convertir la matriz de perspectiva findHomography de OpenCV en iOS 'CATransform3D

Me gustaría tomar la matriz de transformación de perspectiva devuelta por la function findHomography de OpenCV y convertirla (ya sea en C ++ o Objective-C) en iOS ' CATransform3D '. Me gustaría que estuvieran lo más cerca posible en términos de reproducir con precisión el efecto "warp" en el lado de Core Graphics. ¡El código de ejemplo realmente sería apreciado!

Desde iOS 'CATransform3D.h:

 /* Homogeneous three-dimensional transforms. */ struct CATransform3D { CGFloat m11, m12, m13, m14; CGFloat m21, m22, m23, m24; CGFloat m31, m32, m33, m34; CGFloat m41, m42, m43, m44; }; 

Preguntas similares:

Aplicar la matriz de homografía usando Core Graphics

convertir una matriz afín opencv a CGAffineTransform

Renuncia

Nunca he probado esto, así que tómalo con un poco de sal.

CATRansform3D es una matriz 4×4 que opera en un vector homogéneo tridimensional (4×1) para producir otro vector del mismo tipo. Estoy suponiendo que cuando se renderizan, los objects descritos por un vector 4×1 tienen cada elemento dividido por el cuarto elemento y el tercero se usa solo para determinar qué objects aparecen en la parte superior. Suponiendo que esto sea correcto …

Razonamiento

La matriz 3×3 devuelta por findHomography funciona en un vector homogéneo de 2 dimensiones. Ese process se puede pensar en 4 pasos

  1. La primera columna de la homografía se multiplica por x
  2. La segunda columna de la homografía se multiplica por y
  3. La tercera columna de la homografía se multiplica por 1
  4. los elementos vectoriales primero y segundo resultantes están divididos por el tercero

Necesita este process para replicarse en un vector 4×4 en el que estoy asumiendo que el tercer elemento en el vector resultante no tiene sentido para sus propósitos.

Solución

Construya su matriz de esta manera (H es su matriz de homografía)

 [H(0,0), H(0,1), 0, H(0,2), H(1,0), H(1,1), 0, H(1,2), 0, 0, 1, 0 H(2,0), H(2,1), 0, H(2,2)] 

Esto satisface claramente 1,2 y 3. 4 se satisface porque el elemento homogéneo es siempre el último. Es por eso que la "fila homogénea" si tuviera que pasar por una línea. El 1 en la 3ª fila es dejar que el componente z del vector pase sin ser molestado.

Todo lo anterior se realiza en notación principal en fila (como openCV) para tratar de evitar que las cosas sean confusas. Puede ver la respuesta de Tommy para ver cómo se ve la conversión a la columna principal (básicamente, simplemente transposition). Tenga en count, sin embargo, que por el momento Tommy y yo estamos en desacuerdo sobre cómo build la matriz.

De mi lectura de la documentation, m11 en CATransform3D es equivalente a a en CGAffineTransform , m12 es equivalente a b y así sucesivamente.

Según su comentario a continuación, entiendo que la matriz OpenCV vuelve a ser 3×3 (que, en retrospectiva, es del tamaño que cabría esperar). Entonces completaría los otros elementos con los equivalentes a la matriz de identidad. De acuerdo con la respuesta de Hammer, desea conservar la parte que trata con la coorderada homogénea (generalmente implícita) en su lugar mientras rellena todo lo demás con la identidad.

[aparte: mi respuesta original fue incorrecta . Lo he editado para ser correcto, ya que he publicado el código y Hammer no. Esta publicación está marcada como wiki de la comunidad para reflejar que no es en absoluto solo mi respuesta]

Entonces creo que querrías:

 CATransform3D MatToTransform(Mat cvTransform) { CATransform3D transform; transform.m11 = cvTransform.at<float>(0, 0); transform.m12 = cvTransform.at<float>(1, 0); transform.m13 = 0.0f; transform.m14 = cvTransform.at<float>(2, 0); transform.m21 = cvTransform.at<float>(0, 1); transform.m22 = cvTransform.at<float>(1, 1); transform.m23 = 0.0f; transform.m24 = cvTransform.at<float>(2, 1); transform.m31 = 0.0f; transform.m32 = 0.0f; transform.m33 = 1.0f; transform.m34 = 0.0f; transform.m41 = cvTransform.at<float>(0, 2); transform.m42 = cvTransform.at<float>(1, 2); transform.m43 = 0.0f; transform.m44 = cvTransform.at<float>(2, 2); return transform; } 

O use cvGetReal1D si mantiene fuera de C ++.