OpenCV官方教程中文版 —— 傅里叶变换

OpenCV官方教程中文版 —— 傅里叶变换

  • 前言
  • 一、原理
  • 二、Numpy 中的傅里叶变换
  • 三、OpenCV 中的傅里叶变换
  • 四、为什么拉普拉斯算子是高通滤波器?

前言

本小节我们将要学习:

使用 OpenCV 对图像进行傅里叶变换

使用 Numpy 中 FFT(快速傅里叶变换)函数

傅里叶变换的一些用处

我们将要学习的函数有:cv2.dft(),cv2.idft() 等

一、原理

傅里叶变换经常被用来分析不同滤波器的频率特性。我们可以使用 2D 离散傅里叶变换 (DFT) 分析图像的频域特性。实现 DFT 的一个快速算法被称为快速傅里叶变换(FFT)。关于傅里叶变换的细节知识可以在任意一本图像处理或信号处理的书中找到。请查看本小节中更多资源部分。

对于一个正弦信号:x (t) = A sin (2πft), 它的频率为 f,如果把这个信号转到它的频域表示,我们会在频率 f 中看到一个峰值。如果我们的信号是由采样产生的离散信号好组成,我们会得到类似的频谱图,只不过前面是连续的,现在是离散。你可以把图像想象成沿着两个方向采集的信号。所以对图像同时进行 X 方向和 Y 方向的傅里叶变换,我们就会得到这幅图像的频域表示(频谱图)。

更直观一点,对于一个正弦信号,如果它的幅度变化非常快,我们可以说他是高频信号,如果变化非常慢,我们称之为低频信号。你可以把这种想法应用到图像中,图像那里的幅度变化非常大呢?边界点或者噪声。所以我们说边界和噪声是图像中的高频分量(注意这里的高频是指变化非常快,而非出现的次数多)。如果没有如此大的幅度变化我们称之为低频分量。

现在我们看看怎样进行傅里叶变换。

二、Numpy 中的傅里叶变换

首先我们看看如何使用 Numpy 进行傅里叶变换。Numpy 中的 FFT 包可以帮助我们实现快速傅里叶变换。函数 np.fft.fft2() 可以对信号进行频率转换,输出结果是一个复杂的数组。本函数的第一个参数是输入图像,要求是灰度格式。第二个参数是可选的, 决定输出数组的大小。输出数组的大小和输入图像大小一样。如果输出结果比输入图像大,输入图像就需要在进行 FFT 前补0。如果输出结果比输入图像小的话,输入图像就会被切割。

现在我们得到了结果,频率为 0 的部分(直流分量)在输出图像的左上角。如果想让它(直流分量)在输出图像的中心,我们还需要将结果沿两个方向平移 N/2 。函数 np.fft.fftshift() 可以帮助我们实现这一步。(这样更容易分析)。进行完频率变换之后,我们就可以构建振幅谱了。

