离散傅里叶变换

news2024/11/28 20:58:50

目标

我们将寻求以下问题的答案:

  • 什么是傅里叶变换,为什么要使用它?
  • 如何在OpenCV中做到这一点?
  • 使用以下函数:copyMakeBorder() , merge() , dft() , getOptimalDFTSize() , log() 和 normalize****()

源代码 C++爪哇岛蟒

您可以从此处下载它,也可以在 OpenCV 源代码库中找到它。samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp

下面是 dft() 的用法示例:

#include “opencv2/core.hpp”

#include“opencv2/imgproc.hpp”

#include“opencv2/imgcodecs.hpp”

#include“opencv2/highgui.hpp”

#include < iostream>

使用命名空间 CV;

使用命名空间 std;

静态无效帮助(char ** argv)

{

cout << endl

​ << “该程序演示了离散傅里叶变换(DFT)的使用。<< endl

​ << “拍摄图像的 dft 并显示其功率谱。”<< endl << endl

​ << “用法:” << endl

<< argv[0] << “ [image_name – default lena.jpg]” << endl << endl;

}

int main(int argc, char ** argv)

{

帮助(argv);

​ const char* 文件名 = argc >=2 ?argv[1] : “lena.jpg”;

​ 席I = imread( samples::findFile( 文件名 ), IMREAD_GRAYSCALE);

​ if( I.空()){

cout << “打开图像时出错” << endl;

​ 返回EXIT_FAILURE;

​ }

​ 垫子衬垫;将输入图像放大到最佳大小

​ int m = getOptimalDFTSize( I.rows );

​ int n = getOptimalDFTSize( I.cols );在边框上添加零值

​ copyMakeBorder(I, 填充, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, 标量::all(0));

​ 垫子平面[] = {Mat_(padded), Mat::zeros(padded.size()、CV_32F)};

​ 垫复合物I;

​ merge(planes, 2, complexI);将另一个带有零的平面添加到展开的平面

​ dft(复合物I,复合物I);这样,结果可以适合源矩阵

​ 计算幅度并切换到对数刻度

​ => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))

​ split(complexI, 平面);// planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))

​ 幅度(planes[0], planes[1], planes[0]);// planes[0] = magnitude

​ 垫子 magI = 平面[0];

magI += 标量::all(1);切换到对数刻度

​ 日志(magI, magI);

​ 裁剪光谱,如果它有奇数行或列数

magI = magI(Rect(0, 0, magI.cols & -2, magI.行 & -2));

​ 重新排列傅里叶图像的象限,使原点位于图像中心

​ int cx = magI。cols/2;

​ int cy = magI。行/2;

​ 垫 q0(magI, Rect(0, 0, cx, cy));左上角 - 创建每个象限的投资回报率

​ 垫 q1(magI, Rect(cx, 0, cx, cy));// 右上角

​ 垫 q2(magI, Rect(0, cy, cx, cy));左下角

​ 垫子 q3(magI, Rect(cx, cy, cx, cy));右下角

​ 垫子tmp;交换象限(左上角和右下角)

问题0.copyTo(tmp);

q3.copyTo(q0);

TMP的。copyTo(q3);

q1.copyTo(tmp);交换象限(右上角和左下角)

q2.copyTo(q1);

TMP的。copyTo(q2);

​ 归一化(magI, magI, 0, 1, NORM_MINMAX);将带有浮点值的矩阵转换为

​ 可查看的图像形式(在值 0 和 1 之间浮动)。

​ imshow(“输入图像” , I );显示结果

​ imshow(“频谱幅度”, magI);

​ 等待键();

​ 返回EXIT_SUCCESS;

}

解释 C++爪哇岛蟒

傅里叶变换会将图像分解为正弦和余弦分量。换句话说,它将图像从其空间域转换为其频域。这个想法是,任何函数都可以用无限正弦和余弦函数的总和精确近似。傅里叶变换是一种如何做到这一点的方法。在数学上,二维图像傅里叶变换为:

