热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

数字图像处理离散傅里叶变换(opencv3+C++显示)

参考:http:daily.zhihu.comstory3935067http:blog.csdn.netkeith_bbarticledetails53389819

参考:

http://daily.zhihu.com/story/3935067

http://blog.csdn.net/keith_bb/article/details/53389819

在学习信号与系统或通信原理等课程里面可能对傅里叶变换有了一定的了解。我们知道傅里叶变换是把一个信号从时域变换到其对应的频域进行分析。如果有小伙伴还对傅里叶变换处于很迷糊的状态,请戳这里,非常通俗易懂。而在图像处理中也有傅里叶分析的概念,我这里给出在其官方指导文件opencv_tutorials中给出的解释。 
傅里叶变换可以将一幅图片分解为正弦和余弦两个分量,换而言之,他可以将一幅图像从其空间域(spatial domain)转换为频域(frequency domain)。这种变换的思想是任何函数可以很精确的接近无穷个sin()函数和cos()函数的和。傅里叶变换提供了这种方法来达到这种效果。对于二位图像其傅里叶变换公式如下: 
这里写图片描述, IMREAD_GRAYSCALE); //读入图像灰度图//判断图像是否加载成功if (I.empty()){cout <<"图像加载失败!" <return -1;}elsecout <<"图像加载成功!" <//以0填充输入图像矩阵int m &#61; getOptimalDFTSize(I.rows);int n &#61; getOptimalDFTSize(I.cols);//填充输入图像I&#xff0c;输入矩阵为padded&#xff0c;上方和左方不做填充处理copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));Mat planes[] &#61; { Mat_<float>(padded), Mat::zeros(padded.size(),CV_32F) };Mat complexI;merge(planes, 2, complexI); //将planes融合合并成一个多通道数组complexIdft(complexI, complexI); //进行傅里叶变换//计算幅值&#xff0c;转换到对数尺度(logarithmic scale)//&#61;> log(1 &#43; sqrt(Re(DFT(I))^2 &#43; Im(DFT(I))^2))split(complexI, planes); //planes[0] &#61; Re(DFT(I),planes[1] &#61; Im(DFT(I))//即planes[0]为实部,planes[1]为虚部magnitude(planes[0], planes[1], planes[0]); //planes[0] &#61; magnitudeMat magI &#61; planes[0];magI &#43;&#61; Scalar::all(1);log(magI, magI); //转换到对数尺度(logarithmic scale)//如果有奇数行或列&#xff0c;则对频谱进行裁剪magI &#61; magI(Rect(0, 0, magI.cols&-2, magI.rows&-2));//重新排列傅里叶图像中的象限&#xff0c;使得原点位于图像中心int cx &#61; magI.cols / 2;int cy &#61; magI.rows / 2;Mat q0(magI, Rect(0, 0, cx, cy)); //左上角图像划定ROI区域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);//归一化处理&#xff0c;用0-1之间的浮点数将矩阵变换为可视的图像格式normalize(magI, magI, 0, 1, CV_MINMAX);imshow("输入图像", I);imshow("频谱图", magI);waitKey(0);return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77

程序分析&#xff1a; 
1.图像填充&#xff1a;

Mat padded;
int m &#61; getOptimalDFTSize(I.rows);
int n &#61; getOptimalDFTSize(I.cols);
copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));

  • 1
  • 2
  • 3
  • 4

根据前面的理论介绍可以知道当图像尺寸为2、3、5的倍数时可以得到最快的处理速度&#xff0c;所以通过getOptimalDFTSize()函数获取最佳DFT变换尺寸&#xff0c;之后再结合copyMakeBorder()函数对图像进行扩充。

2.为实部和虚部分配存储空间

Mat planes[] &#61; { Mat_<float>(padded), Mat::zeros(padded.size(),CV_32F) };
Mat complexI;
merge(planes, 2, complexI);

  • 1
  • 2
  • 3

傅里叶变换的结果是复数&#xff0c;这就意味着经过傅里叶变换每个图像值都会变成两个值&#xff0c;此外其频域(frequency domains)范围比空间域(spatial counterpart)范围大很多。我们通常以浮点型数据格式对结果进行存储。因此我们将输入图像转换为这种类型&#xff0c;通过另外的通道扩充图像。

3.傅里叶变换

dft(complexI, complexI);

  • 1

傅里叶变换函数&#xff0c;对图像进行傅里叶变换。

4.将实数和复数的值转换为幅度值

split(complexI, planes);
magnitude(planes[0], planes[1], planes[0]);
Mat magI
&#61; planes[0];

  • 1
  • 2
  • 3

复数包含实部和虚部两个部分&#xff0c;傅里叶变换的结果是一个复数&#xff0c;傅里叶变换的幅度计算公式是&#xff1a; 
这里写图片描述 
5.转换为对数尺度(Switch to a logarithmic scale)

