当前位置:   article > 正文

图片的高频与低频分量 初识 与 相关博客_图像傅里叶变换后高频、低频分别代表图像的什么信息?

图像傅里叶变换后高频、低频分别代表图像的什么信息?

图片的低频与高频分量 初识

图像中的低频信号和高频信号,也叫做低频分量和高频分量。

低频分量对应图像中物体的亮度均匀或变化缓慢的区域;

高频分量对应图像中物体的边缘、细节、噪声。

定义

图像的频率:该图像灰度值变化剧烈程度的指标,是灰度在平面空间上的梯度。

低频

图像信号中的低频分量,指的是图像强度(亮度、灰度)变换平缓的地方。也就是大片色块,变化不那么明显的地方。

低频就是颜色缓慢地变化,也就是灰度缓慢地变化,就代表着那是连续渐变的一块区域,这部分就是低频。对于一幅图像来说,除去高频的就是低频了,也就是边缘以内的内容为低频,而边缘内的内容就是图像的大部分信息,即图像的大致概貌和轮廓,是图像的近似信息。

高频

图像信号中的高频分量,指的就是图像信号强度(亮度/灰度)变化剧烈的地方,也就是我们常说的边缘(轮廓)。

高频就是频率变化快。图像中什么时候灰度变化快?就是相邻区域之间灰度相差很大,这就是变化得快。图像中,一个影像与背景的边缘部位,通常会有明显的差别,也就是说变化那条边线那里,灰度变化很快,也即是变化频率高的部位。因此,图像边缘的灰度值变化快,就对应着频率高,即高频显示图像边缘。图像的细节处也是属于灰度值急剧变化的区域,正是因为灰度值的急剧变化,才会出现细节。

另外噪声(即噪点)也是这样,在一个像素所在的位置,之所以是噪点,就是因为它与正常的点颜色不一样了,也就是说该像素点灰度值明显不一样了,也就是灰度有快速地变化了,所以是高频部分,因此有噪声在高频这么一说。

举例      

1、在一张白纸上有一行字,那么我们肯定直接聚焦在文字上,而不会太在意白纸本身,这里文字就是高频信号,而白纸就是低频信号。

2、为什么图像的频率是表征图像中灰度变化剧烈程度的指标。大面积的沙漠在图像中是一片灰度变化缓慢的区域,对应的频率值很低,属于低频;而对于地表属性变换剧烈的边缘区域在图像中是一片灰度变化剧烈的区域,对应的频率值较高,属于高频。

3、低频保留了光影与颜色,高频保留了纹理与质感。 

4、穿条纹衬衫的人

在上图中,围巾和条纹衬衫为该图像高频的区域,这部分从一种亮度到另一种亮度变化非常迅速。在同一张图像的较高位置,我们看到天空和背景的部分变化非常缓慢,是图像的低频部分。

空域和频域 & 傅里叶变换

空域与频域

空域是指图像平面本身,空域滤波这类方法直接对图像的像素进行处理。频域滤波是变换域滤波的一种,它是指将图像进行变换后(频域是指经过傅里叶变换之后),在变换域中对图像的变换系数进行处理(滤波),处理完毕后再进行逆变换,获得滤波后的图像。

如何将图像从空域切换到频域?使用傅里叶变换。

图像的空间域,就是二维平面坐标系,它有两个正交的轴即x,y轴。 某点在空间域上的幅值就是该点处的灰度。 图像上某点处的灰度是该点在x,y方向上灰度的叠加。 这样,分别以x,y为横坐标,灰度值为纵坐标,得到两个函数。表示图像在x,y方向上的灰度值变化情况。

傅里叶级数。根据傅里叶级数的知识,函数可以写成多个不同振幅及频率的正弦函数的和。因此,通过傅里叶变换,灰度-x函数就变换为振幅-u函数,灰度-y函数就换为振幅-v函数。建立以u,v为正交轴的平面坐标系,这样就得到了频率图。

 

 由于二维DFT通常为复函数,因此可以用极坐标形式表示:

傅里叶变换的目的

Question1:我们对图像作傅里叶变换得到频谱图,是为了啥?

Answer1:

  • 傅里叶变换变换可以得到高频与低频,针对高频与低频处理,可以实现不同的目的;
  • 傅里叶变换是可逆的,通过逆傅里叶变换,可以恢复原图像;
  • 如果对高频与低频进行处理,然后进行逆傅里叶变换,所做的处理会反映到逆变换图像上。

Question2:如何处理才能去除高频 或者 低频信息?

Answer2:如何理解图像的频率域处理? - 知乎 (zhihu.com)

经过低通滤波器处理。保留低频信息,去除高频信息。图像细节部分丢失,图像变模糊。

