Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inverse a DFT with magnitude with opencv python

Tags:

python

opencv

dft

I'm new to all of this, I would like to get a magnitude spectrum from an image and then rebuild the image from a modified magnitude spectrum.. But for now i'am getting a very dark reconstitution.

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('IMG.jpg',0)

dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)

m, a = np.log(cv2.cartToPolar(dft_shift[:,:,0],dft_shift[:,:,1]))

# do somthing with m

x, y = cv2.polarToCart(np.exp(m), a)


back = cv2.merge([x, y])


f_ishift = np.fft.ifftshift(back)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])

plt.subplot(131),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(132),plt.imshow(m, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.subplot(133),plt.imshow(img_back, cmap = 'gray')
plt.title('result'), plt.xticks([]), plt.yticks([])
plt.show()

the result

result

Can you guys help me figure out why is this so dark.

Thank in advance :)

EDIT

I tryed to normalise the image, but it's not working. I'm still having a very dark image.


import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('IMG.jpg',0)

dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)

m, a = np.log1p(cv2.cartToPolar(dft_shift[:,:,0],dft_shift[:,:,1]))

# modify m, then use the modify m to reconstruct


x, y = cv2.polarToCart(np.expm1(m), a)


back = cv2.merge([x, y])


f_ishift = np.fft.ifftshift(back)
img_back = cv2.idft(f_ishift, flags=cv2.DFT_SCALE)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])


min, max = np.amin(img, (0,1)), np.amax(img, (0,1))
print(min,max)

# re-normalize to 8-bits
min, max = np.amin(img_back, (0,1)), np.amax(img_back, (0,1))
print(min,max)
img_back = cv2.normalize(img_back, None, alpha=0, beta=252, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)


min, max = np.amin(img_back, (0,1)), np.amax(img_back, (0,1))
print(min,max)


plt.subplot(131),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(132),plt.imshow(m, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.subplot(133),plt.imshow(img_back, cmap = 'gray')
plt.title('result'), plt.xticks([]), plt.yticks([])
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()

output:

0 252
0.36347726 5867.449
0 252

I would like to modify the magnitude spectrum and used the modify version to reconstruct the image.

like image 711
jean-loup Monnier Avatar asked Jan 29 '20 21:01

jean-loup Monnier


People also ask

What does cv2 magnitude do?

Magnitude Method. Calculates the magnitude of 2D vectors.

How do you find the Fourier transform of an image in Python?

1) Fast Fourier Transform to transform image to frequency domain. 2) Moving the origin to centre for better visualisation and understanding. 3) Apply filters to filter out frequencies. 5) Inverse transform using Inverse Fast Fourier Transformation to get image back from the frequency domain.

What is DFT image?

As we are only concerned with digital images, we will restrict this discussion to the Discrete Fourier Transform (DFT). The DFT is the sampled Fourier Transform and therefore does not contain all frequencies forming an image, but only a set of samples which is large enough to fully describe the spatial domain image.


1 Answers

If you need to modify the magnitude by raising it to a power near 1 (called coefficient rooting or alpha rooting), then it is just a simple modification of my code above using Python/OpenCV. Simply add cv2.pow(mag, 1.1) before converting the magnitude and phase back to real and imaginary components.

Input:

enter image description here

import numpy as np
import cv2

# read input as grayscale
img = cv2.imread('lena.png', 0)

# convert image to floats and do dft saving as complex output
dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)

# apply shift of origin from upper left corner to center of image
dft_shift = np.fft.fftshift(dft)

# extract magnitude and phase images
mag, phase = cv2.cartToPolar(dft_shift[:,:,0], dft_shift[:,:,1])

# get spectrum for viewing only
spec = np.log(mag) / 30

# NEW CODE HERE: raise mag to some power near 1
# values larger than 1 increase contrast; values smaller than 1 decrease contrast
mag = cv2.pow(mag, 1.1)

# convert magnitude and phase into cartesian real and imaginary components
real, imag = cv2.polarToCart(mag, phase)

# combine cartesian components into one complex image
back = cv2.merge([real, imag])

# shift origin from center to upper left corner
back_ishift = np.fft.ifftshift(back)

# do idft saving as complex output
img_back = cv2.idft(back_ishift)

# combine complex components into original image again
img_back = cv2.magnitude(img_back[:,:,0], img_back[:,:,1])

# re-normalize to 8-bits
min, max = np.amin(img_back, (0,1)), np.amax(img_back, (0,1))
print(min,max)
img_back = cv2.normalize(img_back, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)

cv2.imshow("ORIGINAL", img)
cv2.imshow("MAG", mag)
cv2.imshow("PHASE", phase)
cv2.imshow("SPECTRUM", spec)
cv2.imshow("REAL", real)
cv2.imshow("IMAGINARY", imag)
cv2.imshow("COEF ROOT", img_back)
cv2.waitKey(0)
cv2.destroyAllWindows()

# write result to disk
cv2.imwrite("lena_grayscale_opencv.png", img)
cv2.imwrite("lena_grayscale_coefroot_opencv.png", img_back)


Original Grayscale:

enter image description here

Coefficient Rooting Result:

enter image description here

Here is an animation showing the differences (created using ImageMagick):

enter image description here

like image 120
fmw42 Avatar answered Nov 15 '22 01:11

fmw42