A simple pre-processing filter for image processing
When processing images, it is useful to avoid artifacts, in particular when you try to understand biological processes. In the past, I have used natural images (found on internet, grabbed from holiday pictures, ...) without controlling for possible problems.
In particular, digital pictures are taken on pixels which are most often placed on a rectangular grid. It means that if you rotate that image, you may lose information and distort it and thus get wrong results (even for the right algorithm!). Moreover, pictures have a border while natural scenes do not, unless you are looking at it through an aperture. Intuitively, this means that large objects would not fit on the screen and are less informative.
In computer vision, it is easier to handle these problems in Fourier space. There, an image (that we suppose square for simplicity) is transformed in a matrix of coefficients of the same size as the image. If you rotate the image, the Fourier spectrum is also rotated. But as you rotate the image, the information that was in the corners of the original spectrum may span outside the spectrum of the rotated image. Also, the information in the center of the spectrum (around low frequencies) is less relevant than the rest.
Here, we will try to keep as much information about the image as possible, while removing the artifacts related to the process of digitalizing the picture.
Let's first initialize an image and a simple image processing library:
%matplotlib inline
%load_ext autoreload
%autoreload 2
from SLIP import Image
im = Image('https://raw.githubusercontent.com/bicv/SLIP/master/default_param.py')
image= im.imread('https://raw.githubusercontent.com/bicv/SLIP/master/database/lena256.png')
im.set_size(image)
_ = im.show_spectrum(image)
Much of the energy is contrated on the lower energies and we may scale them for a better visualization by using a whitening filter:
white = im.whitening(image)
_ = im.show_spectrum(white)
Note that much of the energy is concentrated on the cardinal axis.
print(im.retina.__doc__)
_ = im.show_FT(im.f_mask)
print(im.preprocess.__doc__)
white_pre = im.preprocess(white)
_ = im.show_spectrum(white_pre)
The residual is as expected mainly noise which corresponds to the information that we wished initaially to discard:
_ = im.show_spectrum(white_pre-white)
Applied to the original image directly, it shows a pretty recognizable pre-processed image:
image_pre = im.preprocess(image)
_ = im.show_spectrum(image_pre)
Again, the residual shows the features that we wished to cancel out:
_ = im.show_spectrum(image_pre-image)
A whitening shows better the high-frequency artifact (by associativity of the Fourier transform, this result is exactly the same as the residual on the pre-processing of the whitened image shown above):
_ = im.show_spectrum(im.whitening(image_pre-image))
CQFD.