目的:
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竖直方向-50到206的像素
forjinrange(w-50): #取img水平方向-50到206的像素
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竖直方向-50到206的像素
forjinrange(w-50): #取img水平方向-50到206的像素
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--2行2列第一张
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--2行2列第一张
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模块作图。
原图傅里叶频谱与旋转后图像频谱的对应关系:图像的旋转会影响图像的频谱,原图旋转多少度,频谱就相应地旋转多少度。
注意几个图像傅里叶变换的步骤:
- 需要先获取最佳DFT变换的大小(cv.getOptimalDFTSize),然后以这个大小对原图进行扩充( padding,cv.copyMakeBorder)
- 需要DFT变换后的矩阵进行分解(cv.split),从中提取谱分量(cv.magnitude)
- 如果谱分量行列为奇数,需要对其进行裁剪成偶数(cv.Rect)
- 如果谱分量太大,需要对其进行对数变换(log),以便更好的显示
- 将傅里叶变换后图像的原点调整到中心