2011-06-15 17 views
8

quisiera rotar una imagen que no es cuadrado, con Matlab:Rotación de una imagen sin la caja de herramientas de procesamiento de imágenes

  • sin utilizar la función imrotate, ya que es parte de la Imagen Processing Toolbox,
  • con el parámetro loose, lo que significa que el tamaño de la salida difiere del tamaño de la imagen de entrada,
  • y con una función no demasiado lenta en comparación con imrotate.

que ya han encontrado a function con el fin de hacer esto (basta con sustituir imshow y bestblk con sus propias funciones con el fin de no utilizar la caja de herramientas), sin embargo, es muy lento para grandes imágenes. Mi enfoque trataría de evitar hacer bucles y confiar tanto como sea posible en interp2.


La firma de la función sería:

imOutput = my_imrotate(imInput, theta_degres, interpolation, bbox)

donde:

  • interpolation sería bilinear, bicubic o nearest,
  • bbox habría crop, o loose.

cultivos

ya tengo un buen resultado con el parámetro crop, pero no consigo encontrar el desplazamiento para el parámetro loose.

Este es el código para el parámetro crop, donde Z es la entrada y Zi es la salida:

Z = double(imInput); 
sz = size(Z); 
[X,Y] = meshgrid(1:sz(2), 1:sz(1)); 
%# Center 
c = sz(end:-1:1)/2; 
%# Angle 
t = theta_degres*pi/180; 
%# Rotation 
ct = cos(t); 
st = sin(t); 
Xi = c(1) + ct*(X-c(1))-st*(Y-c(2)); 
Yi = c(2) + st*(X-c(1))+ct*(Y-c(2)); 
%# Rotation 
Zi = interp2(X, Y, Z, Xi, Yi); 

suelta

Mi idea es calcular el tamaño de una marco que contendría la imagen original así como la imagen girada, y luego:

  1. almohadilla de la imagen original con el fin de tener una imagen cuyo tamaño es el tamaño de la trama,
  2. uso interp2 en la imagen acolchado,
  3. cosecha la imagen resultante de modo que tenga la imagen girada sin los restos del relleno.

para obtener el tamaño de la imagen rotada con el parámetro loose, puedo calcular la rotation_matrix y llamo rotate_points de las coordenadas de las esquinas p de la imagen de entrada:

rotation_matrix = [ct, -st; st, ct]; 
rotate_points = @(p) bsxfun(@plus, c', rotation_matrix * bsxfun(@minus, p, c)')'; 

Cualquier ayuda sería muy apreciado.


Editar: El uso de la solución suministrada en la respuesta a continuación, y el siguiente código, que parece funcionar del todo bien:

%# See the answer below 
[sz1,sz2] = size(Z); 
sz1New = sz1*cos(t)+sz2*sin(t); 
sz2New = sz2*cos(t)+sz1*sin(t); 
[Xi,Yi] = meshgrid(-(sz2New-1)/2:(sz2New-1)/2,-(sz1New-1)/2:(sz1New-1)/2); 
%# now all that's left is rotating Xi,Yi - I have already subtracted the center 

%# My little piece of additional code 
Xii = (1+sz2)/2 + ct*Xi - st*Yi; 
Yii = (1+sz1)/2 + st*Xi + ct*Yi; 
Zi = interp2(X, Y, Z, Xii, Yii); 
+0

Es sorprendente esta pregunta tiene 3k puntos de vista, y sin embargo sólo 4 upvotes, y la respuesta sólo 2 upvotes, aunque la pregunta es clara y respondió correctamente. – Wok

Respuesta

4

Para la versión loose, todo lo que tiene que hacer es averiguar la cantidad de relleno que necesitas Puede estimarlo fácilmente con un poco de geometría:

Si dibuja el rectángulo "suelto", básicamente está agregando cuatro triángulos en ángulo recto al rectángulo original. La hipotenusa de los triángulos son los lados del rectángulo. Si puede determinar los otros dos lados, puede calcular fácilmente la longitud de los nuevos lados y, por lo tanto, el relleno. Afortunadamente, uno de los ángulos del triángulo rectángulo es exactamente el ángulo de rotación.

Como resultado, ni siquiera necesita calcular el relleno explícitamente; simplemente crea una matriz más grande Xi, Yi que tiene el tamaño de la imagen 'suelta'.

Por lo tanto:

[sz1,sz2] = size(Z); 
sz1New = sz1*cos(t)+sz2*sin(t); 
sz2New = sz2*cos(t)+sz1*sin(t); 
[Xi,Yi] = meshgrid(-(sz2New-1)/2:(sz2New-1)/2,-(sz1New-1)/2:(sz1New-1)/2); 
%# now all that's left is rotating Xi,Yi - I have already subtracted the center 
+0

¡Eso es genial! ¡Creo que (casi) lo conseguí, gracias a ti! – Wok

+0

@wok: Acabo de ver que siempre sumas y restas el centro por separado. Puede ser más fácil si todas sus rejillas de malla pasaron de '-s/2: s/2', o si acaba de ir 1: szNuevo en mi solución. – Jonas

+0

¡Genial! Podría reescribir 'imrotate', pero es más lento que' imrotate' de Matlab en 900x1000 imágenes. ¡Aún así aceptable! :) – Wok

Cuestiones relacionadas