1
votes

I have a hybrid image that was created by superimposing the low frequencies of one image with the high frequencies of another. I'm trying to separate (de-hybridize) this image by passing it through a low-pass filter to extract the low frequencies (one of the two images), and then subtracting that from the original image to yield the other image (high frequencies).

**Problem: ** When I extract the low frequencies, the values are all higher than the original image, so when I subtract the low frequencies from the original image, what's left is a bunch of negative values.

Does anyone know why my low pass filter is yielding higher frequency values than the original image?

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from numpy.fft import fft2, ifft2, fftshift, ifftshift

# Make Gaussian filter
def makeGaussianFilter(numRows, numCols, sigma, highPass=True):
   centerI = int(numRows/2) + 1 if numRows % 2 == 1 else int(numRows/2)
   centerJ = int(numCols/2) + 1 if numCols % 2 == 1 else int(numCols/2)

   def gaussian(i,j):
      coefficient = np.exp(-1.0 * ((i - centerI)**2 + (j - centerJ)**2) / (2 * sigma**2))
      return 1 - coefficient if highPass else coefficient

   return np.array([[gaussian(i,j) for j in range(numCols)] for i in range(numRows)])

# Filter discrete Fourier transform
def filterDFT(imageMatrix, filterMatrix):
   shiftedDFT = fftshift(fft2(imageMatrix))
   filteredDFT = shiftedDFT * filterMatrix
   return ifft2(ifftshift(filteredDFT))

# Low-pass filter
def lowPass(imageMatrix, sigma):
   n,m = imageMatrix.shape
   return filterDFT(imageMatrix, makeGaussianFilter(n, m, sigma, highPass=False))

# Read in einsteinandwho.png and convert to format that can be displayed by plt.imshow
im3 = mpimg.imread('einsteinandwho.png')
rows = im3.shape[0]
cols = im3.shape[1]
img3 = np.ones((rows, cols, 4))
for i in range(rows):
    for j in range(cols):
        img3[i][j][0:3] = im3[i][j]
        img3[j][j][3] = 1

# Extract low frequencies and convert to format that can be displayed by plt.imshow
lowPassed = np.real(lowPass(im3, 10))
low = np.ones((rows, cols, 4))

for i in range(rows):
    for j in range(cols):
        low[i][j][0:3] = lowPassed[i][j]
        low[j][j][3] = 1

# Remove low frequencies from image
output = img3[:,:,0:3] - low[:,:,0:3]
1
You don't need to make an RGBA version of the image for display by plt.imshow. In fact, it's easier to display the gray-scale image directly.Cris Luengo

1 Answers

0
votes

Does anyone know why my low pass filter is yielding higher frequency values than the original image?

Do notice the difference between pixel values and frequency values. You are seeing the pixel values being higher, not the frequency values!


When I run your code I see the high-frequency component having both negative and positive pixel values, not all negative values. It is expected for this image to have a zero mean. The zero frequency component (also called DC component) is the one that sets the mean pixel value. By subtracting a low-pass filtered image, you are setting the zero frequency to 0, and thus setting the mean pixel value to 0 (the low-pass filtered image contains all of the power of the zero frequency).