F(k,l)=∑i=0N−1∑j=0N−1f(i,j)e−i2π(kiN+ljN)

e我x=COSX+ISINX

这里 f 是其空间域中的图像值,F 是其频域中的图像值。变换的结果是复数。可以通过真实图像和复杂图像或通过星等相位图像来显示这一点。然而,在整个图像处理算法中,只有量级图像是有趣的,因为它包含我们需要的有关图像几何结构的所有信息。但是,如果您打算以这些形式对图像进行一些修改,然后需要重新转换它,则需要保留这两种形式。

在此示例中,我将演示如何计算和显示傅里叶变换的幅度图像。在数字图像的情况下是离散的。这意味着它们可能会占用给定域值中的值。例如,在基本灰度中,图像值通常介于 0 和 255 之间。因此,傅里叶变换也需要是离散类型,从而产生离散傅里叶变换 (DFT)。每当您需要从几何角度确定图像的结构时,您都需要使用它。以下是要遵循的步骤(如果是灰度输入图像 I):

将图像扩展到最佳大小

DFT 的性能取决于图像大小。对于数字 2、3 和 5 的倍数的图像大小,它往往是最快的。因此,为了实现最佳性能,通常最好将边框值填充到图像上,以获得具有此类特征的大小。getOptimalDFTSize() 返回这个最佳大小,我们可以使用 copyMakeBorder() 函数来扩展图像的边框(附加的像素初始化为零):

垫子衬垫;将输入图像放大到最佳大小

​ int m = getOptimalDFTSize( I.rows );

​ int n = getOptimalDFTSize( I.cols );在边框上添加零值

​ copyMakeBorder(I, 填充, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));

为复杂和真实的价值腾出空间

傅里叶变换的结果很复杂。这意味着对于每个图像值,结果是两个图像值(每个组件一个)。此外,频域范围远大于其空间对应范围。因此,我们通常至少以浮点格式存储这些内容。因此,我们将输入图像转换为此类型,并使用另一个通道对其进行扩展以保存复数值:

垫子平面[] = {Mat_(padded), Mat::zeros(padded.size(), CV_32F)};

垫复合物I;

​ merge(planes, 2, complexI);将另一个带有零的平面添加到展开的平面

进行离散傅里叶变换

可以进行就地计算(输入与输出相同):

​ dft(复合物I,复合物I);这样,结果可以适合源矩阵

将实数值和复数值转换为量级

复数有一个实数 (Re) 和一个复数 (虚数 - Im) 部分。DFT 的结果是复数。DFT 的大小为:

M=Re(DFT(我))2+我m(DFT(我))2−−−−−−−−−−−−−−−−−−−−−−−−√2

转换为 OpenCV 代码:

​ split(complexI, 平面);// planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))

​ 幅度(planes[0], planes[1], planes[0]);// planes[0] = magnitude

垫子 magI = 平面[0];

切换到对数刻度

事实证明,傅里叶系数的动态范围太大,无法显示在屏幕上。我们有一些小的和一些高变化的值,我们不能像这样观察到。因此,高值将全部显示为白点,而小值将显示为黑点。为了使用灰度值进行可视化,我们可以将线性刻度转换为对数刻度:

M1=日志(1+M)

转换为 OpenCV 代码:

magI += 标量::all(1);切换到对数刻度

​ 日志(magI, magI);

裁剪和重新排列

还记得,在第一步,我们扩展了图像吗?好吧,是时候扔掉新引入的价值观了。出于可视化目的,我们还可以重新排列结果的象限,使原点(零,零)与图像中心相对应。

​ 裁剪光谱,如果它有奇数行或列数

magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2));

​ 重新排列傅里叶图像的象限,使原点位于图像中心

​ int cx = magI.cols/2;

​ int cy = magI.rows/2;

垫 q0(magI, Rect(0, 0, cx, cy));左上角 - 创建每个象限的投资回报率

垫 q1(magI, Rect(cx, 0, cx, cy));// 右上角

垫 q2(magI, Rect(0, cy, cx, cy));左下角

