Using fft2 with reshaping for an RGB filter

Posted by Mahmoud Aladdin on Stack Overflow See other posts from Stack Overflow or by Mahmoud Aladdin
Published on 2012-10-12T14:50:11Z Indexed on 2012/10/12 15:37 UTC
Read the original article Hit count: 269

Filed under:
|
|
|
|

I want to apply a filter on an image, for example, blurring filter [[1/9.0, 1/9.0, 1/9.0], [1/9.0, 1/9.0, 1/9.0], [1/9.0, 1/9.0, 1/9.0]].

Also, I'd like to use the approach that convolution in Spatial domain is equivalent to multiplication in Frequency domain.

So, my algorithm will be like.

  1. Load Image.
  2. Create Filter.
  3. convert both Filter & Image to Frequency domains.
  4. multiply both.
  5. reconvert the output to Spatial Domain and that should be the required output.

The following is the basic code I use, the image is loaded and displayed as cv.cvmat object.

Image is a class of my creation, it has a member image which is an object of scipy.matrix and toFrequencyDomain(size = None) uses spf.fftshift(spf.fft2(self.image, size)) where spf is scipy.fftpack and dotMultiply(img) uses scipy.multiply(self.image, image)

f = Image.fromMatrix([[1/9.0, 1/9.0, 1/9.0],
          [1/9.0, 1/9.0, 1/9.0],
          [1/9.0, 1/9.0, 1/9.0]])
lena = Image.fromFile("Test/images/lena.jpg")
print lena.image.shape
lenaf = lena.toFrequencyDomain(lena.image.shape)
ff = f.toFrequencyDomain(lena.image.shape)
lenafm = lenaf.dotMultiplyImage(ff)
lenaff = lenafm.toTimeDomain()
lena.display()
lenaff.display()

So, the previous code works pretty well, if I told OpenCV to load the image via GRAY_SCALE.

However, if I let the image to be loaded in color ... lena.image.shape will be (512, 512, 3) ..

so, it gives me an error when using scipy.fttpack.ftt2 saying "When given, Shape and Axes should be of same length".

What I tried next was converted my filter to 3-D .. as

[[[1/9.0, 1/9.0, 1/9.0], 
  [1/9.0, 1/9.0, 1/9.0], 
  [1/9.0, 1/9.0, 1/9.0]],
 [[1/9.0, 1/9.0, 1/9.0], 
  [1/9.0, 1/9.0, 1/9.0], 
  [1/9.0, 1/9.0, 1/9.0]],
 [[1/9.0, 1/9.0, 1/9.0], 
  [1/9.0, 1/9.0, 1/9.0], 
  [1/9.0, 1/9.0, 1/9.0]]]

And, not knowing what the axes argument do, I added it with random numbers as (-2, -1, -1), (-1, -1, -2), .. etc. until it gave me the correct filter output shape for the dotMultiply to work.

But, of course it wasn't the correct value. Things were totally worse.

My final trial, was using fft2 function on each of the components 2-D matrices, and then re-making the 3-D one, using the following code.

# Spiltting the 3-D matrix to three 2-D matrices.
for i, row in enumerate(self.image):
            r.append(list())
            g.append(list())
            b.append(list())
            for pixel in row:
                r[i].append(pixel[0])
                g[i].append(pixel[1])
                b[i].append(pixel[2])
        rfft = spf.fftshift(spf.fft2(r, size)) 
        gfft = spf.fftshift(spf.fft2(g, size)) 
        bfft = spf.fftshift(spf.fft2(b, size))
        newImage.image = sp.asarray([[[rfft[i][j], gfft[i][j], bfft[i][j]] for j in xrange(len(rfft[i]))] for i in xrange(len(rfft))] )
        return newImage

Any help on what I made wrong, or how can I achieve that for both GreyScale and Coloured pictures.

© Stack Overflow or respective owner

Related posts about python

Related posts about opencv