12

I would like to use python to perform a geometric transform over an image, to 'straighten' or rectify an image along a given curve. It seems that scikit-image ProjectiveTransform() and warp() are very good for this, but the documentation is sparse. I followed the documentation here, but I couldn't get it to work properly for a sample case.

Here's an example: I'll create an image with two concentric circles, and the goal is to rectify one quarter of these circles, so that the resulting image are two parallel lines. Here is the sample data:

import numpy as np
a = np.zeros((500, 500))

# create two concentric circles with a thickness of a few pixels:
for i in range(500):
    for j in range(500):
        r = np.sqrt((i - 250)**2 + (j - 250)**2) 
        if r > 50 and r < 52:
            a[i, j] = 10
        if r > 100 and r < 102:
            a[i, j] = 10
# now create the coordinates of the control points in the original image:
(x0, y0) = (250, 250)
r = 30   # inner circle
x = np.linspace(250 - r, 250, 50)
y = np.sqrt(r ** 2 - (x - x0) ** 2) + x0
r2 = 120   # outer circle
x2 = np.linspace(250 - r2, 250, 50)
y2 = np.sqrt(r2 ** 2 - (x2 - x0) ** 2) + x0
dst = np.concatenate((np.array([x, y]).T, np.array([x2, y2]).T))

And this can be plotted, e.g.:

imshow(a, cmap='gist_gray_r')
plot(x, y, 'r.')
plot(x2, y2, 'r.')

enter image description here

So my goal is to rectify the image in the quadrant given by the red control points. (In this case, this is the same as a Cartesian to polar transformation.) Using scikit image from the documentation example, I've done:

# create corresponding coordinates for control points in final image:
xi = np.linspace(0, 100, 50)
yi = np.zeros(50)
xi2 = xi
yi2 = yi + (r2 - r)
src = np.concatenate((np.array([xi, yi]).T, np.array([xi2, yi2]).T))

# transform image
from skimage import transform, data
tform3 = transform.ProjectiveTransform()
tform3.estimate(src, dst)
warped = transform.warp(a, tform3)

I was expecting this warped image to show two parallel lines, but instead I get: enter image description here

What am I doing wrong here?

Note that while in this case it is a Cartesian to polar transform, in the most general case I'm looking for a transformation from some arbitrary curve. If someone knows of a better way using some other package, please let me know. I can solve this problem by using ndimage.map_coordinates for a bunch of radial lines, but was looking for something more elegant.

tiago
  • 22,602
  • 12
  • 72
  • 88

1 Answers1

8

A ProjectiveTransform is a linear transformation, and cannot match your deformation scheme. There may be better options, but for arbitrary curves you can make it work with a PiecewiseAffineTransform, which will match anything you throw at it by tessellating linear transformations. If you simply change the name of the transform in your code, this is the output I get:

enter image description here

So you'll probably need to tweak it a little bit to get what you are after, but at least it produces the two parallel lines you were expecting in the area where your transformation is well defined.

Jaime
  • 65,696
  • 17
  • 124
  • 159
  • 1
    I don't think that's the exact reason it doesn't work: A homography is linear in homogeneous coordinates but the corresponding 2D projective transformation isn't linear. – YXD Oct 29 '13 at 16:09
  • Good point, maybe I generalized too much. I still don't think it can model a transformation from Cartesian to polar coordinates, which is what th eOP is after. – Jaime Oct 29 '13 at 16:12
  • Thanks, that does solve it. One can use the argument `output_shape` in warp so that the output will have the dimensions where the transformation is defined. E.g., in this case: `output_shape=(90, 100)`. I now see that there is also a `PolynomialTransform` which I guess could also be used here (sadly the examples are scarce again). – tiago Oct 29 '13 at 17:16
  • 1
    @tiago I tried to set it up with `PolynomialTransform` but failed to get anything else than a blank image... You may want to ping the [skimage mailing list](http://groups.google.com/group/scikit-image), I'm pretty sure they'll be more than happy to help you sort any of the transforms out. – Jaime Oct 29 '13 at 17:52
  • I only ran across this question now, but if you are still having problems please let us know. We're more than happy to add additional examples to the gallery. – Stefan van der Walt Jan 13 '14 at 14:49