垫子 q3(magI, Rect(cx, cy, cx, cy));右下角

垫子tmp;交换象限(左上角和右下角)

q0.copyTo(tmp);

q3.copyTo(q0);

tmp.copyTo(q3);

q1.copyTo(tmp);交换象限(右上角和左下角)

q2.copyTo(q1);

tmp.copyTo(q2);

正常化

出于可视化目的,再次执行此操作。我们现在有了幅度,但这仍然超出了我们0到1的图像显示范围。我们使用 cv::normalize() 函数将我们的值归一化到这个范围。

​ 归一化(magI, magI, 0, 1, NORM_MINMAX);将带有浮点值的矩阵转换为

​ 可查看的图像形式(在值 0 和 1 之间浮动)。

结果

一个应用思路是确定图像中存在的几何方向。例如,让我们找出文本是否是水平的?看一些文本,你会注意到文本线也形成了水平线,字母形成了垂直线。在傅里叶变换的情况下,也可以看到文本片段的这两个主要组成部分。让我们使用这个关于文本的水平和旋转图像。

如果是水平文本:

result_normal.jpg

如果是旋转文本:

result_rotated.jpg

您可以看到,频域中影响最大的分量(幅度图像上最亮的点)遵循图像上物体的几何旋转。由此,我们可以计算偏移量并执行图像旋转以纠正最终的未对齐。

在线教程

  • 麻省理工学院人工智能视频教程 – 麻省理工人工智能课程
  • 人工智能入门 – 人工智能基础学习。Peter Norvig举办的课程
  • EdX 人工智能 – 此课程讲授人工智能计算机系统设计的基本概念和技术。
  • 人工智能中的计划 – 计划是人工智能系统的基础部分之一。在这个课程中,你将会学习到让机器人执行一系列动作所需要的基本算法。
  • 机器人人工智能 – 这个课程将会教授你实现人工智能的基本方法,包括:概率推算,计划和搜索,本地化,跟踪和控制,全部都是围绕有关机器人设计。
  • 机器学习 – 有指导和无指导情况下的基本机器学习算法
  • 机器学习中的神经网络 – 智能神经网络上的算法和实践经验
  • 斯坦福统计学习
    有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓

请添加图片描述

人工智能书籍

  • OpenCV(中文版).(布拉德斯基等)
  • OpenCV+3计算机视觉++Python语言实现+第二版
  • OpenCV3编程入门 毛星云编著
  • 数字图像处理_第三版
  • 人工智能:一种现代的方法
  • 深度学习面试宝典
  • 深度学习之PyTorch物体检测实战
  • 吴恩达DeepLearning.ai中文版笔记
  • 计算机视觉中的多视图几何
  • PyTorch-官方推荐教程-英文版
  • 《神经网络与深度学习》(邱锡鹏-20191121)

  • 在这里插入图片描述

第一阶段:零基础入门(3-6个月)

新手应首先通过少而精的学习,看到全景图,建立大局观。 通过完成小实验,建立信心,才能避免“从入门到放弃”的尴尬。因此,第一阶段只推荐4本最必要的书(而且这些书到了第二、三阶段也能继续用),入门以后,在后续学习中再“哪里不会补哪里”即可。

第二阶段:基础进阶(3-6个月)

熟读《机器学习算法的数学解析与Python实现》并动手实践后,你已经对机器学习有了基本的了解,不再是小白了。这时可以开始触类旁通,学习热门技术,加强实践水平。在深入学习的同时,也可以探索自己感兴趣的方向,为求职面试打好基础。

第三阶段:工作应用

这一阶段你已经不再需要引导,只需要一些推荐书目。如果你从入门时就确认了未来的工作方向,可以在第二阶段就提前阅读相关入门书籍(对应“商业落地五大方向”中的前两本),然后再“哪里不会补哪里”。

有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓

在这里插入图片描述

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

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

相关文章

蓝桥杯:C++排列与组合

