离散傅里叶变化

傅里叶变换

对傅里叶变换了解不是很清楚的朋友推荐一下这个帖子,讲得很详细 傅里叶变换

源码

先看源码链接

#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"#include <iostream>using namespace cv;
using namespace std;static void help(char ** argv)
{cout << endl<< "This program demonstrated the use of the discrete Fourier transform (DFT). " << endl<< "The dft of an image is taken and it's power spectrum is displayed." << endl << endl<< "Usage:" << endl<< argv[0] << " [image_name -- default lena.jpg]" << endl << endl;
}int main(int argc, char ** argv)
{help(argv);const char* filename = argc >=2 ? argv[1] : "lena.jpg";// 读取灰度图像Mat I = imread(samples::findFile(filename), IMREAD_GRAYSCALE);if(I.empty()){cout << "Error opening image" << endl;return EXIT_FAILURE;}// 扩展输入图像到最优尺寸Mat padded; int m = getOptimalDFTSize(I.rows);int n = getOptimalDFTSize(I.cols); copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));// 创建包含实部和虚部的平面Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};Mat complexI;merge(planes, 2, complexI); // 合并成一个复数矩阵// 进行DFT变换dft(complexI, complexI);// 计算幅度谱并转换为对数尺度split(complexI, planes); // 分离实部和虚部magnitude(planes[0], planes[1], planes[0]); // 计算幅度Mat magI = planes[0];magI += Scalar::all(1); // 转换为对数尺度log(magI, magI);// 如果频谱的行列是奇数,则进行裁剪magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2));// 重新排列傅里叶图像的象限,使原点在图像中心int cx = magI.cols/2;int cy = magI.rows/2;Mat q0(magI, Rect(0, 0, cx, cy)); // 左上Mat q1(magI, Rect(cx, 0, cx, cy)); // 右上Mat q2(magI, Rect(0, cy, cx, cy)); // 左下Mat q3(magI, Rect(cx, cy, cx, cy)); // 右下Mat tmp;q0.copyTo(tmp);q3.copyTo(q0);tmp.copyTo(q3);q1.copyTo(tmp);q2.copyTo(q1);tmp.copyTo(q2);// 归一化幅度图像到0-1之间normalize(magI, magI, 0, 1, NORM_MINMAX);// 显示原图像和频谱图像imshow("Input Image", I);imshow("spectrum magnitude", magI);waitKey();return EXIT_SUCCESS;
}
}

原理

傅里叶变换将图像分解为其正弦和余弦分量。这就意味着,傅里叶变换可以将复杂的图像表示为不同频率和振幅的正弦波和余弦波的组合,这些波的频率和相位描述了图像的周期性结构。低频成分对应图像中的大面积平滑区域,高频成分对应图像中的边缘和细节。
在这里插入图片描述

空间域和频域

  • f : 图像在空间域中的值,即图像像素的强度值。
  • F :图像在频域中的值,即通过傅里叶变换后的结果。

傅里叶变换结果

傅里叶变换将图像从空间域转换到频域,其结果是复数,这意味着每个频率分量有两个部分:实部和虚部。通过所保留地完整的复数信息,可以重新变回空间域。链接

显示频域图像

有两种方式来显示频域图像:

  1. 实部和虚部图像:分别显示傅里叶变换结果的实部和虚部
  2. 幅度和相位图像: 幅度图像和相位图像分别显示每个频率分量的强度和相位信息。

在图像处理中,通常情况下我们只会针对幅度图像做进一步研究,因为其包含了图像几何结构的所有信息。幅度图像显示了频率分量的强度,这与图像的结构和边缘有关。

对于数字图像来说,其经过傅里叶变换所获得的幅度图像是离散的,这也就意味着他们可以从指定的域值中取值,比如说,在基本的灰度图中,像素值通常在0到255之间,因此傅里叶变换也需要是离散类型的。

以下是一个以灰度图为输入例子的步骤详解。

