热门标签 | 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; 
这里写图片描述



推荐阅读
  • Cookie学习小结
    Cookie学习小结 ... [详细]
  • vue引入echarts地图的四种方式
    一、vue中引入echart1、安装echarts:npminstallecharts--save2、在main.js文件中引入echarts实例:  Vue.prototype.$echartsecharts3、在需要用到echart图形的vue文件中引入:   importechartsfrom&amp;quot;echarts&amp;quot;;4、如果用到map(地图),还 ... [详细]
  • 使用HTML和JavaScript实现视频截图功能
    本文介绍了如何利用HTML和JavaScript实现从远程MP4、本地摄像头及本地上传的MP4文件中截取视频帧,并展示了具体的实现步骤和示例代码。 ... [详细]
  • 本文详细介绍了 HTML 中 a 标签的 href 属性的多种用法,包括实现超链接、锚点以及调用 JavaScript 方法。通过具体的示例和解释,帮助开发者更好地理解和应用这些技术。 ... [详细]
  • 微信公众号推送模板40036问题
    返回码错误码描述说明40001invalidcredential不合法的调用凭证40002invalidgrant_type不合法的grant_type40003invalidop ... [详细]
  • 使用 Jupyter Notebook 实现 Markdown 编写与代码运行
    Jupyter Notebook 是一个开源的基于网页的应用程序,允许用户在同一文档中编写 Markdown 文本和运行多种编程语言的代码,并实时查看运行结果。 ... [详细]
  • WPF项目学习.一
    WPF项目搭建版权声明:本文为博主初学经验,未经博主允许不得转载。一、前言记录在学习与制作WPF过程中遇到的解决方案。使用MVVM的优点是数据和视图分离,双向绑定,低耦合,可重用行 ... [详细]
  • 本文介绍了如何使用Adobe Photoshop将图片调整为800x800像素,并确保图片清晰度不受影响,特别适合用于制作淘宝主图。无论是原始图片大于或小于800x800像素,都能通过以下步骤轻松完成。 ... [详细]
  • 无论是在迁移到云服务还是更换云服务商的过程中,数据迁移都是一个至关重要的环节。本文将探讨数据迁移中可能遇到的问题及解决方案,包括路径问题、速度问题和数据完整性等。 ... [详细]
  • 本文详细介绍了如何使用JavaScript实现面部交换功能,包括基本原理和具体实现步骤。 ... [详细]
  • 本文详细介绍了如何在PHP中记录和管理行为日志,包括ThinkPHP框架中的日志记录方法、日志的用途、实现原理以及相关配置。 ... [详细]
  • 专业人士如何做自媒体 ... [详细]
  • 三角测量计算三维坐标的代码_双目三维重建——层次化重建思考
    双目三维重建——层次化重建思考FesianXu2020.7.22atANTFINANCIALintern前言本文是笔者阅读[1]第10章内容的笔记,本文从宏观的角度阐 ... [详细]
  • MicrosoftDeploymentToolkit2010部署培训实验手册V1.0目录实验环境说明3实验环境虚拟机使用信息3注意:4实验手册正文说 ... [详细]
  • Framework7:构建跨平台移动应用的高效框架
    Framework7 是一个开源免费的框架,适用于开发混合移动应用(原生与HTML混合)或iOS&Android风格的Web应用。此外,它还可以作为原型开发工具,帮助开发者快速创建应用原型。 ... [详细]
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社区 版权所有