what graphics image-processing

graphics - what - introduction to digital image processing



Transformación proyectiva (6)

Creo que lo que buscas es una homografía planar, eche un vistazo a estas notas de clase:

http://www.cs.utoronto.ca/~strider/vis-notes/tutHomography04.pdf

Si te desplazas hacia abajo hasta el final, verás un ejemplo de lo que estás describiendo. Supongo que hay una función en la biblioteca Intel OpenCV que hará exactamente esto.

Dado dos búferes de imagen (suponiendo que es una matriz de entradas de ancho de ancho * alto, con cada elemento un valor de color), ¿cómo puedo mapear un área definida por un cuadrilátero de un búfer de imagen en el otro búfer de imagen (siempre cuadrado)? Me hacen entender que esto se llama "transformación proyectiva".

También estoy buscando una forma general (no específica del idioma o de la biblioteca) de hacer esto, de modo que pueda aplicarse razonablemente en cualquier idioma sin depender de la "función mágica X que hace todo el trabajo por mí".

Un ejemplo: escribí un programa corto en Java usando la biblioteca Processing (processing.org) que captura videos de una cámara. Durante un paso inicial de "calibración", el video capturado se envía directamente a una ventana. Luego, el usuario hace clic en cuatro puntos para definir un área del video que se transformará, luego se mapeará en la ventana cuadrada durante el funcionamiento posterior del programa. Si el usuario hiciera clic en los cuatro puntos que definen las esquinas de una puerta visible en un ángulo en la salida de la cámara, esta transformación haría que el siguiente video mapeara la imagen transformada de la puerta en toda el área de la ventana, aunque algo distorsionado.


Así es como lo haría en principio:

  • mapear el origen de A con el origen de B a través de un vector de traslación t .
  • tomar vectores unitarios de A (1,0) y (0,1) y calcular cómo se mapearían en los vectores unitarios de B.
  • esto le da una matriz de transformación M para que cada vector a en A se corresponda con M a + t
  • invierte la matriz y niega el vector de traslación, por lo que para cada vector b en B tienes el mapeo inverso b -> M -1 ( b - t )
  • una vez que tenga esta transformación, para cada punto en el área objetivo en B, encuentre el correspondiente en A y copie.

La ventaja de este mapeo es que solo se calculan los puntos que se necesitan, es decir, se recorren los puntos objetivo , no los puntos fuente . Fue una técnica ampliamente utilizada en la escena de "codificación demo" hace unos años.


Existe un proyecto de C ++ en CodeProject que incluye fuente para transformaciones proyectivas de bitmaps. Las matemáticas están en Wikipedia aquí . Tenga en cuenta que, por lo que sé, una transformación proyectiva no asignará ningún cuadrilátero arbitrario a otro, pero sí lo hará para triángulos, también puede buscar transformaciones sesgadas.


Si esta transformación tiene que verse bien (a diferencia de la apariencia de un mapa de bits si se cambia el tamaño en Paint), no se puede simplemente crear una fórmula que asigne píxeles de destino a los píxeles de origen. Los valores en el búfer de destino deben basarse en un promedio complejo de píxeles de origen cercanos o los resultados estarán altamente pixelados.

Así que, a menos que desee entrar en una codificación compleja, use la función mágica de otra persona , como sugirieron Smacl e Ian.


EDITAR

La suposición debajo de la invarianza de las relaciones de ángulo es incorrecta. En cambio, las transformaciones proyectivas preservan las relaciones cruzadas y la incidencia. Una solución entonces es:

  1. Encuentre el punto C ''en la intersección de las líneas definidas por los segmentos AD y CP.
  2. Encuentre el punto B ''en la intersección de las líneas definidas por los segmentos AD y BP.
  3. Determine la relación cruzada de B''DAC '', es decir, r = (BA'' * DC '') / (DA * B''C'').
  4. Construye la línea proyectada F''HEG ''. La relación cruzada de estos puntos es igual a r, es decir, r = (F''E * HG '') / (HE * F''G'').
  5. F''F y G''G se intersectarán en el punto proyectado Q, por lo que se equipararán las relaciones cruzadas y, conociendo la longitud del lado del cuadrado, se puede determinar la posición de Q con cierta gimnasia aritmética.

Hmmmm ... Haré una puñalada en esto. Esta solución se basa en la suposición de que las proporciones de ángulos se conservan en la transformación. Consulte la imagen para obtener orientación (lo siento por la mala calidad de la imagen ... es REALMENTE tarde). El algoritmo solo proporciona la asignación de un punto en el cuadrilátero a un punto en el cuadrado. Aún necesitaría implementar el tratamiento de múltiples puntos cuádruples que se asignan al mismo punto cuadrado.

Deje que ABCD sea un cuadrilátero donde A es el vértice superior izquierdo, B es el vértice superior derecho, C es el vértice inferior derecho y D es el vértice inferior izquierdo. El par (xA, yA) representa las coordenadas xey del vértice A. Estamos mapeando puntos en este cuadrilátero con el cuadrado EFGH cuyo lado tiene una longitud igual a m.

texto alternativo http://img355.imageshack.us/img355/3991/geomyr1.gif

