Frequency domain filtering and spatial domain filtering are inextricably linked. The frequency domain filter achieves the purpose of image processing by controlling the changing frequency of the image, while the spatial domain filter achieves the effect of processing the image by convolving the template with the image matrix. It can be known from the convolution theorem that the convolution in the spatial domain is numerically equal to the inverse transformation of the product of the Fourier transform of the image and the template.
That is to say, if the template in the spatial domain is subjected to discrete Fourier transformation to obtain the template in the frequency domain, then the final result of using the spatial domain template for spatial filtering and using the obtained frequency domain template for frequency domain filtering is the same. The two methods sometimes interchangeable.
However, it should be noted that the length of the convolution result obtained by convolving the original image and the spatial template is longer than that of the original image. Even if the image and the template are filled, the first bit of the convolution result obtained is not The convolution of the template at the first pixel of the original image.
For example, assuming that the length of the p-bit original image is P, and q is the length of the convolution template, the length of the convolution template is Q. From the calculation formula of convolution, it is easy to obtain that the minimum size of the image after filling without confusion is P+Q-1. After filling, p, q for
Run the following program
import numpy as np # Keep the last three digits of the significant point np.set_printoptions(precision=3) # Do not use scientific notation np.set_printoptions(suppress=True) p = np.array([[1,2,3,0,0],[4,5,6,0,0],[7,8,9,0,0],[0,0,0,0,0],[0,0,0,0,0]]) q = np.array([[1,1,1,0,0],[1,-8,1,0,0],[1,1,1,0,0],[0,0,0,0,0],[0,0,0,0,0]]) pp = np.fft.fft2(p) qq = np.fft.fft2(q) tt = pp*qq t = np.fft.ifft2(tt) print('p\n', p) print('q\n', q) print('t\n', t.real)
Using the convolution theorem, the result t after convolution can be obtained as
It can be seen from the above running results that although zero-padding can effectively avoid confusion, one thing that cannot be changed is that the size of the image after convolution will become larger. It can be seen that the result after convolution fills the entire 5×5 matrix. In theory, it is more appropriate to replace the original first pixel of the image with the convolution value of the template at the first pixel of the image (that is, 3). This result is at (1,1) of the convolution operation. In fact, the real convolution result on the image is located at the center of t, that is, the screenshot below is the filtering result of the same size as the original image.
Therefore, in order to obtain the same result as the spatial domain filter, when the image is extracted after filling and frequency domain filtering, the edges of the obtained processing result must be removed. Assuming that the template size is P×Q, the edge width obtained after filtering is (floor(P/2), floor(Q/2)).
The following is a comparison of spatial domain filtering and frequency domain filtering. The comparison steps are as follows
(1) Define a small-sized spatial domain template, and use this template to perform spatial filtering to obtain a filtered image.
(2) Calculate the filling size of the frequency domain template according to the size of the spatial domain filtering template and the original image.
(3) Fill the air domain template and multiply it by $(-1)^{x+y}$, and then perform Fourier transform to obtain the frequency domain template.
(4) Perform frequency domain filtering with the obtained frequency domain template, and intercept the filtering result.
(5) The results of spatial domain filtering and frequency domain filtering are displayed and compared.
The comparison code for the sobel operator is as follows
import frequency_function as fre import airspace_filter as air import cv2 as cv import numpy as np import matplotlib.pyplot as plt original_image_test4 = cv.imread('test4.tif',0) '''Compare whether the corresponding frequency-domain filter and spatial-domain filter are equivalent''' # # Compare sobel operator # # get airspace sobel filter function airspace_result_test1 = air.laplace_sharpen(original_image_test4, my_type='big') # Define Spatial Filter Template air_model = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]]) # Calculate the size of the template after filling shape = (2*original_image_test4.shape[0], 2*original_image_test4.shape[1]) # Fill the spatial domain template to the corresponding size, transform to frequency domain template and move the low frequency to the center fre_model = np.fft.fft2(fre.my_get_fp(fre.my_fill(air_model, shape))) # Frequency Domain Filtering with Frequency Domain Templates frequency_result_test1 = fre.myfunc_seldifine(original_image_test4, fre_model, output_offset=(1, 1)) # Convert the pixel value of the filtered result to 0~255 airspace_result_test1=air.show_edge(airspace_result_test1) frequency_result_test1=air.show_edge(frequency_result_test1) # The results show plt.subplot(131) plt.imshow(original_image_test4) plt.title('original') plt.subplot(132) plt.imshow(airspace_result_test1) plt.title('spatial filter') plt.subplot(133) plt.imshow(frequency_result_test1) plt.title('frequency filter') plt.show()
The comparison result is
It can be seen that the effect of the two methods is the same.
Comparison code for Gaussian low pass filtering
import frequency_function as fre import airspace_filter as air import cv2 as cv import numpy as np import matplotlib.pyplot as plt original_image_test1 = cv.imread('test1.pgm',0) original_image_test2 = cv.imread('test2.tif',0) original_image_test3 = cv.imread('test3_corrupt.pgm',0) original_image_test4 = cv.imread('test4.tif',0) # # Compare Gaussian Filters # # Get the spatial Gaussian filter function airspace_result_test1 = air.gaussion_blur_gray(original_image_test1, 7, 1.5) # Get the spatial Gaussian filter template air_model = air.get_gaussion_blur_retric(7, 1.5) # Calculate the size of the template after filling shape = (original_image_test1.shape[0] + 7, original_image_test1.shape[1] + 7) # Fill the spatial domain template to the corresponding size, transform to frequency domain template and move the low frequency to the center fre_model = np.fft.fft2(fre.my_get_fp(fre.my_fill(air_model, shape))) # Frequency Domain Filtering with Frequency Domain Templates frequency_result_test1 = fre.myfunc_seldifine(original_image_test1, fre_model, output_offset=(3, 3)) # Filter result display plt.subplot(131) plt.imshow(original_image_test1) plt.title('original') plt.subplot(132) plt.imshow(airspace_result_test1) plt.title('spatial filter') plt.subplot(133) plt.imshow(frequency_result_test1) plt.title('frequency filter') plt.show()
The comparison result is