2009-03-29 20 views
7

Consulte también: Why is my image rotation algorithm not working?¿Cómo giro una imagen?

Esta pregunta no es un lenguaje específico, y es un problema de matemáticas. Sin embargo, usaré algún código C++ para explicar lo que necesito ya que no soy demasiado aficionado a las matemáticas.

Así es como se compone la imagen:

ImageMatrix image; 
image[0][0][0] = 1; 
image[0][1][0] = 2; 
image[0][2][0] = 1; 
image[1][0][0] = 0; 
image[1][1][0] = 0; 
image[1][2][0] = 0; 
image[2][0][0] = -1; 
image[2][1][0] = -2; 
image[2][2][0] = -1; 

Aquí está el prototipo de la función que estoy tratando de crear:

ImageMatrix rotateImage(ImageMatrix image, double angle); 

me gustaría girar sólo los dos primeros índices (filas y columnas) pero no el canal.

+0

rotación por cuánto? un ángulo arbitrario o múltiplo de 90 grados? – shoosh

+0

@shoosh: como sugiere el prototipo (doble ángulo) esto debe estar utilizando un tipo doble de cualquier valor. –

Respuesta

26

La forma habitual de resolver esto es hacerlo al revés. En lugar de calcular dónde termina cada píxel en la imagen de entrada en la imagen de salida, se calcula dónde se encuentra cada píxel en la imagen de salida en la imagen de entrada (rotando la misma cantidad en la otra dirección. De esta forma puede estar Asegúrese de que todos los píxeles de la imagen de salida tendrán un valor.

output = new Image(input.size()) 

for each pixel in input: 
{ 
    p2 = rotate(pixel, -angle); 
    value = interpolate(input, p2) 
    output(pixel) = value 
} 

Hay diferentes maneras de hacer la interpolación. para la fórmula de rotación Creo que usted debe comprobar https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions

Pero sólo para ser agradable, aquí es (rotación del punto (x, y) ángulo grados/radianes):

newX = cos(angle)*x - sin(angle)*y 
newY = sin(angle)*x + cos(angle)*y 
+0

Gracias kigurai. Traté de implementar esto pero no he tenido mucha suerte, ¿quizás podrías echar un vistazo? http://stackoverflow.com/questions/697520/why-is-my-image-rotation-algorithm-not-working –

2

Nota: hay otra solución aparte de las matrices de rotación, que no pierde información de la imagen mediante el aliasing. Puede separar la rotación de imágenes 2D en skews and scalings, que conserva la calidad de la imagen.

Here's a simpler explanation

+0

Interesante, pero no entiendo la mayoría de los términos matemáticos como "frecuencia Nyquist" o "espectro de la imagen". ¿Puede indicarme materiales para leer para obtener información de antecedentes? ¿Esto es algo que podría explorar por mi cuenta o necesitaría una verdadera educación matemática? (Soy un estudiante de secundaria de matemáticas del último año). –

+0

@Iraimbilanja: la teoría del procesamiento de señales es algo del EE de segundo o tercer año. Saber cómo hacer cálculos integrales primero ayuda. –

+0

Siempre hay wikipedia: http://en.wikipedia.org/wiki/Nyquist_frequency Piense en la frecuencia como el espectrograma de una imagen: es equivalente a la salida de un analizador gráfico de un reproductor de audio, solo en 2D. Muestra qué frecuencia es más visible en la imagen y en qué dirección. – heeen

0

Parece que el ejemplo que nos ha facilitado es un poco de kernel de detección de bordes. Entonces, si lo que quiere es detectar bordes de diferentes ángulos, será mejor que elija alguna función continua (que en su caso podría ser un gaussiano parametrizado de x1 multiplicado por x2) y luego rotarlo de acuerdo con las fórmulas proporcionadas por kigurai. Como resultado, sería capaz de producir un kernel de disco de manera más eficiente y sin aliasing.

2

Para girar una imagen, se crea 3 puntos:

A----B 
| 
| 
C 

y girar en torno de que A. Para obtener la nueva imagen rotada hacer esto:

  • giran en torno ABC A en 2D, por lo que esta es una sola rotación euler
  • transversal en el estado girado de A a B. Por cada píxel, también se recorre de izquierda a derecha sobre la línea horizontal en la imagen original. Entonces, si la imagen es una imagen de ancho 100, altura 50, atravesará de A a B en 100 pasos y de A a C en 50 pasos, dibujando 50 líneas de 100 píxeles en el área formada por ABC en su estado girado .

Esto puede sonar complicado pero no lo es.Por favor, vea el código C# que escribí hace algún tiempo: rotoZoomer by me

Cuando dibujo, altero los punteros de código un poco para conseguir un efecto parecido a la goma, pero si se deshabilita que, verá el código de la imagen girará sin problemas. Por supuesto, en algunos ángulos obtendrá una imagen que se ve ligeramente distorsionada. El código fuente contiene comentarios sobre lo que está sucediendo, por lo que debería poder tomar fácilmente la matemática/lógica que está detrás.

Si como Java mejor, también he hecho una versión de Java una vez, hace 14 años más o menos;) -> http://www.xs4all.nl/~perseus/zoom/zoom.java

Cuestiones relacionadas