Calcule las longitudes AD, CD, AC, BD y BC:

AD = sqrt((xA-xD)^2 + (yA-yD)^2) CD = sqrt((xC-xD)^2 + (yC-yD)^2) AC = sqrt((xA-xC)^2 + (yA-yC)^2) BD = sqrt((xB-xD)^2 + (yB-yD)^2) BC = sqrt((xB-xC)^2 + (yB-yC)^2)

Deje que thetaD sea el ángulo en el vértice D y thetaC el ángulo en el vértice C. Calcule estos ángulos usando la ley del coseno:

thetaD = arccos((AD^2 + CD^2 - AC^2) / (2*AD*CD)) thetaC = arccos((BC^2 + CD^2 - BD^2) / (2*BC*CD))

Asignamos cada punto P en el cuadrilátero a un punto Q en el cuadrado. Para cada punto P en el cuadrilátero, haga lo siguiente:

  • Encuentra la distancia DP:

    DP = sqrt((xP-xD)^2 + (yP-yD)^2)

  • Encuentra la distancia CP:

    CP = sqrt((xP-xC)^2 + (yP-yC)^2)

  • Encuentre el ángulo thetaP1 entre CD y DP:

    thetaP1 = arccos((DP^2 + CD^2 - CP^2) / (2*DP*CD))

  • Encuentre el ángulo thetaP2 entre CD y CP:

    thetaP2 = arccos((CP^2 + CD^2 - DP^2) / (2*CP*CD))

  • La relación de thetaP1 a thetaD debe ser la relación de thetaQ1 a 90. Por lo tanto, calcule thetaQ1:

    thetaQ1 = thetaP1 * 90 / thetaD

  • Del mismo modo, calcule thetaQ2:

    thetaQ2 = thetaP2 * 90 / thetaC

  • Encuentra la distancia HQ:

    HQ = m * sin(thetaQ2) / sin(180-thetaQ1-thetaQ2)

  • Finalmente, la posición xey de Q con respecto a la esquina inferior izquierda de EFGH es:

    x = HQ * cos(thetaQ1) y = HQ * sin(thetaQ1)

Debería hacer un seguimiento de cuántos valores de color se asignan a cada punto en el cuadrado para que pueda calcular un color promedio para cada uno de esos puntos.


¡Usar álgebra lineal es mucho más fácil que toda esa geometría! Además, no necesitarás usar seno, coseno, etc., para que puedas almacenar cada número como una fracción racional y obtener el resultado numérico exacto si lo necesitas.

Lo que quiere es un mapeo de sus coordenadas antiguas (x, y) a sus coordenadas nuevas (x '', y''). Puedes hacerlo con matrices. Necesita encontrar la matriz de proyección P 2 por 4 P de manera que P por las coordenadas antiguas sea igual a las nuevas coordenadas. Asumiremos que está mapeando líneas a líneas (no, por ejemplo, líneas rectas a parábolas). Como tiene una proyección (las líneas paralelas no permanecen paralelas) y la traducción (deslizamiento), también necesita un factor de (xy) y (1). Dibujado como matrices:

[x ] [a b c d]*[y ] = [x''] [e f g h] [x*y] [y''] [1 ]

Necesitas saber a través de h para resolver estas ecuaciones:

a*x_0 + b*y_0 + c*x_0*y_0 + d = i_0 a*x_1 + b*y_1 + c*x_1*y_1 + d = i_1 a*x_2 + b*y_2 + c*x_2*y_2 + d = i_2 a*x_3 + b*y_3 + c*x_3*y_3 + d = i_3 e*x_0 + f*y_0 + g*x_0*y_0 + h = j_0 e*x_1 + f*y_1 + g*x_1*y_1 + h = j_1 e*x_2 + f*y_2 + g*x_2*y_2 + h = j_2 e*x_3 + f*y_3 + g*x_3*y_3 + h = j_3

De nuevo, puedes usar álgebra lineal:

[x_0 y_0 x_0*y_0 1] [a e] [i_0 j_0] [x_1 y_1 x_1*y_1 1] * [b f] = [i_1 j_1] [x_2 y_2 x_2*y_2 1] [c g] [i_2 j_2] [x_3 y_3 x_3*y_3 1] [d h] [i_3 j_3]

Conecta tus esquinas para x_n, y_n, i_n, j_n. (Las esquinas funcionan mejor porque están muy separadas para disminuir el error si se seleccionan los puntos de, digamos, clics del usuario). Tome la inversa de la matriz 4x4 y multiplíquela por el lado derecho de la ecuación. La transposición de esa matriz es P. Debes poder encontrar funciones para calcular una matriz inversa y multiplicar en línea.

Donde probablemente tengas errores:

  • Al calcular, recuerde verificar la división por cero. Esa es una señal de que su matriz no es invertible. Eso podría suceder si tratas de asignar una coordenada (x, y) a dos puntos diferentes.
  • Si escribe su propia matriz matemática, recuerde que las matrices generalmente se especifican como fila, columna (vertical, horizontal) y los gráficos de pantalla son x, y (horizontal, vertical). Seguramente te saldrá algo mal la primera vez.