2012-07-13 8 views
5

Quiero aplicar transformaciones corporales rígidas a un gran conjunto de matrices de imágenes 2D. Idealmente, me gustaría poder proporcionar una matriz de transformación afín que especifique tanto la traducción como la rotación, aplicar esto de una vez, luego hacer una interpolación de spline cúbica en la salida.Transformaciones corporales rígidas 2D rápidas en numpy/scipy

Desafortunadamente parece que affine_transform en scipy.ndimage.interpolation no hace la traducción. Sé que podría usar una combinación de shift y rotate, pero esto es un poco complicado e implica la interpolación de la salida varias veces.

También he intentado usar el genérico geometric_transformation así:

import numpy as np 
from scipy.ndimage.interpolation import geometric_transformation 

# make the affine matrix 
def maketmat(xshift,yshift,rotation,dimin=(0,0)): 

    # centre on the origin 
    in2orig = np.identity(3) 
    in2orig[:2,2] = -dimin[0]/2.,-dimin[1]/2. 

    # rotate about the origin 
    theta = np.deg2rad(rotation) 
    rotmat = np.identity(3) 
    rotmat[:2,:2] = [np.cos(theta),np.sin(theta)],[-np.sin(theta),np.cos(theta)] 

    # translate to new position 
    orig2out = np.identity(3) 
    orig2out[:2,2] = xshift,yshift 

    # the final affine matrix is just the product 
    tmat = np.dot(orig2out,np.dot(rotmat,in2orig)) 

# function that maps output space to input space 
def out2in(outcoords,affinemat): 
    outcoords = np.asarray(outcoords) 
    outcoords = np.concatenate((outcoords,(1.,))) 
    incoords = np.dot(affinemat,outcoords) 
    incoords = tuple(incoords[0:2]) 
    return incoords 

def rbtransform(source,xshift,yshift,rotation,outdims): 

    # source --> target 
    forward = maketmat(xshift,yshift,rotation,source.shape) 

    # target --> source 
    backward = np.linalg.inv(forward) 

    # now we can use geometric_transform to do the interpolation etc. 
    tformed = geometric_transform(source,out2in,output_shape=outdims,extra_arguments=(backward,)) 

    return tformed 

Esto funciona, pero es terriblemente lento, ya que es esencialmente un bucle sobre las coordenadas del pixel! ¿Cuál es una buena manera de hacer esto?

Respuesta

3

creo affine_transformhace hacer traducción --- existe el parámetro offset.

+0

¡Hah, haz un buen punto! Lo que me sorprendió fue que esperaba suministrar una matriz de rango 3 y se negó a aceptar más de dos filas. Creo que sería mucho más sencillo si 'affine_transform' aceptara una matriz única para la transformación, como en la sugerencia de Nichola. –

+0

Affine no es rígido –

3

¿Se puede usar el scikit image? Si este es el caso, podría intentar aplicar una homografía. Una cabina de homografía utilizada para representar tanto la traducción como la rotación al mismo tiempo a través de una matriz de 3x3. Puede usar la función skimage.transform.fast_homography.

import numpy as np 
import scipy 
import skimage.transform 
im = scipy.misc.lena() 
H = np.asarray([[1, 0, 10], [0, 1, 20], [0, 0, 1]]) 
skimage.transform.fast_homography(im, H) 

La transformación tomó aproximadamente 30 ms en mi viejo Core 2 Duo.

Sobre homografía: http://en.wikipedia.org/wiki/Homography

+0

Agradable, casi exactamente lo que estaba buscando. El único inconveniente es que 'fast_homography' solo parece admitir la interpolación bilineal, pero la' homography' simple es bicúbica y es lo suficientemente rápida para mis propósitos. –

Cuestiones relacionadas