# -*- coding: utf-8 -*-
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('ball.png', 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()

结果如下:

在这里插入图片描述
我们可以看到输出结果的中心部分更白(亮),这说明低频分量更多。

现在我们可以进行频域变换了,我们就可以在频域对图像进行一些操作了,例如高通滤波和重建图像(DFT 的逆变换)。比如我们可以使用一个60x60 的矩形窗口对图像进行掩模操作从而去除低频分量。然后再使用函数np.fft.ifftshift() 进行逆平移操作,所以现在直流分量又回到左上角了,左后使用函数 np.ifft2() 进行 FFT 逆变换。同样又得到一堆复杂的数字,我们可以对他们取绝对值:

rows, cols = img.shape
crow, ccol = int(rows / 2), int(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)
plt.figure()
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()

结果如下:
在这里插入图片描述
上图的结果显示高通滤波其实是一种边界检测操作。这就是我们在前面图像梯度那一章看到的。同时我们还发现图像中的大部分数据集中在频谱图的低频区域。我们现在已经知道如何使用 Numpy 进行 DFT 和 IDFT 了,接着我们来看看如何使用 OpenCV 进行这些操作。

如果你观察仔细的话,尤其是最后一章 JET 颜色的图像,你会看到一些不自然的东西(如我用红色箭头标出的区域)。看上图那里有些条带装的结构,这被成为振铃效应。这是由于我们使用矩形窗口做掩模造成的。这个掩模被转换成正弦形状时就会出现这个问题。所以一般我们不适用矩形窗口滤波。最好的选择是高斯窗口。

三、OpenCV 中的傅里叶变换

OpenCV 中相应的函数是 cv2.dft()cv2.idft()。和前面输出的结果一样,但是是双通道的。第一个通道是结果的实数部分,第二个通道是结果的虚数部分。输入图像要首先转换成 np.float32 格式。我们来看看如何操作。

plt.figure()
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()

在这里插入图片描述
现在我们来做逆 DFT。在前面的部分我们实现了一个 HPF(高通滤波),现在我们来做 LPF(低通滤波)将高频部分去除。其实就是对图像进行模糊操作。首先我们需要构建一个掩模,与低频区域对应的地方设置为 1, 与高频区域对应的地方设置为 0。

rows, cols = img.shape
crow, ccol = int(rows / 2), int(cols / 2)
# create a mask first, center square is 1, remaining all zeros
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1
# apply mask and inverse DFT
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.figure()
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()

在这里插入图片描述

四、为什么拉普拉斯算子是高通滤波器?

我在论坛中遇到了一个类似的问题。为什么拉普拉斯算子是高通滤波器?为什么 Sobel 是 HPF?等等。对于第一个问题的答案我们以傅里叶变换的形式给出。我们一起来对不同的算子进行傅里叶变换并分析它们:

# -*- coding: utf-8 -*-
import cv2
import numpy as np
from matplotlib import pyplot as pltmean_filter = np.ones((3, 3))  # simple averaging filter without scaling parameter
x = cv2.getGaussianKernel(5, 10)  # creating a guassian filter
gaussian = x * x.T  # x.T 为矩阵转置
# different edge detecting filters
scharr = np.array([[-3, 0, 3],[-10, 0, 10],[-3, 0, 3]])  # scharr in x-direction
sobel_x = np.array([[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]])  # sobel in x direction
sobel_y = np.array([[-1, -2, -1],[0, 0, 0],[1, 2, 1]])  # sobel in y direction
laplacian = np.array([[0, 1, 0],[1, -4, 1],[0, 1, 0]])  # laplacian
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 = [20 * 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()

在这里插入图片描述
从图像中我们就可以看出每一个算子允许通过那些信号。从这些信息中我们就可以知道那些是 HPF 那是 LPF。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/121353.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多线程线程池

线程安全问题 当多个线程同时操作同一个共享资源的时候,可能会出现结果不符合预期的问题 解决安全问题 方式一: 同步代码块 作用: 把访问共享资源的核心代码给上锁,以此保证线程安全 格式: synchronized(同步锁) { 访问共享资源的核心代…

unocss和tailwindcss css原子引擎

第一种tailwindcss: tailwindcss官网 https://tailwindcss.com/docs/grid-column 基本介绍及优点分析 Tailwind CSS 中文文档 - 无需离开您的HTML,即可快速建立现代网站 PostCss 处理 Tailwind Css 基本流程 PostCSS - 是一个用 JavaScript 工具和插…

67 内网安全-域横向smbwmi明文或hash传递

#知识点1: windows2012以上版本默认关闭wdigest,攻击者无法从内存中获取明文密码windows2012以下版本如安装KB2871997补丁,同样也会导致无法获取明文密码针对以上情况,我们提供了4种方式解决此类问题 1.利用哈希hash传递(pth,ptk等…

尚未解决:use_python()和use_virtualenv()的使用

reticulate包为Python和R之间的互操作性提供了一套全面的工具。该包包含以下功能: 以多种方式从R调用Python,包括RMarkdown、获取Python脚本、导入Python模块以及在R会话中交互使用Python。 R和Python对象之间的转换(例如,R和Pan…

2023年中国调音台产业链、产量及市场规模分析[图]

调音台是一种专业音频设备,用于混音、处理和控制音频信号。它通常用于音乐制作、现场演出、录音室以及广播等场景中。调音台允许用户调整不同声音来源的音频信号,使其在混音过程中达到理想的音质和平衡。调音台按信号出来方式可分为:模拟式调…

UVa10976 Fractions Again?!(分数拆分)

1、题目 2、题意 输入正整数 k k k,找到所有正整数 x ≥ y x \ge y x≥y,使得 1 k 1 x 1 y \frac{1}{k} \frac{1}{x} \frac{1}{y} k1​x1​y1​。 3、分析 既然要求找出所有的 x , y x,y x,y,枚举对象自然是 x , y x,y x,y了。可…

C# 基于腾讯云人脸核身和百度云证件识别技术相结合的 API 实现

目录 腾讯云人脸核身技术 Craneoffice.net 采用的识别方式 1、活体人脸核身(权威库): 2、活体人脸比对: 3、照片人脸核身(权威库): 调用成本 百度云身份证识别 调用成本 相关结合点 核心代码 实现调用人脸核身API的示例 实现调用身…

拓世大模型 | 立足行业所需,发力终端,缔造智能无限可能

蒸汽机的发明为人类工业革命揭开序幕,引领了近现代产业变革。众所周知,而今AI技术的革命性突破,站在了时代舞台的中心,特别是大模型的崛起,无疑是第四次产业革命的焦点,它的地位可与当年的“蒸汽机”相提并…

JAVA排序

目录 再看各种排序前我们先了解一下什么叫 稳定性 插入排序: 希尔排序:(插入排序的优化) 测试插入排序和希尔排序(插入排序的优化)排序时间对比 选择排序: 选择排序的优化: 正确的 选择排序优化 快速排序(挖坑法:未优化) 快速排序的优化1 快速排序优化2 优化快速排序…

server2012 通过防火墙开启局域网内限定IP进行远程桌面连接

我这里需要被远程桌面的电脑系统版本为windows server2012 1、打开允许远程连接设置 2、开启防火墙 3、设置允许“远程桌面应用”通过防火墙 勾选”远程桌面“ 3、入站规则设置 高级设置→入站规则→远程桌面-用户模式(TCP-In) 进入远程桌面属性的作用域——>远程IP地址—…

实体店做商城小程序如何

互联网电商深入各个行业,传统线下店商家无论产品销售还是服务业,仅靠以往的经营模式,很难拓展到客户,老客流失严重,同时渠道单一,无法实现外地客户购物及线上客户赋能等。 入驻第三方平台有优势但也有不足…

Spring Web MVC入门

一:了解Spring Web MVC (1)关于Java开发 🌟Java开发大多数场景是业务开发 比如说京东的业务就是电商卖货、今日头条的业务就推送新闻;快手的业务就是短视频推荐 (2)Spring Web MVC的简单理解 💗Spring Web MVC:如何使…

分布估计算法(Estimation of distribution algorithm,EDA)

概论 分布估计算法(Estimation of distribution algorithm,EDA)是一种新兴的基于统计学原理的随机优化算法。 为什么要叫这个名字呢? 首先,“分布”指的就是概率分布。 其次,“估计”指的是这个概率分布…

通过requests库使用HTTP编写的爬虫程序

使用Python的requests库可以方便地编写HTTP爬虫程序。以下是一个使用requests库的示例: import requests# 发送HTTP GET请求 response requests.get("http://example.com")# 检查响应状态码 if response.status_code 200:# 获取响应内容html response.…

Docker实战之二

一、前言 前一篇 Docker实战之一 我们介绍了Dokcer 镜像和容器基本概念,这一节我们来具体制作一个镜像文件并进行快速部署,这个镜像文件是我们的测试环境,主要包含JDK1.8、Nginx、Git、Node、Gradle,基础镜像为CentOS&#xff0c…

Java练习题2020-3

统计从1到N的整数中,所有立方值的平方根为整数的数的个数 输入说明&#xff1a;整数 N(N<10000)&#xff1b; 输出说明&#xff1a;符合条件的数的个数&#xff0c;如4^3648^2 输入样例&#xff1a;10 输出样例&#xff1a;3 (说明&#xff1a;样例中符合条件的3个数是1、4、…

用低代码平台代替Excel搭建进销存管理系统

目录 一、用低代码平台搭建系统 1.需求调研 2.基于痛点梳理业务流程 3.低代码实现 &#xff08;1&#xff09;基础资料模块 &#xff08;2&#xff09;采购管理模块 &#xff08;3&#xff09;销售管理模块 &#xff08;4&#xff09;库存管理模块 &#xff08;5&…

【点云】有序/无序点云区别(详细详解)

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

Windows server部署filebeat到kafka

需求&#xff1a;Windows dhcp日志需要实时传输到elk或者其他告警平台。 1、filebeat下载地址&#xff1a;https://www.elastic.co/cn/downloads/beats/filebeat 2、下载后解压后配置filebeat.yml文件&#xff0c; 3、README.md文件中有运行的操作方法&#xff1a;cmd上进入f…

为什么网上的流量卡都有禁发地区呢?流量卡管控地区整理!

在网上购买过流量卡的朋友应该都知道&#xff0c;但凡是运营商推出的大流量优惠套餐&#xff0c;在套餐详情中都是有禁发地区&#xff0c;只不过每张卡的禁发地区不同而已。 设置禁发地区的主要目的还是为了防止一些电信诈骗案件的发生&#xff0c;或者违法违规利用电话卡的情…