OpenCV图像变换之傅里叶变换的一些应用


Posted in Python onJuly 26, 2021

前言

这篇博客将介绍OpenCV中的图像变换,包括用Numpy、OpenCV计算图像的傅里叶变换,以及傅里叶变换的一些应用;

2D Discrete Fourier Transform (DFT)二维离散傅里叶变换
Fast Fourier Transform (FFT) 快速傅里叶变换

傅立叶变换用于分析各种滤波器的频率特性。对于图像采用二维离散傅立叶变换(DFT)求频域。一种称为快速傅立叶变换(FFT)的快速算法用于DFT的计算。

OpenCV使用cv2.dft()、cv2.idft() 实现傅里叶变换,效率更高一些(比OpenCV快3倍)

Numpy使用np.ifft2() 、np.fft.ifftshift() 实现傅里叶变换,使用更友好一些;

1. 效果图

灰度图 VS 傅里叶变换效果图如下:

可以看到白色区域大多在中心,显示低频率的内容比较多。

OpenCV图像变换之傅里叶变换的一些应用

傅里叶变换去掉低频内容后效果图如下:

可以看到使用矩形滤波后,效果并不好,有波纹的振铃效果;用高斯滤波能好点;

OpenCV图像变换之傅里叶变换的一些应用

傅里叶变换去掉高频内容后效果图如下:

删除图像中的高频内容,即将LPF应用于图像,它实际上模糊了图像。

OpenCV图像变换之傅里叶变换的一些应用

各滤波器是 HPF(High Pass Filter)还是 LPF(Low Pass Filter),一目了然:

拉普拉斯是高频滤波器;

OpenCV图像变换之傅里叶变换的一些应用

2. 原理

  • DFT的性能优化:在一定的阵列尺寸下,DFT计算的性能较好。当数组大小为2的幂时,速度最快。大小为2、3和5的乘积的数组也可以非常有效地处理。

为达到最佳性能,可以通过OpenCV提供的函数cv2.getOptimalDFTSize() 寻找最佳尺寸。
然后将图像填充成最佳性能大小的阵列,对于OpenCV,必须手动填充零。但是对于Numpy,可以指定FFT计算的新大小,会自动填充零。

通过使用最优阵列,基本能提升4倍的效率。而OpenCV本身比Numpy效率快近3倍;

拉普拉斯是高通滤波器(High Pass Filter)

3. 源码

3.1 Numpy实现傅里叶变换

# 傅里叶变换

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('ym3.jpg', 0)

# 使用Numpy实现傅里叶变换:fft包
# fft.fft2() 进行频率变换
# 参数1:输入图像的灰度图
# 参数2:>输入图像 用0填充;  <输入图像 剪切输入图像; 不传递 返回输入图像
f = np.fft.fft2(img)

# 一旦得到结果,零频率分量(直流分量)将出现在左上角。
# 如果要将其置于中心,则需要使用np.fft.fftshift()将结果在两个方向上移动。
# 一旦找到了频率变换,就能找到幅度谱。
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()

# 找到了频率变换,就可以进行高通滤波和重建图像,也就是求逆DFT
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.ifft2(f_ishift)
img_back = np.abs(img_back)

# 图像渐变章节学习到:高通滤波是一种边缘检测操作。这也表明大部分图像数据存在于频谱的低频区域。
# 仔细观察结果可以看到最后一张用JET颜色显示的图像,有一些瑕疵(它显示了一些波纹状的结构,这就是所谓的振铃效应。)
# 这是由于用矩形窗口mask造成的,掩码mask被转换为sinc形状,从而导致此问题。所以矩形窗口不用于过滤,更好的选择是高斯mask。)
plt.subplot(131), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(img_back, cmap='gray')
plt.title('Image after HPF'), plt.xticks([]), plt.yticks([])
plt.subplot(133), plt.imshow(img_back)
plt.title('Result in JET'), plt.xticks([]), plt.yticks([])

plt.show()

3.2 OpenCV实现傅里叶变换

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('ym3.jpg', 0)
rows, cols = img.shape
print(rows, cols)

# 计算DFT效率最佳的尺寸
nrows = cv2.getOptimalDFTSize(rows)
ncols = cv2.getOptimalDFTSize(cols)
print(nrows, ncols)

nimg = np.zeros((nrows, ncols))
nimg[:rows, :cols] = img
img = nimg

# OpenCV计算快速傅里叶变换,输入图像应首先转换为np.float32,然后使用函数cv2.dft()和cv2.idft()。
# 返回结果与Numpy相同,但有两个通道。第一个通道为有结果的实部,第二个通道为有结果的虚部。
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()

rows, cols = img.shape
crow, ccol = rows // 2, cols // 2

