频域图像处理

 

目的:

1.掌握图像快速傅里叶变换及其实现

2.掌握图像二维频谱的分布特点

 

原理:

图像的快速傅里叶变换

傅里叶变换将信号分成不同频率成分,类似光学中的分色棱镜把白光按波长(频率)分成不同颜色,被称为数学棱镜。傅里叶变换的成分主要分为直流分量和交流分量。信号变换的快慢与频率域的频率有关。噪声、边缘、跳跃部分代表图像的高频分量;背景区域和慢变部分代表图像的低频分量。

二维离散傅里叶变换可分离为两个一维离散傅里叶变换。

 

傅里叶变换频谱图像

一句话解释为: 二维频谱中的每一个点都是一个与之一 一对应的二维正弦/余弦波。

在经过频谱居中后的频谱中,中间最亮的点是最低频率,属于直流分量(DC分量)。越往边外走,频率越高,所以频谱图中的四个角和X,Y轴的尽头都是高频分量。

未经过处理的频谱图,四个角对应低频成分,中央部分对应高频成分,图像亮条的平移影响频谱的分布;但当频谱搬移到中心时,图像亮条的平移前后所导致的频谱图是相同的。图像旋转,频谱也会旋转,并且角度相同。

频谱具有平移特性,可分离性。

 

内容或步骤:

1.对一张图像进行平移,显示原始图像和处理后的图像;

 

代码:

importcv2
importnumpyasnp

defmain():
    img=cv2.imread(
r'.\lena.jpg')         #读取lena.jpg
   
imgInfo=img.shape                     #获取和img相同的属性值
   h=imgInfo[0]                          #竖直方向的像素
   w=imgInfo[1]                          #水平方向的像素
   img_changed=np.zeros(imgInfo,np.uint8)#np.uint8的数据类型构造一个像img的矩阵
   foriinrange(h-50):                 #img竖直方向-50206的像素
       forjinrange(w-50):             #img水平方向-50206的像素
           img_changed[i+50,j+50]=img[i,j]#赋予矩阵像素值
                                           #不存在的部分python用黑色像素表示
   cv2.imshow("orignal",img)             #显示
   cv2.imshow("changed",img_changed)
    cv2.waitKey(
0)

if__name__=='__main__':
    main()

 

思路与讨论:

先cv2.imread()读取,然后利用numpy模块构造一个和原图像大小相同的矩阵,在for循环中设定要进行的平移操作后,赋予矩阵像素值,之后利用cv2.imshow()显示即可。

 

 

 

2.分别对两幅图像进行傅里叶变换,显示变换后的结果,分析原图傅里叶频谱与平移后图像频谱的对应关系;

 

代码:

importnumpyasnp
importcv2
frommatplotlibimportpyplotasplt

defmain():
    img=cv2.imread(
r'.\lena.jpg',0)       #读取lena.jpg
   
imgInfo=img.shape                     #获取和img相同的属性值
   h=imgInfo[0]                          #竖直方向的像素
   w=imgInfo[1]                          #水平方向的像素
   img_changed=np.zeros(imgInfo,np.uint8)#np.uint8的数据类型构造一个像img的矩阵
   foriinrange(h-50):                 #img竖直方向-50206的像素
       forjinrange(w-50):             #img水平方向-50206的像素
           img_changed[i+50,j+50]=img[i,j]#赋予矩阵像素值
                                           #不存在的部分python用黑色像素表示
   img1=np.float32(img);                 #np.int8类型转化为float32
   
img2=np.float32(img_changed)
    img1f=cv2.dft(img1,
flags=cv2.DFT_COMPLEX_OUTPUT)#使用cv2.dft进行傅里叶变化
   img2f=cv2.dft(img2,flags=cv2.DFT_COMPLEX_OUTPUT)
    img1ff=np.fft.fftshift(img1f)         
#使用np.fft.shiftfft()将变化后的图像的低频转移到中心位置
   img2ff=np.fft.fftshift(img2f)
   
   
#使用cv2.magnitude将实部和虚部转换为实部,乘以20是为了使得结果更大
   magnitude_spectrum1=20*np.log(cv2.magnitude(img1ff[:, :,0], img1ff[:, :,1]))
    magnitude_spectrum2=