排列是暴力枚举时的常见操作。有以下两种情况。 C的 next_permutation()是全排列函数&#xff0c;只能输出序列中所有元素的全排列。 本节将给出手写排列和组合的代码。因为在很多场合中不能使用系统自带的排列函数&#xff0c;所以需要自己编写。 全排列函数&#xff1a;nex…

Lag-Llama:第一个时间序列预测的开源基础模型介绍和性能测试

2023年10月&#xff0c;我们发表了一篇关于TimeGPT的文章&#xff0c;TimeGPT是时间序列预测的第一个基础模型之一&#xff0c;具有零样本推理、异常检测和共形预测能力。 虽然TimeGPT是一个专有模型&#xff0c;只能通过API访问。但是它还是引发了对时间序列基础模型的更多研…

读十堂极简人工智能课笔记03_遗传算法与进化

1. 寻找正确答案 1.1. 卡尔西姆斯 1.1.1. 计算机图形艺术家和研究者 1.1.2. 演示过数字进化之创造性和新颖性的先驱 1.1.3. 1994年 1.1.3.1. 创造一批能游泳、走路、跳跃&#xff0c;甚至互相竞争的虚拟动物震惊了整个科学界 1.1.3.2. 它们的人工大脑却是个极其复杂的网络…

公需课考试怎么搜题找答案?推荐你使用这5个公众号和工具 #知识分享#其他#知识分享

大学生必备&#xff0c;这条笔记大数据一定定要推给刚上大学的学弟学妹&#xff01;&#xff01; 1.快练题 这是一个网站 找题的网站海量题库,在线搜题,快速刷题~为您提供百万优质题库,直接搜索题库名称,支持多种刷题模式:顺序练习、语音听题、本地搜题、顺序阅读、模拟考试…

Leetcode-1572. 矩阵对角线元素的和

题目&#xff1a; 给你一个正方形矩阵 mat&#xff0c;请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例 1&#xff1a; 输入&#xff1a;mat [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;25 解释&#xff1a;对角线…

解决ucore实验qemu不断重启问题

解决 ucore 实验 qemu 不断重启问题 做清华大学操作系统 ucore 实验 (x86版本)&#xff0c;实验一编译后运行 qemu 发现系统不断重启&#xff0c;无法正常运行 kernel。实验环境是 ubuntu 22.04&#xff0c;gcc 11.4.0&#xff0c;ld 2.38。最终查证是链接脚本 kernel.ld 导致…

Docker 在window 2024版笔记 下载 安装 操作 配置

---Docker 前言--- Docker windows版官方版是一款专业开源的应用容器引擎&#xff0c;可以加快用户构建、共享和运行现代应用程序的速度&#xff0c;支持运行Linux和Windows Docker容器。 Docker 在容器的基础上&#xff0c;进行了进一步的封装&#xff0c;从文件系统、网络互…

[office] excel2016怎么求最大值和最小值 #职场发展#知识分享

excel2016怎么求最大值和最小值 excel求最大值最小值步骤&#xff1a; 1、鼠标左键双击计算机桌面Excel2016程序图标&#xff0c;将其打开运行。在打开的Excel2016程序窗口&#xff0c;点击“打开其他工作簿”选项&#xff0c;打开需要进行编辑的Excel工作表。如图所示; 2、在打…

SpringCloud-搭建Nacos配置中心

一、Nacos 功能介绍 Nacos&#xff08;Dynamic Naming and Configuration Service&#xff09;是阿里巴巴开源的一个分布式服务注册、配置管理&#xff0c;以及服务健康管理平台。在微服务架构中&#xff0c;配置管理是至关重要的一环&#xff0c;Nacos 提供了可靠、动态的配置…

python-分享篇-GUI界面开发-PyQt5-禁止窗体显示最大化按钮及调整窗体大小

代码 # -*- coding: utf-8 -*-# Form implementation generated from reading ui file nochange.ui # # Created by: PyQt5 UI code generator 5.11.3 # # WARNING! All changes made in this file will be lost! 禁止窗体显示最大化按钮及调整窗体大小from PyQt5 import QtCo…

