C++离散傅里叶变换

一、序言:

该教程基于之前的图像处理类MYCV,是对其的补充。

二、设计目标

对图像进行简单的离散傅里叶变换,并输出生成的频谱图。

三、需要提前掌握的知识

二维傅里叶变换公式:

四、详细步骤

1.首先定义一个方法,该方法对输入的图像进行傅里叶变换

输入:MyImage 源图像

输出:ComplexNu 进行离散傅里叶变换后的复数数组

定义:

static ComplexNumber* Dft2(MyImage const &Scr);

实现:

ComplexNumber* MyCV::Dft2(MyImage const &Scr)

{

    int width = Scr.m_width;

    int height = Scr.m_height;

    // 将 scr_data 转化为灰度

    MyImage *grayimage = Gray(Scr);

    unsigned char* gray_data = grayimage->m_data;

    int gray_bytesPerLine = grayimage->m_bytesPerLine;

    // 将 gray_data 转化为 double 型,并去掉用于填充的多余空间

    double *double_data = new double[width*height];

    for(int i=;i<height;i++)

        for(int j=;j<width;j++)

        {

            double_data[i*width+j]=(double)gray_data[i*gray_bytesPerLine+j];

        }

    // 对 double_data 进行傅里叶变换

    ComplexNumber *dft2_data = new ComplexNumber[width*height];

    double fixed_factor_for_axisX = (- * PI) / height;

    // evaluate -i2π/N of -i2πux/N, and store the value for computing efficiency

    double fixed_factor_for_axisY = (- * PI) / width;

    // evaluate -i2π/N of -i2πux/N, and store the value for computing efficiency

    for (int u = ; u<height; u++) {

            for (int v = ; v<width; v++) {

                for (int x = ; x<height; x++) {

                    for (int y = ; y<width; y++) {

                        double powerX = u * x * fixed_factor_for_axisX; // evaluate -i2πux/N

                        double powerY = v * y * fixed_factor_for_axisY; // evaluate -i2πux/N

                        ComplexNumber cplTemp;

                        cplTemp.m_rl = double_data[y + x*width] * cos(powerX + powerY);

                        // evaluate f(x) * e^(-i2πux/N), which is equal to f(x) * (cos(-i2πux/N)+sin(-i2πux/N)i) according to Euler's formula

                        cplTemp.m_im = double_data[y + x*width] * sin(powerX + powerY);

                        dft2_data[v + u*width] = dft2_data[v + u*width] + cplTemp;

                    }

                }

            }

        }

    // 返回傅里叶数组

    return dft2_data;

}

2.为了让傅里叶变换可视化,旭阳对其进行标准化和中性化

输入:ComplexNumber 离散傅里叶变换生成的复数数组

输出:MyImage 可视化后的图像

定义:

static MyImage* Dft22MyImage(ComplexNumber *Scr,int width,int height);

实现:

MyImage* MyCV::Dft22MyImage(ComplexNumber *Scr, int const width, int const height)

