I want to apply rigid body transformations to a large set of 2D image matrices. Ideally, I'd like to be able to just supply an affine transformation matrix specifying both the translation and rotation, apply this in one go, then do cubic spline interpolation on the output.
Unfortunately it seems that affine_transform in scipy.ndimage.interpolation doesn't do translation. I know I could use a combination of shift and rotate, but this is kind of messy and in involves interpolating the output multiple times.
I've also tried using the generic geometric_transformation like this:
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
This works, but it's horribly slow, since it's essentially looping over pixel coordinates! What's a good way to do this?
I think affine_transform does do translation --- there's the offset parameter.
Can you use the scikit image? If this is the case, you could try to apply an homography. An homography cab used to represent both translation and rotation at the same time through a 3x3 matrix. You can use the skimage.transform.fast_homography function.
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)
The transform took about 30 ms on my old Core 2 Duo.
About homography : http://en.wikipedia.org/wiki/Homography
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With