[C con Clase] [Windows API] Transformación Afín

Steven Davidson srd4121 en njit.edu
Vie Abr 13 04:23:36 CEST 2012


Hola Lourdes,

On 4/12/2012 7:37 PM, Lourdes Celene Haros Becerra wrote:
> Qué tal, buen día!!
>
> Revisé las pagina que me sugeriste
> http://graficos.conclase.net/curso/index.php?cap=006c#Transformaciones_Afines
> y sí me sirvió mucho, pero sigo con dudas para implementar que la
> imagen fuente gire con respecto a imagen destino... encontré aqui
> http://es.scribd.com/doc/63650237/54/Coordenadas-homogeneas-y-representacion-matricial
> en la pagina 99 información al respecto, pero nosé cómo
> implementarla, no sé si podrían ayudarme. Porq ahi habla de hacer la
> rotación respecto a un punto de pivote cualquiera, creo que es lo que
> necesito. Mi pregunta es ¿El vector por el que tengo que multiplicar
> cambia? ¿Cómo sería?... porq la ecuación de rotación con pivote en el
> origen es x'=xcos(theta) -ysin(theta) y'=xsin(theta)+ycos(theta)
>

Bueno, en primer lugar, ten cuidado con los términos que usas. Dudo que 
estés usando vectores, sino más bien parejas ordenadas para representar 
puntos o como dices posteriormente píxeles de una imagen.

En una imagen, guardamos las intensidades en cada píxel; y un píxel 
requiere una pareja ordenada para referirnos a un píxel. Analíticamente, 
podemos representar una imagen como una función de intensidades: f(x,y). 
Esto significa que por cada pareja de coordenadas (x,y) podemos conocer 
la intensidad, f, en tal píxel.

Las fórmulas explicadas tanto en el capítulo 6 de nuestro curso de 
programación como en el libro del enlace sirven para puntos, que 
seguramente describen vértices de un polígono, de un modelo analítico de 
una figura en dos dimensiones. Por ejemplo, los vértices de un 
rectángulo, de un triángulo, o de cualquier otro tipo de polígono en 
general, al igual que un segmento, o incluso coordenadas para describir 
curvas.

En tu caso, necesitas una variación de estas fórmulas para que funcionen 
con píxeles de una imagen. Como todas las coordenadas en una imagen (de 
píxeles) son válidas, tenemos que aplicar cualquier transformación a 
TODOS los píxeles y por tanto tenemos que recorrer TODAS las 
coordenadas. El algoritmo entonces podría ser el siguiente:

Imagen Rotar_Imagen( Imagen f, Dimensión M, Dimensión N, Ángulo a )

1.  Crear Imagen: g de M x N
2.  Inicializar 0 intensidad a todos los píxeles de "g"  // 0 => Negro
3.  Para: x = 0 hasta M-1
4.     Para: y = 0 hasta N-1
5.        u <- x * cos(a) - y * sen(a)
6.        v <- x * cos(a) + y * sen(a)
7.        g(u,v) <- f(x,y)
8.  Terminar( g )

(Nota: uso <- para indicar "copiar" o "asignar"). Podemos asignar otro 
valor incialmente a todos los píxeles de la imagen resultante, pero creo 
que 0 tiene más sentido. También date cuenta que estamos creando una 
nueva imagen en este algoritmo y además la rotación es alrededor del 
origen (0,0). Si quieres otro "centro" para la rotación, entonces aplica 
una traslación en la rotación.

El problema de implementar este algoritmo es que los cálculos de las 
coordenadas de (u,v) pueden resultar en las mismas más de una vez y por 
tanto estaríamos copiando diferentes intensidades al mismo píxel. 
También puede darse el caso de que no todos los píxeles de la imagen 
resultante son asignados, excepto por el valor inicial.

Una solución alternativa es aplicar la transformación inversa. Esto 
significa que analizamos cada píxel de la imagen resultante usando sus 
coordenadas en la transformación inversa para generar las coordenadas de 
la imagen original y así consultar sus intensidades. Como se trata de 
una rotación, su inversa es una rotación del ángulo negativo. El 
algoritmo ahora sería,

Imagen Rotar_Imagen( Imagen f, Dimensión M, Dimensión N, Ángulo a )

1.  Crear Imagen: g de M x N
2.  Para: u = 0 hasta M-1
3.     Para: v = 0 hasta N-1
4.        x <- u * cos(a) + u * sen(a)
5.        y <- v * cos(a) - v * sen(a)
6.        g(u,v) <- f(x,y)
7.  Terminar( g )

El paso #6 no es tan directo, porque tenemos que comprobar que las 
coordenadas calculadas para (x,y) realmente existen; si no, entonces hay 
que asignar algún valor como por ejemplo 0 (negro).

Como posiblemente obtendremos una imagen rotada con algunos píxeles 
negros (intesidad cero), podemos aplicar una mejor solución para 
aproximar la intensidad de esos píxeles sin intensidad, como es una 
interpolación lineal de los píxeles cercanos o vecinos, interpolación 
bilineal, o interpolación bicúbica.


Espero que todo esto te sirva.

Steven





Más información sobre la lista de distribución Cconclase