{

    // 将傅里叶数组归一化

    // 取模

    double mold[width*height];

    for(int i =  ;i<width*height;i++)

    {

        mold[i] = Scr[i].get_mold();

    }

    // 获取最小值

    double min = mold[];

    for(int i = ;i<width*height;i++)

    {

        if(mold[i]<min)

            min = mold[i];

    }

    // 获取去掉前几大值的最大值

    double maxqueue[] = {.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.},max;

    for(int i = ;i<width*height;i++){

        if(mold[i]>maxqueue[])

            maxqueue[] = mold[i];

    }

    for(int j =;j<;j++){

        for(int i = ;i<width*height;i++){

            if(mold[i]>maxqueue[j]&&mold[i]<maxqueue[j-])

                maxqueue[j] = mold[i];

        }

    }

    max = maxqueue[];

    unsigned char *normalized_data = new unsigned char[width*height];

    for(int i=;i<height;i++)

        for(int j=;j<width;j++)

        {

            unsigned char t = (unsigned char)((mold[i*width+j]-min)/(max-min)*);

            if(t>)

                t = ;

            normalized_data[i*width+j]=t;

        }

    // 将图像中心化

    unsigned char* center_data = new unsigned char[width*height];

    for (int u = ; u<height; u++)

        {

        for (int v = ; v<width; v++) {

            if ((u<(height / )) && (v<(width / ))) {

                center_data[v + u*width] =

                    normalized_data[width /  + v + (height /  + u)*width];

            }

            else if ((u<(height / )) && (v >= (width / ))) {

                center_data[v + u*width] =

                    normalized_data[(v - width / ) + (height /  + u)*width];

            }

            else if ((u >= (height / )) && (v<(width / ))) {

                center_data[v + u*width] =

                    normalized_data[(width /  + v) + (u - height / )*width];

            }

            else if ((u >= (height / )) && (v >= (width / ))) {

                center_data[v + u*width] =

                    normalized_data[(v - width / ) + (u - height / )*width];

            }

        }

    }

    // 向中心化的数组填充空间

    int bytesPerLine = (width*+)/*;

    unsigned char *dst_data = new unsigned char[bytesPerLine*height];

    for(int i=;i<height;i++)

        for(int j=;j<width;j++)

        {

            dst_data[i*bytesPerLine+j] = center_data[i*width+j];

        }

    return new MyImage(dst_data,width,height,MyImage::format::GRAY8);

}

至此,离散傅里叶变换的方法实现完成,效果图如下:

如果上述教程或代码中有任何错误,欢迎批评和指证。

五、c++实现离散傅里叶变换的更多相关文章

  1. 离散傅里叶变换(DFT)

    目录     一.研究的意义     二.DFT的定义    三.DFT与傅里叶变换和Z变换的关系     四.DFT的周期性     五.matlab实验       五.1 程序         ...

  2. opencv3.2.0图像离散傅里叶变换

    源码: ##名称:离散傅里叶变换 ##平台:QT5.7.1+opencv3.2.0 ##日期:2017年12月13. /**** 新建QT控制台程序****/ #include <QCoreAp ...

  3. c语言数字图像处理(六):二维离散傅里叶变换

    基础知识 复数表示 C = R + jI 极坐标:C = |C|(cosθ + jsinθ) 欧拉公式:C = |C|ejθ 有关更多的时域与复频域的知识可以学习复变函数与积分变换,本篇文章只给出DF ...

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

    我是做Tracking 的,对于速度要求非常高.发现傅里叶变换能够使用. 于是学习之. 核心: 最根本的一点就是将时域内的信号转移到频域里面.这样时域里的卷积能够转换为频域内的乘积! 在分析图像信号的 ...

  5. opencv 3 core组件进阶(3 离散傅里叶变换;输入输出XML和YAML文件)

    离散傅里叶变换 #include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" ...

  6. 用matlab脚本语言写M文件函数时用三种方法简单实现实现DFT(离散傅里叶变换)

    %用二重循环实现DFT: function xk=dt_0(xn); %define a function N=length(xn); %caculate the length of the vari ...

  7. 灰度图像--频域滤波 傅里叶变换之离散傅里叶变换(DFT)

    学习DIP第23天 转载请标明本文出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对此表示很不 ...

  8. 【转】离散傅里叶变换-DFT(FFT)基础

    转:https://blog.csdn.net/zhangxz259/article/details/81627341 什么是离散傅里叶变换 matlab例子 本文是从最基础的知识开始讲解,力求用最通 ...

  9. OpenCV离散傅里叶变换

    离散傅里叶变换 作用:得到图像中几何结构信息 结论:傅里叶变换后的白色部分(即幅度较大的低频部分),表示的是图像中慢变化的特性,或者说是灰度变化缓慢的特性(低频部分). 傅里叶变换后的黑色部分(即幅度 ...

随机推荐

  1. spring-cloud 服务优雅下线

      在集群环境下,zuul后面的api服务一般会有多个实例,当下线某个实例时,如果使用 kill -9 pid 的方式,会造成这个服务在eureka中还存在,请求还会路由到这个服务上面,造成500,所 ...

  2. 第一周作业-Linux基础入门

    写在前面 实验楼中linux基础入门的内容很多,几乎涵盖了所有的常用命令.命令的记忆不是一朝一夕的,更不能死记硬背,在实践中多操作,熟悉后自然就记住了.我没有将对每个命令操作结果都截图记录下来(事实上 ...

  3. Metasploit和python两种安全工具的学习笔记

    Metasploit是个好东西 主要参考了<Metasploit渗透测试魔鬼训练营>这本书. 一.先用自己的靶机感受一下该工具的强大 linux靶机的ip如图 按照书上写的配置,如图 然后 ...

  4. SpringFox 初体验

    本文来自网易云社区. 1.什么是SpringFox? 1.1 Springfox 是一个开源的API Doc的框架, 它的前身是swagger-springmvc,可以将我们的Controller中的 ...

  5. 51nod1315(位运算)

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1315 题意:中文题诶- 思路:位或(|)运算是二进制位有一个 ...

  6. 2017-10-7 清北刷题冲刺班p.m

    测试 A 同花顺 文件名 输入文件 输出文件 时间限制 空间限制card.cpp/c/pas card.in card.out 1s 512MB题目描述所谓同花顺,就是指一些扑克牌,它们花色相同,并且 ...

  7. 分层图最短路【bzoj2763】: [JLOI2011]飞行路线

    bzoj2763: [JLOI2011]飞行路线 Description Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0 ...

  8. Extending JMeter – Creating Custom Config Element – Property File Reader

    JMeter is one of the best open source tools in the Test Automation Community. It comes with all the ...

  9. 基于CentOS系统下的Oracle的安装

    背景 最近的数据库的实验课,要求利用虚拟机安装CentOS系统,并在此系统上安装Oracle_11g软件实现监听,在windows系统上安装SQL Developer软件作为客户端 ,从而可以在SQL ...

  10. Appium+Python入门学习总结

    最近研究了一下Appium,查看了一些大神的博客,绕过了一些坑,现将从搭建环境到运行真机测试的流程总结如下: 一.搭建环境,这里我参考了虫师的博客,一步一步来,搭好了Appium的环境,如果需要真机测 ...