魏老师学生——Cecil:学习OpenCV-机器视觉之旅
- 用处:分析不同滤波器的频率特性。
- 2D离散傅里叶变化(DFT):分析图像的频域特性。
- 快速傅里叶变换(FFT):实现DFT的快速算法。
- 图像中,边界点或者噪声处的频率幅度变化大,是高频分量。
Numpy中的傅里叶变换
- FFT包:实现快速傅里叶变换。
- np.fft.fft2(灰度图像名,输出数组大小) ——解释:对信号进行频率转换,输出复杂的数组。
- np.fft.fftshift() ——解释:输出图像中左上角频率为0的部分(直流分量)移到中心。
代码演示
#coding=utf-8
import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('222.jpg',0)
f=np.fft.fft2(img)
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()
频域变换(高通滤波 重建图像)
- 60的矩形窗口对图像掩模,去除低频分量。
- np.fft.ifftshift() 逆平移操作。
- 直流分量位于左上角,np.ifft2() FFT逆变换。
- 得到 复杂数字,取绝对值。
代码演示
#coding=utf-8
import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('222.jpg',0)
f=np.fft.fft2(img)
fshift=np.fft.fftshift(f)
magnitude_spectrum=20*np.log(np.abs(fshift))
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.sfft2(f_ishift)
img_back=np.abs(img_back) #取绝对值
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.subplot(123),plt.imshow(img_back)
plt.title('result in jet'),plt.xticks([]),plt.yticks([])
plt.show()
- 高通滤波:边界检测操作。
OpenCV中的傅里叶变换
cv2.dft() cv2.idft() 双通道:第一个通道是结果的实数部分,第二个通道是结果的虚数部分。
输入图像:转换成np.float32格式。
cv2.cartToPolar() ——解释:返回幅度和相位。
代码演示
#coding=utf-8
import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('pingguo.jpg',0)
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()
代码演示
#coding=utf-8
import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('pingguo.jpg',0)
rows,cols=img.shape
crow,ccol=rows/2,cols/2
dft=cv2.dft(np.float32(img),flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift=np.fft.fftshift(dft)
mask=np.zeros((rows,cols,2),np.uint8)
mask[crow-10:crow+10,ccol-10:ccol+10]=1
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()
DFT性能优化
数组大小为2,3,5的指数时DFT效率很高。
修改输入图像的大小(补0),OpenCV手动补0,numpy自动补0。
cv2.getOptimalDFTSize() ——解释:确定最佳大小。
cv2.copyMakeBorder(img,0,bottom,0,right,bordertype,value=0) ——解释:改善数组大小。
拉普拉斯算子是高通滤波器
通过傅里叶变换得出结果。高通滤波器(HPF) 低通滤波器(LPF)
代码演示
#coding=utf-8
import cv2
import numpy as np
from matplotlib import pyplot as plt
mean_filter=np.ones((3,3))
x=cv2.getGaussianKernel(5,10) #生成一个高斯滤波器
gaussian=x*x.T #转置矩阵
scharr=np.array([[-3,0,3],
[-10,0,10],
[-3,0,3]]) # 不同边缘检测滤波器
sobel_x=np.array([[-1,0,1],
[-2,0,2],
[-1.0,1]])
sobel_y=np.array([[-1,-2,-1],
[0,0,0],
[1,2,1]])
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()