二维离散傅里叶变换

简介: 笔记

在学完一维的傅里叶变换后,紧接着就是二维的傅里叶变换了。直接上干货吧!!!

途中会用到opencv读取与显示图片。


一. 公式

M表示图像的行数,N表示图像的列数。20.png


2.经过欧拉公式可以得一下形式,这样就可以轻松得到实部和虚部了。

21.png

3.其逆变换22.png

4. 将傅里叶保护后的图像中心化。只需要在傅里叶变换的f(x,y)前面成以一个(-1)的x+y次方就可以了。其数学推导可以自行去百度。

23.png

看完上面的公式之后,下面开始编程实现拉,使用的是C++。

二. 编程实现DTF

代码中有详细的注释。就不在这里作过多的解释了。


头文件包含及以下宏定义

#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/core/core.hpp>
#include<iostream>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
#define PI 3.1415926535    //定义π
#define col 100       //图像的行数为100,再大的话运算量太大的。
#define row 100       //图像的列数为100。

类的定义

class FFT {
private:
  double img[col][row];    //保存输入的数据,输入的数据只有实部
  double re[col][row];    //保存DFT后的实部
  double im[col][row];  //保存DFT后的虚部
  Mat a = imread("1.jpg", 0);   //读取图像
public:
  void init();       //将读取的图像数据写入img中
  void dft();   //进行DFT变换
  void idft();  //进行DFT逆变换
  void reserve();
  void fudu();       //计算幅度值。
  void show();
};


init()函数

void FFT::init()
{
  int b;
  resize(a, a, Size(100, 100));   //将图像resize到(100,100)
  for (int i = 0; i < 100; i++)
  {
  for (int j = 0; j < 100; j++)
  {
    b = a.at<uchar>(i, j);   //得到每一个像素值
    img[i][j] = b;
  }
  }
}


dft()函数

void FFT::dft()
{
  double a, b;
  for(int n=0;n<col;n++)
  for (int m = 0; m < row; m++)
  {
    a = 0.0;
    b = 0.0;
    for (int i = 0; i < col; i++)
    {
    for (int j = 0; j < row; j++)
    {
    //根据公式列表达式
      a += pow(-1, i + j)*img[i][j] * cos(2 * PI*(((double(n*i) / double(col))+(double((m*j))/double(row)))));
      b += pow(-1, i + j)*img[i][j] * sin(2 * PI*(((double(n*i) / double(col)) + (double((m*j)) / double(row)))));
    }
    }
    //将计算的值写入对应的变量中,这里已经进行了中心化操作
    re[n][m] = a;
    im[n][m] = -b;
  }
}


idft()函数

void FFT::idft()
{
  double a;
  for (int n = 0; n < col; n++)
  {
  for (int m = 0; m < row; m++)
  {
    a = 0.0;
    for (int i = 0; i < col; i++)
    {
    for (int j = 0; j < row; j++)
    {
      //这里只求其逆变换的实部,与原图片对比。
      a += re[i][j] * cos(2 * PI*((double(n*i) / double(col)) + (double(m*j) / double(row)))) - im[i][j] * sin(2 * PI*((double(n*i) / double(col)) + (double(m*j) / double(row))));
    }
    }
    re[n][m] = ((1. / (10000.))*a);
  }
  }
}

fudu()函数

void FFT::fudu()
{
  int b;
  for(int i=0;i<col;i++)
  for (int j = 0; j < row; j++)
  {
    //计算幅度值
    b = sqrt(re[i][j] * re[i][j] + im[i][j] * im[i][j]);
    b = b / 255;    //归一化到0-255
    //写入Mat中,便于可视化
    a.at<uchar>(i, j) = b;
  }
  //显示DTF幅度场
  imshow("aa", a);
  waitKey(0);
}

show()函数

//显示逆变换后的图像,看看与原始图像是不是一样的。
void FFT::show()
{
  for(int i=0;i<col;i++)
  for (int j = 0; j < row; j++)
  {
    a.at<uchar>(i, j) = re[i][j];
  }
  imshow("aa", a);
  waitKey(0);
}


main()函数

int main(void)
{
  FFT a;
  a.init();
  a.dft();
  a.idft();
  a.fudu();
  //a.show();
  return 0;
}


所有的函数都实现了,下面来看看实现的效果吧!

原始图像

30.png

DFT后的振幅场

31.png

逆变换后的图像,差距有点大O(∩_∩)O。

32.png

Thank for your reading !!!!


公众号:FPGA之旅


目录
相关文章
|
4月前
第4章-变换-4.0
第4章-变换-4.0
30 2
|
6月前
快速傅里叶变换
【6月更文挑战第2天】
73 6
|
7月前
|
计算机视觉
傅里叶
傅里叶 “【5月更文挑战第23天】”
87 1
|
7月前
|
算法 计算机视觉
傅里叶变换
傅里叶变换
99 2
|
7月前
|
存储 计算机视觉
【OpenCV】—离散傅里叶变换
【OpenCV】—离散傅里叶变换
频域滤波—离散余弦变换
频域滤波—离散余弦变换
|
算法 计算机视觉 Python
|
C++ 异构计算
|
人工智能 算法 安全
【基础算法】差分的应用(一维差分和二维差分)
【基础算法】差分的应用(一维差分和二维差分)
209 0
【基础算法】差分的应用(一维差分和二维差分)