经过高通滤波器处理,也就是去除频率域中的低频信息,只保存高频信息后的结果。图像只保留了细节部分。

左图为频率图,右图为原图

经低通滤波器处理,去除高频信息,保留低频信息;
左图为处理后的频率图,右图为处理后的图像。

经高通滤波器处理,去除低频信息,保留高频信息;
左图为处理后的频率图,右图为处理后的图像。

傅里叶变换

图像傅里叶变换原理 python实现 - 我坚信阳光灿烂 - 博客园

推荐 数字图像处理 - 标签 - 我坚信阳光灿烂 - 博客园 (cnblogs.com)

在数字图像处理中,有两个经典的变换被广泛使用——傅里叶变换和霍夫变换。傅里叶变换是将时间域上的信号转变为频率域上的信号,进而进行图像去噪、图像增强等处理。

傅里叶变换(Fourier Transform,FT)后,对同一事物的观看角度随之改变,可以从频域里发现一些从时域里不易察觉的特征。某些在时域内不好处理的地方,在频域内可以容易地处理。

傅里叶定理:“ 任何连续周期信号都可以表示成(或者无限逼近)一系列正弦信号的叠加。”

 

python方法实现傅里叶变换

见 图像处理之傅里叶变换 - 知乎 (zhihu.com)

python里有两种常见方法:numpy 和 OpenCV。

1.numpy

Python Numpy np.fft2()方法|极客教程 (geek-docs.com)

NumPy 1.22 中文 (runebook.dev)

numpy.fft.fft(a, n=None, axis=-1, norm=None)

numpy.fft.fft - 计算一维离散傅里叶变换。 (runebook.dev)

功能:计算一维傅里叶变换。使用高效的快速傅立叶变换(FFT)算法[CT] 计算一维n点离散傅立叶变换(DFT)。

numpy.fft.fft2(a, n=None, axis=-1, norm=None)

numpy.fft.fft2 - 计算二维离散傅立叶变换。 (runebook.dev)

功能:计算二维的傅里叶变换。此函数通过快速傅立叶变换(FFT)计算M维数组中任何轴上的n维离散傅立叶变换。默认情况下,转换是在输入数组的最后两个轴上进行的,即二维FFT。

numpy.fft.fftn()

numpy.fft.fftn - 计算N维离散傅立叶变换。 (runebook.dev)

功能:计算n维的傅里叶变换。通过快速傅立叶变换(FFT)计算M维数组中任意数量轴上的N维离散傅立叶变换。

numpy.fft.fftfreq()

numpy.fft.rfftfreq - 返回离散傅里叶变换的采样频率(与rfft、irfft一起使用)。 (runebook.dev)

功能:返回离散傅里叶变换的采样频率(与rfft、irfft一起使用)。返回的浮点数组 f 包含频率单元中心,该频率单元中心以每单位采样间隔的周期为周期(开始时为零)。例如,如果样本间隔为秒,则频率单位为循环/秒。

numpy.fft.shift()

numpy.fft.fftshift - 将零频分量移到光谱中心。 (runebook.dev)

功能:将FFT输出中的直流分量移动到频谱中央。列出的所有轴交换半角空格(默认为全部)。

20*np.log(np.abs(fshift))

功能:傅里叶变换得到的结果是一个复数数组,不能直接用于显示图像,要想得到频谱灰度图像,我们需要一个映射,把复数映射[0, 255]之间。

np.abs(i_img)

功能:设置值范围,实现傅里叶逆变换

2.OpenCV

cv2.dft()

功能:实现傅里叶变换

cv2.magnitude(参数1,参数2)

这个函数的作用与numpy数组:np.abs(fshift)是一回事,np.abs(fshift)是求复数数组fshift中每个复数的大小(注:fshift是一个一维的复数数组),而cv2.dft()返回的是一个二维数组(一维是复数的实部,一个是复数的虚部).

cv2.idft(ishift)

功能:实现傅里叶逆变换。


 

应用示例:高低频图像混合

怎么理解图像的高低频? 

图像的低频部分可以理解为“轮廓”,比如人脸的脸型。

图像的高频部分可以理解为“细节”,比如人脸的皱纹、斑点等。

因此,对图像做模糊处理后得到了图像的低频部分,对图像做锐化处理会让图像的高频信息更多。

放大缩小图片会看到不同的结果?

当我们放大混合图像时,可以清楚地看到高频信息,于是人眼更倾向于识别这部分的信息。相反地,当我们缩小图片时,高频信息就不那么容易被观察到了,这时候我们我们就更倾向于识别低频的部分。

这里有一张哈利波特和伏地魔的混叠图像。可以看到,当图像放大时我们看到的是哈利波特,而当图片缩小时,我们会认为这张图片是描述伏地魔的。

