Image transform in OpenCV – Fourier transform

This blog will introduce the image transform in OpenCV, including using Numpy, OpenCV to calculate the Fourier transform of images, and some applications of the Fourier transform;

2D Discrete Fourier Transform (DFT) Two-dimensional Discrete Fourier Transform (FFT) Fast Fourier Transform

Fourier transform is used to analyze the frequency characteristics of various filters. Two – dimensional discrete Fourier transform (DFT) is used to calculate the frequency domain. A fast algorithm called fast Fourier Transform (FFT) is used to calculate the DFT.

  • OpenCV uses cv2.dft(), cv2.idft() to implement the Fourier transform, which is more efficient (3 times faster than OpenCV).
  • Numpy uses np.ifft2(), np.fft.ifftShift () to implement the Fourier transform, which is more user-friendly;

1. The rendering

The gray scale VS Fourier transform rendering is as follows:You can see that the white area is mostly in the center, showing more low-frequency content. The Fourier transform effect after removing the low-frequency content is as follows:

It can be seen that after using rectangular filtering, the effect is not good, there is a ripple ringing effect; Gaussian filtering can be better; The effect picture of Fourier transform after removing the high frequency content is as follows:By removing the high frequency content in the image, applying LPF to the image, it actually blurs the image. It is clear whether each Filter is High Pass Filter (HPF) or Low Pass Filter (LPF) :Laplace is a high frequency filter;

Principle 2.

  • Performance optimization of DFT: Under certain array size, the performance of DFT calculation is better. The speed is fastest when the array size is a power of two. Arrays of products of size 2, 3, and 5 can also be handled very efficiently.

For best performance, the best size can be found using the OpenCV provided function cv2.getoptimaldftSize (). The image is then filled into the array of the best performance size, and for OpenCV, you must manually fill in zero. But for Numpy, you can specify the new size that FFT computes, and zero is automatically filled in.

By using the optimal array, you can increase efficiency by a factor of four. OpenCV itself is nearly three times faster than Numpy;

Laplace is a High Pass Filter.

3. The source code

3.1 Numpy implements the Fourier transform

Fourier transform

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

img = cv2.imread('ym3.jpg'.0)

# Use Numpy to implement the Fourier transform: FFT packet
# fft.fft2() perform frequency conversion
# Parameter 1: input grayscale image
Input image is filled with 0; < input image shear input image; No return input image is passed
f = np.fft.fft2(img)

# Once the result is obtained, the zero frequency component (dc component) will appear in the upper left corner.
# If you want to center it, use np.fft.fftShift () to move the result in both directions.
Once the frequency transformation is found, the amplitude spectrum can be found.
fshift = np.fft.fftshift(f)
magnitude_spectrum = 20 * np.log(np.abs(fshift))

plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

# Once the frequency transformation is found, high-pass filtering and image reconstruction can be carried out, that is, inverse DFT
rows, cols = img.shape
crow, ccol = rows // 2, cols // 2
fshift[crow - 30:crow + 30, ccol - 30:ccol + 30] = 0
f_ishift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)

# Image gradient chapter learned: high-pass filtering is an edge detection operation. This also indicates that most of the image data exists in the low-frequency region of the spectrum.
# A closer look at the results shows that the last image, shown in JET colors, has some imperfections (it shows some wavy structures, which is called the ringing effect).
# This is caused by using a rectangular window mask, which is converted to a SINC shape, causing this problem. So rectangular Windows are not used for filtering, a Gaussian mask is a better choice.
plt.subplot(131), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(img_back, cmap='gray')
plt.title('Image after HPF'), plt.xticks([]), plt.yticks([])
plt.subplot(133), plt.imshow(img_back)
plt.title('Result in JET'), plt.xticks([]), plt.yticks([])

plt.show()
Copy the code

3.2 OpenCV implements Fourier transform

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

img = cv2.imread('ym3.jpg'.0)
rows, cols = img.shape
print(rows, cols)

# Calculate the size for optimal DFT efficiency
nrows = cv2.getOptimalDFTSize(rows)
ncols = cv2.getOptimalDFTSize(cols)
print(nrows, ncols)

nimg = np.zeros((nrows, ncols))
nimg[:rows, :cols] = img
img = nimg

# OpenCV computs the fast Fourier transform, the input image should first be converted to NP.float32, then the functions cv2.dft() and cv2.idft() are used.
# return the same result as Numpy, but with two channels. The first channel is the real part of the result, and the second channel is the imaginary part of the result.
dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)

magnitude_spectrum = 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))

plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

rows, cols = img.shape
crow, ccol = rows // 2, cols // 2

Create a mask with center square 1 and all other squares 0
# How to delete the high frequency content in the image, that is, we apply LPF to the image. It actually blurs the image.
# To do this, first create a mask with a high value at low frequencies, that is, pass the LF content, 0 in the HF region.
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow - 30:crow + 30, ccol - 30:ccol + 30] = 1

# Apply Mask and inverse DTF
fshift = dft_shift * mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])

plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img_back, cmap='gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
Copy the code

3.3 HPF or LPF?

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

# Simple mean filtering
mean_filter = np.ones((3.3))

# Build gaussian filtering
x = cv2.getGaussianKernel(5.10)
gaussian = x * x.T

# Different edge detection algorithms scharr-x direction
scharr = np.array([[-3.0.3], [...10.0.10], [...3.0.3]])
# Sobel_x
sobel_x = np.array([[-1.0.1], [...2.0.2], [...1.0.1]])
# Sobel_y
sobel_y = np.array([[-1, -2, -1],
                    [0.0.0],
                    [1.2.1]])
# Laplace
laplacian = np.array([[0.1.0],
                      [1, -4.1],
                      [0.1.0]])

filters = [mean_filter, gaussian, laplacian, sobel_x, sobel_y, scharr]
filter_name = ['mean_filter'.'gaussian'.'laplacian'.'sobel_x', \
               'sobel_y'.'scharr_x']
fft_filters = [np.fft.fft2(x) for x in filters]
fft_shift = [np.fft.fftshift(y) for y in fft_filters]
mag_spectrum = [np.log(np.abs(z) + 1) for z in fft_shift]

for i in range(6):
    plt.subplot(2.3, i + 1), plt.imshow(mag_spectrum[i], cmap='gray')
    plt.title(filter_name[i]), plt.xticks([]), plt.yticks([])

plt.show()

Copy the code

reference

  • Docs.opencv.org/3.0-beta/do…