开局托儿所

一&#xff0c;游戏规则 示例&#xff1a; 9549366345591582732535371762455786747469134955224161766515693255444341522757146691483635716392362557418825198461525396798798225943422864547928724689891326449758 二&#xff0c;贪心算法 我们先用贪心算法试一下&#xf…

wordpress好的网站主题

有什么好的网站主题&#xff0c;都分享在这里了。 蓝色风格的wordpress模板&#xff0c;好的wordpress网站主题&#xff0c;需要既好看&#xff0c;又好用。 https://www.zhanyes.com/qiye/6305.html 血红色的好看的wordpress主题&#xff0c;布局经典&#xff0c;设计好的&am…

Vue2学习第二天

Vue2 学习第二天 1. 数据绑定 Vue 中有 2 种数据绑定的方式&#xff1a; 单向绑定(v-bind)&#xff1a;数据只能从 data 流向页面。双向绑定(v-model)&#xff1a;数据不仅能从 data 流向页面&#xff0c;还可以从页面流向 data。 备注&#xff1a; 双向绑定一般都应用在表单…

大学生画图搜题答案神器?一键查询完备大学题库 #知识分享#经验分享#学习方法

大学生必备的搜题工具&#xff0c;专业课本习题、电子版教材、考研资料、英语四六级等考试题目也能一并搜索&#xff0c;每道题目都有详细的讲解&#xff0c;每个都堪称大学神器。 1.试题易 这是一个网站 涵盖初高中&#xff0f;大学&#xff0f;专升本&#xff0f;考研&…

python视频播放列表信息库之m3u8使用详解

m3u8库是什么&#xff1f; m3u8是一个用于解析和操作M3U8文件的Python库。M3U8文件&#xff0c;是指使用UTF-8编码格式的M3U文件&#xff0c;它们通常用于播放列表文件&#xff0c;尤其是在HTTP Live Streaming&#xff08;HLS&#xff09;中。简单来说&#xff0c;m3u8库能帮…

嵌入式中I2C 相关的硬件问题汇总及死锁解决办法

本文主要介绍如何解决I2C设备硬件设计上的各种问题&#xff0c;希望对大家有所帮助&#xff01; 关于I2C协议详细的讲解&#xff0c;可以参考之前的推文&#xff1a;全面解析 I2C 通信协议 一般情况下&#xff0c; i2c 设备焊接没什么问题&#xff0c;按照设备手册一步步来&a…

<网络安全>《33 网络信息安全基础(4)网络安全工程师进阶体系(一)》

1 图谱 1 基础入门 1.1 网络安全导论 网络安全行业简介&#xff1a; 行业前景 历史 重要事件 网络安全意识与法律法规 安全意识 法律法规 案例 网络安全管理概述 安全运营、运维、模型 等保测评 等保简介、等保规定、流程和规范 1.2 渗透测试基础 渗透测试概述 - 流程、分…

Go语言每日一练——链表篇(九)

传送门 牛客面试笔试必刷101题 ----------------链表相加(二) 题目以及解析 题目 解题代码及解析 解析 这一道题主要是要对链表相加的过程进行模拟&#xff0c;虽然思路不难但是细节出比较多&#xff0c;这里博主的思路主要是先将两个链表反转过来然后以Head1为基础来模拟…

java 宠物在线商城系统Myeclipse开发mysql数据库web结构jsp编程servlet计算机网页项目

一、源码特点 java 宠物在线商城系统是一套完善的java web信息管理系统 servletdaobean mvc模式&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S 模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&…

Windows11通过SMB映射NAS网络驱动磁盘

环境 NAS&#xff1a;威联通TS-416 操作系统&#xff1a;Windows11 第一步 连接NAS winr 打开运行&#xff0c;输入NAS局域网IP地址&#xff0c;按照如下的格式输入 然后输入NAS的账号和密码就可以通过SMB连接到NAS了 第二步 映射网络驱动器 举个栗子&#xff1a;右键Stora…