# 首先创建一个mask,中心正方形为1,其他均为0
# 如何删除图像中的高频内容,即我们将LPF应用于图像。它实际上模糊了图像。
# 为此首先创建一个在低频时具有高值的掩码,即传递LF内容,在HF区域为0。
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow - 30:crow + 30, ccol - 30:ccol + 30] = 1

# 应用掩码Mask和求逆DTF
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()

3.3 HPF or LPF?

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-x方向
scharr = np.array([[-3, 0, 3],
                   [-10, 0, 10],
                   [-3, 0, 3]])
# Sobel_x
sobel_x = np.array([[-1, 0, 1],
                    [-2, 0, 2],
                    [-1, 0, 1]])
# Sobel_y
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()

参考

  • https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/py_transforms/py_fourier_transform/py_fourier_transform.html#fourier-transform

总结

到此这篇关于OpenCV图像变换之傅里叶变换的文章就介绍到这了,更多相关OpenCV图像变换傅里叶变换内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python的shutil模块中文件的复制操作函数详解
Jul 05 Python
Python快速从注释生成文档的方法
Dec 26 Python
使用python画个小猪佩奇的示例代码
Jun 06 Python
PyQt打开保存对话框的方法和使用详解
Feb 27 Python
pyqt5 实现在别的窗口弹出进度条
Jun 18 Python
Django关于admin的使用技巧和知识点
Feb 10 Python
python操作yaml说明
Apr 08 Python
pandas读取csv文件提示不存在的解决方法及原因分析
Apr 21 Python
Python正则表达式高级使用方法汇总
Jun 18 Python
python中数字是否为可变类型
Jul 08 Python
Pycharm配置lua编译环境过程图解
Nov 28 Python
用python对excel进行操作(读,写,修改)
Dec 25 Python
Python类方法总结讲解
pandas数值排序的实现实例
Jul 25 #Python
python非标准时间的转换
Jul 25 #Python
OpenCV 图像梯度的实现方法
Jul 25 #Python
ROS系统将python包编译为可执行文件的简单步骤
Jul 25 #Python
Pandas自定义选项option设置
Jul 25 #Python
Pandas 稀疏数据结构的实现
Jul 25 #Python
You might like
php函数的常用方法及注意之处小结
2011/07/10 PHP
PHP将字符分解为多个字符串的方法
2014/11/22 PHP
php车辆违章查询数据示例
2016/10/14 PHP
微信第三方登录(原生)demo【必看篇】
2017/05/26 PHP
解决JS中乘法的浮点错误的方法
2014/01/03 Javascript
判断文档离浏览器顶部的距离的方法
2014/01/08 Javascript
Javascript中call与apply的学习笔记
2014/09/22 Javascript
jQuery动画出现连续触发、滞后反复执行的解决方法
2015/01/28 Javascript
jquery实现简单的自动播放幻灯片效果
2015/06/13 Javascript
AngularJS用户选择器指令实例分析
2016/11/04 Javascript
JS传播事件、取消事件默认行为、阻止事件传播详解
2017/08/14 Javascript
在React 组件中使用Echarts的示例代码
2017/11/08 Javascript
详解Vue开发微信H5微信分享签名失败问题解决方案
2018/08/09 Javascript
基于Vue实现平滑过渡的拖拽排序功能
2019/06/12 Javascript
帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
2019/08/23 Javascript
Vue 自定义指令功能完整实例
2019/09/17 Javascript
Vue页面切换和a链接的本质区别详解
2019/11/12 Javascript
vue-drag-chart 拖动/缩放图表组件的实例代码
2020/04/10 Javascript
JavaScript动画实例之粒子文本的实现方法详解
2020/07/28 Javascript
JS如何操作DOM基于表格动态展示数据
2020/10/15 Javascript
python查看FTP是否能连接成功的方法
2015/07/30 Python
django实现前后台交互实例
2017/08/07 Python
python3学习笔记之多进程分布式小例子
2018/02/13 Python
python 通过xml获取测试节点和属性的实例
2018/03/31 Python
python3下实现搜狗AI API的代码示例
2018/04/10 Python
python 动态调用函数实例解析
2019/10/21 Python
python常量折叠基础知识点讲解
2021/02/28 Python
前端面试必备之CSS3的新特性
2017/09/05 HTML / CSS
Anthropologie英国:美国家喻户晓的休闲服装和家居产品品牌
2018/12/05 全球购物
ShellScript面试题一则-ShellScript编程
2014/03/05 面试题
JVM是一个编译程序还是解释程序
2012/09/11 面试题
高中军训广播稿
2014/01/14 职场文书
区三好学生主要事迹
2014/01/30 职场文书
中学清明节活动总结
2014/07/04 职场文书
评奖评优个人先进事迹材料
2015/11/04 职场文书
win server2012 r2服务器共享文件夹如何设置
2022/06/21 Servers