如何实现混合图像的效果?

实现的总体思路很简单——将只有低频信息的图片和只有高频信息的图像叠加在一起。具体步骤如下:

  1. 取第一张图片:
    1. 准备好低频的滤波器(常用高斯模糊)
    2. 将图像转为矩阵,分层(如JPG图像会分成RGB三层)处理。其中,第一二列表示图像的横纵坐标,第三列存储不同的层的index(如JPG有0-2,PNG有0-3(其中第四层(3)存的是透明度));举个栗子,[;, ;, 0] 指的是R层的数据点
    3. 每一个维度的图片分别与高斯滤波器做卷积
  2. 取第二张图片:
    1. 准备好低频的滤波器(常用高斯模糊)
    2. 将图像转为矩阵
    3. 每一个维度的图片分别与高斯滤波器做卷积
    4. 用原图矩阵减去卷机后的矩阵,得到高频图矩阵
  3. 将两个处理后的图像矩阵相加,得到混合图像

实现代码:GitHub - MinisculeDust/Hybrid-Image

实现代码

 MyHybridImages.py

  1. import numpy as np
  2. from MyConvolution import convolve
  3. # version 3.3 2019.11.7-18:57
  4. # https://github.com/MinisculeDust/Hybrid-Image/blob/master/MyHybridImages.py
  5. def makeGaussianKernel(sigma):
  6. # set the sacle of templet
  7. size = (int)(8 * sigma + 1) # (this implies the window is + / - 4 sigmas from the centre of the Gaussian)
  8. if (size % 2 == 0):
  9. size += 1 # size must be odd
  10. # templet's centre position
  11. center = (size - 1) / 2
  12. # state kernel
  13. kernel = np.zeros((size, size))
  14. kernel_sum = 0
  15. # gaussian calculating
  16. for i in range(size):
  17. x2 = pow(i - center, 2)
  18. for j in range(size):
  19. y2 = pow(j - center, 2)
  20. g = np.exp(-(x2 + y2)/(2 * sigma * sigma)) / (2 * np.pi * sigma * sigma)
  21. kernel[i][j] = g
  22. kernel_sum += kernel[i][j]
  23. # normalisation
  24. # kernel_sum2 = 0
  25. # for i in range(size):
  26. # for j in range(size):
  27. # kernel[i][j] = kernel[i][j] / kernel_sum
  28. # kernel_sum2 += kernel[i][j]
  29. return kernel
  30. def myHybridImages(lowImage: np.ndarray, lowSigma, highImage: np.ndarray, highSigma):
  31. # make kernel
  32. low_kernel = makeGaussianKernel(lowSigma)
  33. high_kernel = makeGaussianKernel(highSigma)
  34. # convolve low-pass pictures
  35. low_image = convolve(lowImage, low_kernel)
  36. # make high-pass picture
  37. high_image = (highImage - convolve(highImage, high_kernel))
  38. # final picture
  39. # the weights between and final lighting can be changed flexibly
  40. weight = 1
  41. weight2 = 1
  42. adjustment = 0
  43. hybrid_image = high_image * weight2 + low_image * weight + adjustment
  44. # hybrid_image = high_image + low_image
  45. # randomly double check the output
  46. # print(hybrid_image[11][22][1])
  47. # print(hybrid_image[44][55][0])
  48. # print(hybrid_image[357][159][2])
  49. return hybrid_image

