作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

函数原型

void dft(InputArray src, OutputArray dst, int flags = 0, int nonzeroRows = 0);
void idft(InputArray src, OutputArray dst, int flags = 0, int nonzeroRows = 0);

参数说明

  1. InputArray类型的src,输入图像,如Mat类型。
  2. OutputArray类型的dst,输出图像。
  3. int类型的flags,转换的标识符,默认为0,也就是使用标准的正向变换。
  4. int类型的nonzeroRows,默认值为0。如果该值设为非零值,dft函数会将该值作为非零行的有效区间长度,只对非零行进行处理,提高计算效率。

       针对第三个参数flags,有如下几种常见的标识符,对此展开简单介绍:

  1. DFT_INVERSE:一维或二维逆变换。
  2. DFT_SCALE:缩放比例标识符,输出的结果会以1/N进行缩放。
  3. DFT_ROWS:对输入矩阵的每行进行正向或反向的变换,适用于处理多种矢量的场景,可减小资源开销。
  4. DFT_COMPLEX_OUTPUT:一维或二维实数数组正变换。
  5. DFT_REAL_OUTPUT:一维或二维复数数组反变换。

测试代码

#include<iostream>
#include<opencv2/opencv.hpp>
#include<ctime>
using namespace std;
using namespace cv;void fftshift(cv::Mat &plane0, cv::Mat &plane1);int main(void)
{Mat test = imread("test.jpg", 0);test.convertTo(test, CV_32FC1);//创建通道,存储dft后的实部与虚部(CV_32F,必须为单通道数)cv::Mat plane[] = { test.clone(), cv::Mat::zeros(test.size() , CV_32FC1) };cv::Mat complexIm;cv::merge(plane, 2, complexIm); // 合并通道 (把两个矩阵合并为一个2通道的Mat类容器)cv::dft(complexIm, complexIm, 0); // 进行傅立叶变换,结果保存在自身// 分离通道(数组分离)cv::split(complexIm, plane);// 以下的操作是频域迁移fftshift(plane[0], plane[1]);// 计算幅值cv::Mat mag,mag_log,mag_nor;cv::magnitude(plane[0], plane[1], mag);// 幅值对数化:log(1+m),便于观察频谱信息mag += Scalar::all(1);cv::log(mag, mag_log);cv::normalize(mag_log, mag_nor, 1,0, NORM_MINMAX);cv::Mat BLUR;// 再次搬移回来进行逆变换fftshift(plane[0], plane[1]);cv::merge(plane, 2, BLUR); // 实部与虚部合并cv::idft(BLUR, BLUR);       // idft结果也为复数BLUR = BLUR / BLUR.rows / BLUR.cols;cv::split(BLUR, plane);//分离通道,主要获取通道imshow("original", test / 255);imshow("result", plane[0] / 255);waitKey(0);system("pause");return 0;
}// fft变换后进行频谱搬移
void fftshift(cv::Mat &plane0, cv::Mat &plane1)
{// 以下的操作是移动图像  (零频移到中心)int cx = plane0.cols / 2;int cy = plane0.rows / 2;cv::Mat part1_r(plane0, cv::Rect(0, 0, cx, cy));  // 元素坐标表示为(cx, cy)cv::Mat part2_r(plane0, cv::Rect(cx, 0, cx, cy));cv::Mat part3_r(plane0, cv::Rect(0, cy, cx, cy));cv::Mat part4_r(plane0, cv::Rect(cx, cy, cx, cy));cv::Mat temp;part1_r.copyTo(temp);  //左上与右下交换位置(实部)part4_r.copyTo(part1_r);temp.copyTo(part4_r);part2_r.copyTo(temp);  //右上与左下交换位置(实部)part3_r.copyTo(part2_r);temp.copyTo(part3_r);cv::Mat part1_i(plane1, cv::Rect(0, 0, cx, cy));  //元素坐标(cx,cy)cv::Mat part2_i(plane1, cv::Rect(cx, 0, cx, cy));cv::Mat part3_i(plane1, cv::Rect(0, cy, cx, cy));cv::Mat part4_i(plane1, cv::Rect(cx, cy, cx, cy));part1_i.copyTo(temp);  //左上与右下交换位置(虚部)part4_i.copyTo(part1_i);temp.copyTo(part4_i);part2_i.copyTo(temp);  //右上与左下交换位置(虚部)part3_i.copyTo(part2_i);temp.copyTo(part3_i);
}

测试效果

图1 log后的频谱图

图2 前后对比图

我采用了最基础的dft函数(够用了,几乎很少有场景非要用其他模式的dft)进行傅里叶变换,傅里叶变换后将频谱的低频迁移至中心,再对数化进行观察,因为在频域没有进行任何额外的操作,所以反傅里叶变换后的结果同原图一致。

注意反傅里叶变换后数值要除以图像的宽*高~

如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