magI &#43;&#61; Scalar::all(1);
log(magI, magI);

  • 1
  • 2

之所以要进行对数转换是因为傅里叶变换后的结果对于在显示器显示来讲范围比较大&#xff0c;这样的话对于一些小的变化或者是高的变换值不能进行观察。因此高的变化值将会转变成白点&#xff0c;而较小的变化值则会变成黑点。为了能够获得可视化的效果&#xff0c;可以利用灰度值将我们的线性尺度(linear scale)转变为对数尺度(logarithmic scale)&#xff0c;其计算公式如下&#xff1a; 
这里写图片描述

6.剪切和象限变换

magI &#61; magI(Rect(0, 0, magI.cols&-2, magI.rows&-2));
int cx &#61; magI.cols / 2;
int cy &#61; 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);

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

在进行傅里叶变换时&#xff0c;为了取得更快的计算效果&#xff0c;对图像进行了扩充&#xff0c;现在就需要对新增加的行列进行裁剪了。为了可视化的需要&#xff0c;我们同样需要对显示的结果图像像素进行调整&#xff0c;如果不进行调整&#xff0c;最后显示的结果是这样的&#xff1a; 
这里写图片描述 
可以看到四周的角上时高频分量&#xff0c;现在我们通过重新调整象限将高频分量调整到图像正中间。

7.归一化

normalize(magI, magI, 0, 1, CV_MINMAX);

  • 1

对结果进行归一化处理同样是处于可视化的目的。现在我们得到了幅度值&#xff0c;但是这仍然超出了0-1的显示范围。这就需要利用normalize()函数对数据进行归一化处理。

程序运行结果如图&#xff1a; 
这里写图片描述



推荐阅读
  • 如何高效创建和使用字体图标
    在Web和移动开发中,为什么选择字体图标?主要原因是其卓越的性能,可以显著减少HTTP请求并优化页面加载速度。本文详细介绍了从设计到应用的字体图标制作流程,并提供了专业建议。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • Python自动化处理:从Word文档提取内容并生成带水印的PDF
    本文介绍如何利用Python实现从特定网站下载Word文档,去除水印并添加自定义水印,最终将文档转换为PDF格式。该方法适用于批量处理和自动化需求。 ... [详细]
  • 帝国CMS多图上传插件详解及使用指南
    本文介绍了一款用于帝国CMS的多图上传插件,该插件通过Flash技术实现批量图片上传功能,显著提升了多图上传效率。文章详细说明了插件的安装、配置和使用方法。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 深入探讨CPU虚拟化与KVM内存管理
    本文详细介绍了现代服务器架构中的CPU虚拟化技术,包括SMP、NUMA和MPP三种多处理器结构,并深入探讨了KVM的内存虚拟化机制。通过对比不同架构的特点和应用场景,帮助读者理解如何选择最适合的架构以优化性能。 ... [详细]
  • 本文介绍如何通过注册表编辑器自定义和优化Windows文件右键菜单,包括删除不需要的菜单项、添加绿色版或非安装版软件以及将特定应用程序(如Sublime Text)添加到右键菜单中。 ... [详细]
  • 本文介绍如何使用 Python 提取和替换 .docx 文件中的图片。.docx 文件本质上是压缩文件,通过解压可以访问其中的图片资源。此外,我们还将探讨使用第三方库 docx 的方法来简化这一过程。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 网络运维工程师负责确保企业IT基础设施的稳定运行,保障业务连续性和数据安全。他们需要具备多种技能,包括搭建和维护网络环境、监控系统性能、处理突发事件等。本文将探讨网络运维工程师的职业前景及其平均薪酬水平。 ... [详细]
  • PHP 5.5.0rc1 发布:深入解析 Zend OPcache
    2013年5月9日,PHP官方发布了PHP 5.5.0rc1和PHP 5.4.15正式版,这两个版本均支持64位环境。本文将详细介绍Zend OPcache的功能及其在Windows环境下的配置与测试。 ... [详细]
  • 掌握 Photoshop 是学习网页设计的重要一步。本文将详细介绍 Photoshop 的基础与进阶功能,帮助您更好地进行图像处理和网页设计。推荐使用最新版本的 Photoshop,以体验更强大的功能和更高的效率。 ... [详细]
  • 本文介绍如何使用Python进行文本处理,包括分词和生成词云图。通过整合多个文本文件、去除停用词并生成词云图,展示文本数据的可视化分析方法。 ... [详细]
  • 本文探讨了如何在 PHP 的 Eloquent ORM 中实现数据表之间的关联查询,并通过具体示例详细解释了如何将关联数据嵌入到查询结果中。这不仅提高了数据查询的效率,还简化了代码逻辑。 ... [详细]
author-avatar
拍友2502914703
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有