MyConvolution.py

  1. import numpy as np
  2. # version 3.4 2019.11.8-9:37
  3. # https://github.com/MinisculeDust/Hybrid-Image/blob/master/MyConvolution.py
  4. def calculate_convolution(image, kernel):
  5. # rotating kernel with 180 degrees
  6. kernel = np.rot90(kernel, 2)
  7. kernel_heigh = int(np.array(kernel).shape[0])
  8. kernel_width = int(np.array(kernel).shape[1])
  9. # set kernel matrix to random int matrix
  10. if ((kernel_heigh % 2 != 0) & (kernel_width % 2 != 0)): # make sure that the scale of kernel is odd
  11. # the scale of result
  12. conv_heigh = image.shape[0] - kernel.shape[0] + 1
  13. conv_width = image.shape[1] - kernel.shape[1] + 1
  14. conv = np.zeros((conv_heigh, conv_width))
  15. # convolve
  16. for i in range(int(conv_heigh)):
  17. for j in range(int(conv_width )):
  18. result = (image[i:i + kernel_heigh, j:j + kernel_width] * kernel).sum()
  19. # if(result<0):
  20. # resutl = 0
  21. # elif(result>255):
  22. # result = 255
  23. conv[i][j] = result
  24. return conv
  25. def convolve(image: np.ndarray, kernel: np.ndarray) -> np.ndarray:
  26. # zero padding
  27. kernel_half_row = int((kernel.shape[0]-1)/2)
  28. kernel_half_col = int((kernel.shape[1]-1)/2)
  29. # judge how many channels
  30. if len(image.shape) == 3:
  31. image = np.pad(image, ((kernel_half_row, kernel_half_row), (kernel_half_col, kernel_half_col),(0, 0)), 'constant', constant_values=0)
  32. # if image.shape[2] == 3 or image.shape[2] == 4:
  33. # if style is png, there will be four channels, but we just need to use the first three
  34. # if the style is bmp or jpg, there will be three channels
  35. image_r = image[:, :, 0]
  36. image_g = image[:, :, 1]
  37. image_b = image[:, :, 2]
  38. result_r = calculate_convolution(image_r, kernel)
  39. result_g = calculate_convolution(image_g, kernel)
  40. result_b = calculate_convolution(image_b, kernel)
  41. result_picture = np.dstack([result_r, result_g, result_b])
  42. # if the picture is black and white
  43. elif len(image.shape) == 2:
  44. image = np.pad(image, ((kernel_half_row, kernel_half_row), (kernel_half_col, kernel_half_col)), 'constant', constant_values=0)
  45. result_picture = calculate_convolution(image, kernel)
  46. # returns the convolved image (of the same shape as the input image)
  47. return result_picture
  48. def fourier_trans(image: np.ndarray, kernel: np.ndarray):
  49. # make the scale of the kernel as the same as pictures
  50. # make sure it can work for different sance of pictures
  51. if (image.shape[0] - kernel.shape[0]) % 2 == 0:
  52. pad_heigh = np.int(((image.shape[0] - kernel.shape[0])) / 2)
  53. else:
  54. pad_heigh = np.int(((image.shape[0] - kernel.shape[0])) / 2) + 1
  55. if (image.shape[1] - kernel.shape[1]) % 2 == 0:
  56. pad_width = np.int(((image.shape[1] - kernel.shape[1])) / 2)
  57. else:
  58. pad_width = np.int(((image.shape[1] - kernel.shape[1])) / 2) + 1
  59. pad_heigh_light = np.int(((image.shape[0] - kernel.shape[0])) / 2)
  60. pad_width_light = np.int(((image.shape[1] - kernel.shape[1])) / 2)
  61. kernel = np.pad(kernel, ((pad_heigh_light, pad_heigh), (pad_width_light, pad_width)), 'constant', constant_values=0)
  62. print("kernel.shape", kernel.shape)
  63. copy_fft2_image = np.zeros(image.shape)
  64. # fourier transform for kernel
  65. # shift the centre of kernel to axis origin and then do fourier transform
  66. fft2_kenel_after = np.fft.fft2(np.fft.fftshift(kernel))
  67. if len(image.shape) == 3:
  68. # fourier transform
  69. for i in range(image.shape[2]):
  70. image_fft = np.fft.fft2(image[:, :, i])
  71. # print("fft2_kenel_after * image_fft.shape ==== ", (fft2_kenel_after * image_fft).shape)
  72. # image_fft = np.fft.fftshift(np.fft.fft2(image[:, :, i]))
  73. # copy_fft2_image[:, :, i] = np.fft.ifftshift(np.fft.ifft2(fft2_kenel_after * image_fft))
  74. frequcy_result = fft2_kenel_after * image_fft
  75. # copy_fft2_image[:, :, i] = np.fft.fftshift(np.fft.ifft2(frequcy_result))
  76. copy_fft2_image[:, :, i] = np.fft.ifft2(frequcy_result)
  77. elif len(image.shape) == 2:
  78. image_fft = np.fft.fft2(image)
  79. frequcy_result = fft2_kenel_after * image_fft
  80. copy_fft2_image[:, :] = np.fft.ifft2(frequcy_result)
  81. return copy_fft2_image

参考博客

一文读懂图像信号中的高频和低频_流年若逝的博客-CSDN博客_信号的高频分量与低频分量

图像高频和低频_cys119的博客-CSDN博客_图像中的低频信号和高频信号

图像的高频信息和低频信息的含义_马鹏森的博客-CSDN博客_图像高频和低频对应图像的什么信息

图像中的高低频信息简单理解 - 知乎 (zhihu.com)

图像中的低频和高频 - 知乎 (zhihu.com)

计算机视觉之混合图像(Hybrid) - 知乎 (zhihu.com)

 图像处理之傅里叶变换 - 知乎 (zhihu.com)

图像傅里叶变换原理 python实现 - 我坚信阳光灿烂 - 博客园 (cnblogs.com)

如何理解图像的频率域处理? - 知乎 (zhihu.com)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/78432
推荐阅读
相关标签
  

闽ICP备14008679号