OpenCV-离散傅里叶变换cv::dft&cv::idft

简介: OpenCV-离散傅里叶变换cv::dft&cv::idft

函数原型

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)进行傅里叶变换,傅里叶变换后将频谱的低频迁移至中心,再对数化进行观察,因为在频域没有进行任何额外的操作,所以反傅里叶变换后的结果同原图一致。


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


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

相关文章
|
4月前
|
机器学习/深度学习 人工智能 算法
Python在计算机视觉(CV)中扮演重要角色,得益于其丰富的库如OpenCV、Pillow和Scikit-image。
【7月更文挑战第5天】Python在计算机视觉(CV)中扮演重要角色,得益于其丰富的库如OpenCV、Pillow和Scikit-image。CV涉及图像处理、模式识别和机器学习,用于图像理解和生成。Python的跨平台特性和活跃社区使其成为CV的理想工具。基本流程包括图像获取、预处理、特征提取、分类识别及图像生成。例如,面部识别通过预处理图像,使用如`cv2.CascadeClassifier`进行检测;物体检测类似,但需适应不同目标;图像生成则利用GAN创造新图像。
68 4
|
3月前
|
计算机视觉 索引
OpenCV读取视频失败<无可用信息,未为 opencv_world453.dll 加载任何符号> cv::VideoCapture
本文介绍了解决OpenCV读取视频失败的错误,指出问题通常由视频路径错误或摄像头索引错误导致,并提供了相应的解决方法。
OpenCV读取视频失败<无可用信息,未为 opencv_world453.dll 加载任何符号> cv::VideoCapture
|
3月前
|
计算机视觉
OpenCV 图像类型标识符 CV_<bit_depth><S|U|F>C<number_of_channels>
OpenCV 图像类型标识符 CV_<bit_depth><S|U|F>C<number_of_channels>
39 0
|
6月前
|
存储 计算机视觉
【OpenCV】—离散傅里叶变换
【OpenCV】—离散傅里叶变换
|
计算机视觉
OpenCV-模板匹配cv::matchTemplate
OpenCV-模板匹配cv::matchTemplate
104 0
|
计算机视觉
OpenCV-矩形边框cv::boundingRect
OpenCV-矩形边框cv::boundingRect
104 0
|
6月前
|
计算机视觉
OpenCV报错: cv::Exception,位于内存位置 0x00000078226FEE58 处。
OpenCV报错: cv::Exception,位于内存位置 0x00000078226FEE58 处。
|
6月前
|
计算机视觉 Python
opencv cv::Range()和cv::Rect()用于crop来获得感兴趣区域
opencv cv::Range()和cv::Rect()用于crop来获得感兴趣区域
226 0
|
计算机视觉
OpenCV-绘制标记符cv::drawMarker
OpenCV-绘制标记符cv::drawMarker
249 2
|
计算机视觉 容器
OpenCV-图像金字塔cv::buildPyramid
OpenCV-图像金字塔cv::buildPyramid
OpenCV-图像金字塔cv::buildPyramid