Steps

  1. 将图像拓展到合适的大小
    DFT的性能主要取决于图像的大小,其会在当图像大小为2,3,5的倍数时达到最佳性能。因此,为了达到最佳性能,通常需要对图像的边界进行填充,使用 getOptimalDFTSize()copyMakeBorder() 进行拓展。
Mat padded;
int m = getOptimalDFTSize(I.rows);
int n = getOptimalDFTSize(I.cols);
copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));
  1. 存储复数和实数
    保留复数,可以通过复数来重新转换到空间域。
 Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};Mat complexI;merge(planes, 2, complexI); // Add to the expanded another plane with zeros
  1. 做离散傅里叶变换
 dft(complexI, complexI); // this way the result may fit in the source matrix
  1. 将实值和复值转换为图像强度值
    在这里插入图片描述
    复数由实部和虚部组成,在图像处理和傅里叶变换中,复数表示在频域中的图像信息。
 split(complexI, planes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitudeMat magI = planes[0];
  1. 切换到对数刻度
    结果是傅里叶系数的动态范围太大,无法在屏幕上显示。我们有一些小的和大的变化值我们不能像这样观察到。因此,高值将全部显示为白色点,而小的则显示为黑色点。为了使用灰度值进行可视化,我们可以将线性刻度转换为对数刻度:
    在这里插入图片描述
 magI += Scalar::all(1); // switch to logarithmic scalelog(magI, magI);
  1. 裁剪和重新排列
    由于我们在一开始就拓展了图像,现在是时候将新引入的值去掉。为了可视化的目的,我们还可以重新排列结果的象限,使原点(0,0)与图像中心对应。
 // crop the spectrum, if it has an odd number of rows or columnsmagI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2));// rearrange the quadrants of Fourier image so that the origin is at the image centerint cx = magI.cols/2;int cy = magI.rows/2;Mat q0(magI, Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrantMat q1(magI, Rect(cx, 0, cx, cy)); // Top-RightMat q2(magI, Rect(0, cy, cx, cy)); // Bottom-LeftMat q3(magI, Rect(cx, cy, cx, cy)); // Bottom-RightMat tmp; // swap quadrants (Top-Left with Bottom-Right)q0.copyTo(tmp);q3.copyTo(q0);tmp.copyTo(q3);q1.copyTo(tmp); // swap quadrant (Top-Right with Bottom-Left)q2.copyTo(q1);tmp.copyTo(q2);
  1. 归一化
    再次这样做是为了可视化。我们现在有了大小,但是它仍然在0到1的图像显示范围之外。我们使用**cv::normalize()**函数将值规范化到这个范围。
 normalize(magI, magI, 0, 1, NORM_MINMAX); // Transform the matrix with float values into a// viewable image form (float between values 0 and 1).

应用示例:确定图像中的几何方向

我们可以利用傅里叶变换来确定图像中的几何方向。例如,我们可以判断文本是否是水平的。观察一些文本时,你会注意到文本行形成了水平线,而字母形成了垂直线。这两个主要组成部分也可以在傅里叶变换的结果中看到。我们可以使用水平和旋转的文本图像来实现这一点。

水平方向
在这里插入图片描述
旋转方向
在这里插入图片描述
可以看到,频域最具影响力的分量(星等图像上最亮的点)遵循图像上物体的几何旋转。由此,我们可以计算偏移量并执行图像旋转以纠正最终的未对准。

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

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

相关文章

从零开始了解GPT-4o模型:它是如何工作的?

人工智能&#xff08;AI&#xff09;技术正以惊人的速度发展&#xff0c;其中最引人注目的是OpenAI发布的GPT-4o模型。作为GPT系列的新成员&#xff0c;GPT-4o在多模态输入处理和响应速度上取得了重大进展。本文将深入探讨GPT-4o的工作原理&#xff0c;帮助您全面了解这一尖端A…

MySQL实训

项目名称与项目简介 股票交易系统是一个综合性的金融服务平台&#xff0c;它提供了股票买卖、交易查询、用户管理、股票信息管理以及资金账户管理等功能。系统旨在为用户提供一个安全、高效、便捷的股票交易环境&#xff0c;让用户能够实时掌握市场动态&#xff0c;做出合理的…

模拟物理弧线轨道运动(模拟飞盘,子弹运动)

模拟物理弧线运动&#xff08;模拟飞盘&#xff09; 介绍实现代码总结 介绍 模拟弧线的运动&#xff0c;并且对象始终朝向运动的方向&#xff0c;模拟飞盘子弹的运动轨迹。这里我是没有加重力这么一个概念的&#xff0c;当然了重力其实比较简单可以参考我之前写的模拟抛物线运动…

ubuntu 挂载新硬盘 记录

Ref 安全自动挂载硬盘&#xff0c; https://berylbot.com/archives/mount-disks-ubuntu 挂载新硬盘, https://berylbot.com/archives/mount-disks-ubuntu 1. 检查新硬盘是否被系统识别 lsblk -f 查看所有硬盘的UUID, 其中 mount point 为空则表示尚未挂载的硬盘。 列出所有可用…

ET9中ETTask传递新的Context原理

ET9中ETTask传递新的Context原理 前言 每一个异步函数都会创建两个对象&#xff0c; 第1个是当前异步函数返回值&#xff08;ETTASK&#xff09;对应的ETAsyncTaskMethodBuilder&#xff0c;通过这个类的静态方法Create创建返回&#xff0c;这个builder类中会有一个Task对象&…

idea 自动生成序列化数字

目标&#xff1a;当类继承Serializable后自动生成序列化Uid 网上查了很多说勾选class without ‘serialVersionUID’ 但是我勾选没用 最后发现&#xff0c;我勾选的是Serialization issues里面的配置&#xff0c;要勾选的是JVM languages下的 如下图所示&#xff0c;记录一下…

技术干货|SimLab 电子产品热流体仿真

电子产品热仿真特点有哪些&#xff1f; 结构复杂&#xff0c;电子设备包含几十~上千个元器件 体积小&#xff0c;功率密度高、关注热敏感元器件 多种冷却方式&#xff0c;自然冷却、风扇冷却、液冷、热管等 多维度&#xff0c;芯片级&#xff0c;板级&#xff0c;系统级 单…

昇思25天学习打卡营第03天|张量Tensor

何为张量&#xff1f; 张量&#xff08;Tensor&#xff09;是一个可用来表示在一些矢量、标量和其他张量之间的线性关系的多线性函数&#xff0c;这些线性关系的基本例子有内积、外积、线性映射以及笛卡儿积。其坐标在 &#x1d45b;维空间内&#xff0c;有  &#x1d45b;&a…

ppt模版免费下载网站大全

PPT是我们传达信息、分享知识、展示项目和进行商务沟通的重要工具。一个设计精美、布局合理的PPT不仅能吸引观众的注意力&#xff0c;还能有效提升演讲者的专业形象。PPT模版可以帮助我们高效制作出精美的PPT&#xff0c;下面小编就来和大家分享一些免费无需注册登录就可以直接…

Mysql进阶-索引-使用规则-索引失效情况二(or连接的条件、数据分布影响)

文章目录 1、or连接的条件1.1、展示 tb_user 索引1.2、查询 id10 or age231.3、执行计划 id10 or age231.4、给 age 创建 索引1.4、执行计划 phone17799990004 or age23 2、数据分布影响2.1、查询 tb_user2.2、查询 phone >177999900202.3、执行计划 phone >177999900202…

Python学习打卡:day17

day17 笔记来源于&#xff1a;黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了 目录 day17121、Python 操作 MySQL 基础使用pymysql创建到 MySQL 的数据库链接执行 SQL 语句执行非查询性质的SQL语句执行查询性质的SQL语句 122、Pyth…

幻兽帕鲁Palworld樱花版本服务器一键开服联机

1、登录服务器&#xff08;百度莱卡云&#xff09; 1.1、第一次购买服务器会安装游戏端&#xff0c;大约5分钟左右&#xff0c;如果长时间处于安装状态请联系客服 2、在启动中调整游戏参数 2.1、重启服务器&#xff0c;等待running出现&#xff0c;或者运行时间变为灰色&#x…

Linux0.12内核源码解读(5)-head.s

大家好&#xff0c;我是呼噜噜&#xff0c;好久没有更新old linux了&#xff0c;本文接着上一篇文章图解CPU的实模式与保护模式&#xff0c;继续向着操作系统内核的世界前进&#xff0c;一起来看看heads.s as86 与GNU as 首先我们得了解一个事实&#xff0c;在Linux0.12内核源…

2024年6月27日 (周四) 叶子游戏新闻

老板键工具来唤去: 它可以为常用程序自定义快捷键&#xff0c;实现一键唤起、一键隐藏的 Windows 工具&#xff0c;并且支持窗口动态绑定快捷键&#xff08;无需设置自动实现&#xff09;。 喜马拉雅下载工具: 字面意思 Steam国产“类8番”游戏《永恒逃脱&#xff1a;暗影城堡》…

【JD-GUI】MacOS 中使用Java反编译工具JD-GUI

希望文章能给到你启发和灵感&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏 支持一下博主吧&#xff5e; 阅读指南 开篇说明概念理解一、基础环境说明1.1 硬件环境1.2 软件环境 二、下载与安装2.1 选择对应版本2.2 解压运行排除异常&#xff1a;2.3 关于…

GuiLite C语言实现版本

简介 本项目是idea4good/GuiLite的C语言实现版本&#xff0c;基于2024-06-20节点的版本&#xff08;提交ID&#xff1a;e9c4b57&#xff09;。 本项目仓库&#xff1a;GuiLite_C 需求说明 作为芯片从业人员&#xff0c;国产芯片普遍资源有限&#xff08;ROM和RAM比较少-都是…

[Vulnhub] wallabysnightmare LFI+RCE+Irssi聊天服务RCE

信息收集 Server IP AddressOpening Ports192.168.8.105TCP:22,80,6667,60080 $ nmap -p- -sC -sV 192.168.8.105 --min-rate 1000 -Pn 基础Shell http://192.168.8.105/?page../../../../../etc/shadow 当再次尝试访问已经关闭 $ nmap -p- -sC -sV 192.168.8.105 --min-rat…

【PTA】7-1 网红点打卡攻略(C/C++)代码实现 反思

解题细节分析&#xff1a; 0.比较图的两种存储方法&#xff0c;通过邻接矩阵存储更便于查找给定两点之间的关系 1.注意理解清楚题义&#xff1a;“访问所有网红点”中所有不是指攻略中所有&#xff0c;而是存在的全部的网红点 代码见下&#xff1a;// 需要注明的是&#xff…

锦江丽笙酒店稳步拓局海内外酒店市场 签约及意向合作20个新项目

&#xff08;中国上海&#xff0c;2024年6月27日&#xff09;民族品牌的国际化发展已日趋成为推动经济和文化交流的重要力量。作为民族品牌与国际品牌的融合发展&#xff0c;锦江丽笙酒店顺应市场趋势有序推进旗下品牌矩阵的全面布局&#xff1b;2024年上半年&#xff0c;已达成…

简易深度学习(1)深入分析神经元及多层感知机

一、神经元 单个神经元结构其实可以认为是一个线性回归模型。例如下图中 该神经元输入为三个特征&#xff08;x1&#xff0c;x2&#xff0c;x3&#xff09;&#xff0c;为了方便理解&#xff0c;大家可以认为每条线上都有一个权重和特征对应&#xff08;w1&#xff0c;w2&…