Constructing a rotation-invariant transform

In image processing and object recognition, certain characteristics are highly important to detect while other, such as rotation, are not. Here, we use the Radon transform to construct a system to detect image characteristics, independently of their rotation. As a side note, the Hough transform (see previous post) could also be used to this purpose. A rotation in the Radon transform causes the spectrum to shift. By using a simple DFT technique, this shift can be bypassed.

Screen Shot 2015-05-07 at 16.00.13

Using some example code form the Scikit-Image library for Python, we can obtain the following result.

figure_1

We note that in the projection-angular domain, a 90 degree rotation causes a \frac{\pi}{2} phase shift. However, the DFT transform is unaffected by this shift, as can be seen in the log-value plot.

Try it yourself with the code below.

from __future__ import print_function, division

import numpy as np
import matplotlib.pyplot as plt
from scipy import fftpack

from skimage.io import imread
from skimage import data_dir
from skimage.transform import radon, rescale, rotate

image = imread("finger.jpg", as_grey=True)
image = rescale(image, scale=0.4)

fig, ((ax1, ax2, ax3,), (ax4, ax5, ax6)) = plt.subplots(2, 3, figsize=(8, 4.5))


# Original image
image = rotate(image, 0)
ax1.set_title("Original")
ax1.imshow(image, cmap=plt.cm.Greys_r)

image_rot = rotate(image, 90)
ax4.set_title("(Rotated)")
ax4.imshow(image_rot, cmap=plt.cm.Greys_r)


# Sinogram / Radon transform
theta = np.linspace(0., 180., max(image.shape), endpoint=False)
sinogram = radon(image, theta=theta, circle=True)
sinogram_rot = radon(image_rot, theta=theta, circle=True)

ax2.set_title("Radon transform\n(Sinogram)")
ax2.set_xlabel("Projection angle (deg)")
ax2.set_ylabel("Projection position (pixels)")

ax2.imshow(sinogram, cmap=plt.cm.Greys_r,
           extent=(0, 180, 0, sinogram.shape[0]), aspect='auto')

ax5.imshow(sinogram_rot, cmap=plt.cm.Greys_r,
           extent=(0, 180, 0, sinogram.shape[0]), aspect='auto')


# DFT / Make it rotation invariant
fourier_sine = fftpack.fft2(sinogram)
fourier_shifted = np.log(np.abs(fftpack.fftshift(fourier_sine)))

fourier_sine_rot = fftpack.fft2(sinogram_rot)
fourier_shifted_rot = np.log(np.abs(fftpack.fftshift(fourier_sine_rot)))

ax3.set_title("DFT transform (log)")

ax3.imshow(fourier_shifted)
ax6.imshow(fourier_shifted_rot)

# Plot the data
plt.show()
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s