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 urlopen()函数 示例分享
Jun 12 Python
零基础写python爬虫之HTTP异常处理
Nov 05 Python
Python自定义进程池实例分析【生产者、消费者模型问题】
Sep 19 Python
Python使用defaultdict读取文件各列的方法
May 11 Python
python Pygame的具体使用讲解
Nov 03 Python
python微信跳一跳系列之自动计算跳一跳距离
Feb 26 Python
selenium+python 去除启动的黑色cmd窗口方法
May 22 Python
python调用opencv实现猫脸检测功能
Jan 15 Python
Scrapy框架爬取Boss直聘网Python职位信息的源码
Feb 22 Python
python matplotlib 画dataframe的时间序列图实例
Nov 20 Python
python GUI库图形界面开发之PyQt5状态栏控件QStatusBar详细使用方法实例
Feb 28 Python
python中翻译功能translate模块实现方法
Dec 17 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
利用谷歌 Translate API制作自己的翻译脚本
2014/06/04 PHP
PHP实现QQ、微信和支付宝三合一收款码实例代码
2018/02/19 PHP
javascript中的对象和数组的应用技巧
2007/01/07 Javascript
写js时遇到的一些小问题
2010/12/06 Javascript
javascript实现修改微信分享的标题内容等
2014/12/11 Javascript
javascript实现动态导入js与css等静态资源文件的方法
2015/07/25 Javascript
Bootstrap编写一个同时适用于PC、平板、手机的登陆页面
2016/06/30 Javascript
浅析使用BootStrap TreeView插件实现灵活配置快递模板
2016/11/28 Javascript
微信小程序 scroll-view隐藏滚动条详解
2017/01/16 Javascript
vue 中swiper的使用教程
2018/05/22 Javascript
JS函数动态传递参数的方法分析【基于arguments对象】
2019/06/05 Javascript
微信小程序webview组件交互,内联h5页面并网页实现微信支付实现解析
2019/08/16 Javascript
vue-cli打包后本地运行dist文件中的index.html操作
2020/08/12 Javascript
Vue过滤器,生命周期函数和vue-resource简单介绍
2021/01/12 Vue.js
[03:00]2014DOTA2国际邀请赛 Titan淘汰潸然泪下Ohaiyo专访
2014/07/15 DOTA
详细介绍Python函数中的默认参数
2015/03/30 Python
浅谈Python程序与C++程序的联合使用
2015/04/07 Python
pandas对指定列进行填充的方法
2018/04/11 Python
django允许外部访问的实例讲解
2018/05/14 Python
对Python 3.5拼接列表的新语法详解
2018/11/08 Python
WIn10+Anaconda环境下安装PyTorch(避坑指南)
2019/01/30 Python
Django 中间键和上下文处理器的使用
2019/03/17 Python
Python实现ATM系统
2020/02/17 Python
python中的列表和元组区别分析
2020/12/30 Python
使用Python制作一个数据预处理小工具(多种操作一键完成)
2021/02/07 Python
馥绿德雅美国官方网站:Rene Furterer头皮护理专家
2019/05/01 全球购物
瑞典在互联网上最大的宠物商店:Animail
2020/10/31 全球购物
Java的接口和C++的虚类的相同和不同处
2014/03/27 面试题
AJax面试题
2014/11/25 面试题
《狼和小羊》教学反思
2014/04/20 职场文书
硕士毕业论文导师评语
2014/12/31 职场文书
导游欢送词
2015/01/31 职场文书
2015政治思想表现评语
2015/03/25 职场文书
golang gopm get -g -v 无法获取第三方库的解决方案
2021/05/05 Golang
多线程Spring通过@Scheduled实现定时任务
2022/05/25 Java/Android
Redis配置外网可访问(redis远程连接不上)的方法
2022/12/24 Redis