OpenCV-离散傅里叶变换cv::dftcv::idft相关推荐

  1. 离散傅里叶变换(DFT/IDFT、FFT/IFFT)运算量的讨论

    前言:关于为什么要写这个博客 最近在重新看<合成孔径雷达成像 算法与实现>这本书,看到"离散傅里叶变换记其逆变换的运算量级为"这句话,就想起当初在学<数字信号处理 ...

  2. OpenCV 离散傅里叶变换

    离散傅里叶变换(DFT) 定义 离散傅里叶变换(Discrete Fourier Transform,缩写为DFT),是傅里叶变换在时域和频域上都呈离散的形式,将信号的时域采样变换为其DFT的频域采样 ...

  3. opencv离散傅里叶变换进行图像旋转校正

    前言 离散傅立叶变换的一个应用是决定图片中物体的几何方向.     观察这两张幅度图你会发现频域的主要内容(幅度图中的亮点)是和空间图像中物体的几何方向相关的. 通过这点我们可以计算旋转角度并修正偏差 ...

  4. 独家|OpenCV 1.7 离散傅里叶变换

    翻译:陈之炎 校对:李海明本文约2400字,建议阅读5分钟本文为大家介绍了OpenCV离散傅里叶变换. 目标 本小节将寻求以下问题的答案: 什么是傅立叶变换,为什么要使用傅立叶变换? 如何在OpenC ...

  5. 【OpenCV4】图像的傅里叶变换 cv::dft() 和逆变换 cv::idft() 解析(c++)

    图像傅里叶变换的作用: 频谱分析,获取图像中高频低频的分布情况 快速卷积,两个矩阵的傅里叶变换结果相乘 案例代码: cv::Mat TestOpencvDft() {cv::Mat lena = cv ...

  6. OPenCV:傅里叶变换、时域和频域、频谱和相位谱、傅里叶级数、离散傅里叶变换(DFT)、频域滤波、高通和低通滤波器、带通和带阻滤波器

    日萌社 人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新) 快速了解傅立叶变换(播放PPT即能动态地显示gif图)    ...

  7. Opencv 实现图像的离散傅里叶变换(DFT)、卷积运算(相关滤波)

    原文:http://blog.csdn.net/ikerpeng/article/details/41845545?utm_source=tuicool&utm_medium=referral ...

  8. 基于OpenCV完成离散傅里叶变换

    基于OpenCV完成离散傅里叶变换 目标 学会使用函数: cv::copyMakeBorder() , cv::merge() , cv::dft() , cv::getOptimalDFTSize( ...

  9. 使用OpenCV实现离散傅里叶变换(DFT)

    使用OpenCV实现离散傅里叶变换(DFT) 傅里叶变换,妈呀这个东东好高级啊!真的高级吗?理解起来还真是有点困难,需要一些高等数学的基础.有了OpenCV,你不理解也没问题,会用就OK!就好比你会用 ...

最新文章

  1. 怎样删除usb计算机连接网络打印机驱动,惠普激光打印机安装驱动时报“跟这台计算机连接的一个 USB 设备运行不正...
  2. iOS 使用Instruments优化内存性能
  3. getElementsByTagName
  4. python3.6 使用pyinstaller 打包web程序的方法
  5. 企业服务总线需求说明
  6. 【rzxt】windows7怎么设置桌面背景 如何快速道下一个背景
  7. 【数学期望】【LCA】【树形DP】树
  8. python并发编程5-线程
  9. 机器学习基础(四十二)—— 常用损失函数的设计(multiclass SVM loss hinge loss)
  10. 计算机字长与下列哪项指标密切相关,组成原理与汇编语言-中国大学mooc-题库零氪...
  11. Q112:用Xcode调试程序(以PBRT-V3中的pbrt为例)
  12. Acrobat Pro DC 教程,如何使用文本和图片文件创建 PDF?
  13. PS4 从局域网安装PS4 PKG游戏 | PS4 HEN PS4 Package Sender
  14. 数据库表结构设计,什么是概念模型、逻辑模型、物理模型
  15. 使用markdown-it插件
  16. 5G时代要来了?5G到底什么样?
  17. 免费实现音乐文件转换:将下载的音乐转换为MP3格式
  18. SpringMVC框架|Handler处理器的三种写法
  19. 调试技巧:如何以数组的方式查看一个指针
  20. 华硕服务器怎么装win7系统教程视频,华硕电脑离线重装win7系统详细教程

热门文章

  1. 资源组 —— 助你轻松解决单账户内的资源分组管理难题
  2. ceph进程启动流程
  3. OPENSSH升级为7.4
  4. 南沙发布全国首个智慧城市物联网大数据管理平台
  5. 《ActionScript 3.0基础教程》——1.3 在显示面板输出信息
  6. Asp.Net超时问题汇总
  7. Python 抓取网页乱码问题 以及EXCEL乱码
  8. 2013着重发展的4个方向
  9. Checkbox与RadioGroup的使用方法
  10. socket编程(五)