20*np.log(cv2.magnitude(img2ff[:, :,0], img2ff[:, :,1]))
   
   
#利用plt模块作图221--22列第一张
   plt.subplot(221), plt.imshow(img)
    plt.title(
'img1'),plt.xticks([]),plt.yticks([])
    plt.subplot(
222), plt.imshow(img_changed)
    plt.title(
'img2'),plt.xticks([]),plt.yticks([])
    plt.subplot(
223), plt.imshow(magnitude_spectrum1)
    plt.title(
'magnitude_spectrum1'), plt.xticks([]), plt.yticks([])
    plt.subplot(
224), plt.imshow(magnitude_spectrum2)
    plt.title(
'magnitude_spectrum1'), plt.xticks([]), plt.yticks([])
    plt.show()


if__name__=="__main__":
    main()

 

思路与讨论:

在(1)的基础上,先用np.float32对图像做类型转换,然后利用cv2.dft()对转换后的图像做傅里叶变换,变换后利用np.fft.shiftfft()将图像的低频转移到中心位置,然后利用cv2.magnitude()将实部和虚部转换为实部,选择合适的参数使结果更明显,此处选了20。最后利用plt模块作图。

 

原图傅里叶频谱与平移后图像频谱的对应关系:未经过处理的频谱图,图像亮条的平移影响频谱的分布,但当频谱搬移到中心时,图像亮条的平移所导致的前后频谱图是相同的。

 

 

3.对rectangular.jpg及其旋转图rectangular-rotation.jpg分别进行傅里叶变换,显示变换后的结果,分析原图傅里叶频谱与旋转后图像频谱的对应关系。

 

代码:

importnumpyasnp
importcv2
frommatplotlibimportpyplotasplt

defmain():
    imgone=cv2.imread(
r'.\rectangular.jpg',0)       #读取图像
   imgtwo=cv2.imread(r'.\rectangular_rotation.jpg',0)
    img1=np.float32(imgone)                 
#np.int8类型转化为float32
   
img2=np.float32(imgtwo)

    img1f=cv2.dft(img1,
flags=cv2.DFT_COMPLEX_OUTPUT)#使用cv2.dft进行傅里叶变化
   img2f=cv2.dft(img2,flags=cv2.DFT_COMPLEX_OUTPUT)
    img1ff=np.fft.fftshift(img1f)         
#使用np.fft.shiftfft()将变化后的图像的低频转移到中心位置
   img2ff=np.fft.fftshift(img2f)

   
#使用cv2.magnitude将实部和虚部转换为实部,乘以20是为了使得结果更明显
   magnitude_spectrum1=20*np.log(cv2.magnitude(img1ff[:, :,0], img1ff[:, :,1]))
    magnitude_spectrum2=
20*np.log(cv2.magnitude(img2ff[:, :,0], img2ff[:, :,1]))

   
#利用plt模块作图221--22列第一张
   plt.subplot(221), plt.imshow(imgone)
    plt.title(
'img1'),plt.xticks([]),plt.yticks([])
    plt.subplot(
222), plt.imshow(imgtwo)
    plt.title(
'img2'),plt.xticks([]),plt.yticks([])
    plt.subplot(
223), plt.imshow(magnitude_spectrum1)
    plt.title(
'magnitude_spectrum1'), plt.xticks([]), plt.yticks([])
    plt.subplot(
224), plt.imshow(magnitude_spectrum2)
    plt.title(
'magnitude_spectrum1'), plt.xticks([]), plt.yticks([])
    plt.show()


if__name__=="__main__":
    main()

 

思路与讨论:

和(2)的操作类似,先用np.float32对图像做类型转换,然后利用cv2.dft()对转换后的图像做傅里叶变换,变换后利用np.fft.shiftfft()将图像的低频转移到中心位置,然后利用cv2.magnitude()将实部和虚部转换为实部,选择合适的参数使结果更明显,依旧选了20。最后利用plt模块作图。

 

原图傅里叶频谱与旋转后图像频谱的对应关系:图像的旋转会影响图像的频谱,原图旋转多少度,频谱就相应地旋转多少度。

 

 

注意几个图像傅里叶变换的步骤:

  1. 需要先获取最佳DFT变换的大小(cv.getOptimalDFTSize),然后以这个大小对原图进行扩充( padding,cv.copyMakeBorder)
  2. 需要DFT变换后的矩阵进行分解(cv.split),从中提取谱分量(cv.magnitude)
  3. 如果谱分量行列为奇数,需要对其进行裁剪成偶数(cv.Rect)
  4. 如果谱分量太大,需要对其进行对数变换(log),以便更好的显示
  5. 将傅里叶变换后图像的原点调整到中心

 

 


版权声明:本文为weixin_42760462原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。