opencv-python傅里叶变换
一、图像傅里叶变换
二维傅里叶变换原理
灰度图像是由二维的离散的点构成的。二维离散傅里叶变换(Two-Dimensional Discrete Fourier Transform)常用于图像处理中,对图像进行傅里叶变换后得到其频谱图。频谱图中频率高低表征图像中灰度变化的剧烈程度。图像中边缘和噪声往往是高频信号,而图像背景往往是低频信号。我们在频率域内可以很方便地对图像的高频或低频信息进行操作,完成图像去噪,图像增强,图像边缘提取等操作。
其中H,W分别为图像的高、宽,F(u,v)表示频域图像,f(x,y)表示时域图像(某点的像素),u范围为[0,H−1],v范围为[0,W−1]其中H,W分别为图像的高、宽,F(u,v)表示频域图像,f(x,y)表示时域图像(某点的像素),u范围为[0,H-1],v范围为[0,W-1] 其中H,W分别为图像的高、宽,F(u,v)表示频域图像,f(x,y)表示时域图像(某点的像素),u范围为[0,H−1],v范围为[0,W−1]
自定义图像傅里叶变换功能函数
1、自定义傅里叶变换函数
#自定义傅里叶变换功能函数def dft(img):#获取图像属性H,W,channel=img.shape#定义频域图,从公式可以看出为求出结果为复数,因此,需要定义为复数矩阵F = np.zeros((H, W,channel), dtype=plex)# 准备与原始图像位置相对应的处理索引x = np.tile(np.arange(W), (H, 1))y = np.arange(H).repeat(W).reshape(H, -1)#通过公式遍历for c in range(channel):#对彩色的3通道数进行遍历for u in range(H):for v in range(W):F[u, v, c] = np.sum(img[..., c] * np.exp(-2j * np.pi * (x * u / W + y * v / H))) / np.sqrt(H * W)return F
2、读取图像,进行傅里叶变化并显示变换后的结果
gray=cv2_imread("C://Users//小白二号//Desktop//dd.png",1)gray=cv2.resize(gray,(400,400))img_dft = dft(gray)dft_shift = np.fft.fftshift(img_dft)fimg = np.log(np.abs(dft_shift))cv2.imshow("fimg", fimg)cv2.imshow("gray", gray)cv2.waitKey(0)cv2.destroyAllWindows()
opencv库函数实现傅里叶变换
(1)傅里叶变换函数cv2.dft()
函数原型如下:
img=cv2.dft(src, flags=None, nonzeroRows=None)
src表示输入图像,需要通过np.float32转换格式
flag表示转换标记,其中cv2.DFT _INVERSE执行反向一维或二维转换,而不是默认的正向转换;cv2.DFT _SCALE表示缩放结果,由阵列元素的数量除以它;cv2.DFT _ROWS执行正向或反向变换输入矩阵的每个单独的行,该标志可以同时转换多个矢量,并可用于减少开销以执行3D和更高维度的转换等;cv2.DFT _COMPLEX_OUTPUT执行1D或2D实数组的正向转换,这是最快的选择,默认功能;cv2.DFT _REAL_OUTPUT执行一维或二维复数阵列的逆变换,结果通常是相同大小的复数数组,但如果输入数组具有共轭复数对称性,则输出为真实数组。
nonzeroRows表示当参数不为零时,函数假定只有nonzeroRows输入数组的第一行(未设置)或者只有输出数组的第一个(设置)包含非零,因此函数可以处理其余的行更有效率,并节省一些时间;这种技术对计算阵列互相关或使用DFT卷积非常有用。
(2)复数求模函数cv2.magnitude()
由于输出的频谱结果是一个复数,需要调用cv2.magnitude()函数将傅里叶变换的双通道结果转换为0到255的范围,函数原型如下:
result=cv2.magnitude(x, y)
x表示浮点型X坐标值,即实部
y表示浮点型Y坐标值,即虚部
最终结果为复数的模
(3)应用实例
def cv2_imread(file_path, flag=1):#读取图片数据return cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), flag)gray=cv2_imread("C://Users//小白二号//Desktop//壁纸2.png",1)gray=cv2.cvtColor(gray,cv2.COLOR_BGR2GRAY)gray=cv2.resize(gray,(640,420))np.float32(gray)img_dft = cv2.dft(np.float32(gray),flags=cv2.DFT_COMPLEX_OUTPUT)dft_shift = np.fft.fftshift(img_dft)fimg = 20 * np.log(cv2.magnitude(dft_shift[:, :, 1], dft_shift[:, :, 0]))plt.subplot(121), plt.imshow(gray,'gray'), plt.title('原图像')plt.axis('off')plt.subplot(122), plt.imshow(np.int8(fimg),'gray'), plt.title('傅里叶变换')plt.axis('off')plt.show()cv2.waitKey(0)cv2.destroyAllWindows()
运行结果:
二、图像傅里叶逆变换
二维傅里叶逆变换原理
傅里叶反变换原理就是将图像频域还原为图像时域,具体原理公式如下所示:
其中H,W分别为图像的高、宽,F(u,v)表示频域图像,f(x,y)表示时域图像(某点的像素),x范围为[0,H−1],y范围为[0,W−1]其中H,W分别为图像的高、宽,F(u,v)表示频域图像,f(x,y)表示时域图像(某点的像素),x范围为[0,H-1],y范围为[0,W-1] 其中H,W分别为图像的高、宽,F(u,v)表示频域图像,f(x,y)表示时域图像(某点的像素),x范围为[0,H−1],y范围为[0,W−1]
自定义傅里叶逆变换功能函数
自定义功能函数具体如下:
def idft(G):H, W, channel = G.shape#定义空白时域图像out = np.zeros((H, W, channel), dtype=np.float32)# 准备与原始图像位置相对应的处理索引x = np.tile(np.arange(W), (H, 1))y = np.arange(H).repeat(W).reshape(H, -1)#通过公式遍历for c in range(channel):for u in range(H):for v in range(W):out[u, v, c] = np.abs(np.sum(G[..., c] * np.exp(2j * np.pi * (x * u / W + y * v / H)))) / np.sqrt(W * H)# 剪裁out = np.clip(out, 0, 255)out = out.astype(np.uint8)return out
OpenCV库函数实现傅里叶逆变换
(1)傅里叶逆变换函数
opencv能实现傅里叶逆变换的函数是cv2.idft(),函数原型如下:
img=cv2.idft(src,flags,nonzeroRows)
src表示输入图像,包括实数或复数
flags表示转换标记
nonzeroRows表示要处理的图片行数,其余行的内容未定义
(2)应用实例
def cv2_imread(file_path, flag=1):# 读取图片数据return cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), flag)gray = cv2_imread("C://Users//小白二号//Desktop//壁纸2.png", 1)gray = cv2.cvtColor(gray, cv2.COLOR_BGR2GRAY)gray = cv2.resize(gray, (640, 420))# 傅里叶变换img_dft = cv2.dft(np.float32(gray), flags=cv2.DFT_COMPLEX_OUTPUT)dft_shift = np.fft.fftshift(img_dft)# 将频域从左上角移动到中间fimg = 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))# 傅里叶逆变换idft_shift = np.fft.ifftshift(dft_shift) # 将频域从中间移动到左上角ifimg = cv2.idft(idft_shift)#傅里叶库函数调用ifimg = 20*np.log(cv2.magnitude(ifimg[:, :, 0], ifimg[:, :, 1]))#转化为0-255ifimg=np.abs(ifimg)# 绘制图片plt.subplot(131), plt.imshow(gray, 'gray'), plt.title('原图像')plt.axis('off')plt.subplot(132), plt.imshow(np.int8(fimg), 'gray'), plt.title('傅里叶变换')plt.axis('off')plt.subplot(133), plt.imshow(np.int8(ifimg), 'gray'), plt.title('傅里叶逆变换')plt.show()cv2.waitKey(0)cv2.destroyAllWindows()
运行结果: