2018-12-09 23:06:23 wuyi0105 阅读数 2353
  • 携手STM32CubeMX玩转STM32

    本课程教大家如何利用STM32CubeMX玩转STM32(STM32CubeMX支持的所有型号MCU都适用于本课程)。课程内容分为基础内容和扩展内容,例如:讲解串口时会扩展开讲Xmodem通信协议,讲解ADC/DAC时会扩展讲傅里叶计算,讲解完FLASH操作会扩展将bootloader的编写,讲解完M3的bootloader编写会扩展讲解M0的bootloader...... 内容绝对实在,对于学习以及工作都会有很大的帮助。最终的目的就是让大家学会快速开发STM32并收获与STM32有关的实用技术知识。

    1001 人正在学习 去看看 李凯龙

图像处理领域离散傅里叶变换的作用

将图像由时空域,转换为频域

二维离散傅里叶变换

二维离散傅里叶变换公式

二维离散傅里叶变换公式

将二维的离散傅里叶变换进行转化

将不好处理的二维离散傅里叶变换转化为进行两次一维处理
先处理行,再处理列
二维离散傅里叶转化为两次一维处理
公式如下:
二维离散傅里叶变换公式

将系数转化为矩阵形式

在这里插入图片描述

注意,从矩阵的乘积i形式可以看出,原来是N个值,输出后依然是N个值,而且要注意,输出的N个值的每一个值和输入得每一个值都有关系。换句话说,输出的F(0),F(1),F(2)…F(N),之中的每一个值,比如F(1),都需要,输入的所有值做贡献。
f(x)的全部值对离散的傅氏变换四项中的每一项都产生影响。反之亦然。

所以按照刚才将维的思路,进行矩阵的操作。
权值矩阵A,原函数矩阵FF

采用88的DFT操作,对每一个88图像块,进行一次操作

matlab代码

N=8;
A=zeros(N);
for k=0:N-1
    for m=0:N-1
        A(k+1,m+1)=(1/N)*exp(-2*pi*i*(k*m/N));%8*8的 w 的矩阵
    end
end

[Hh,Hw]=size(WYY);
X=ceil(Hw/8)*8;
Y=ceil(Hw/8)*8;
hall_new=zeros(X,Y);
hall_new(1:Hh,1:Hw)=WYY;%把Y分量赋值进去
%hall_new(Hh+1:X,1:Hw)=repmat(WYY(Hh,1:Hw),X-Hh,1);
%hall_new(1:Hh,Hw+1:Y)=repmat(WYY(1:Hh,Hw),1,Y-Hw);
m=X/8;%行块数
n=Y/8;%列块数
for i1=1:m
     for i2=1:n
         FF=double(hall_new((i1-1)*8+1:i1*8,(i2-1)*8+1:i2*8));%按顺序取8*8的每一块
         BB((i1-1)*8+1:i1*8,(i2-1)*8+1:i2*8)=N*A*FF*A';%DFT变换,变成两次一维度处理,另一个函数,先处理一行,一行的8个值都会产生影响,以行和列为整体看
         KK((i1-1)*8+1:i1*8,(i2-1)*8+1:i2*8)=A'*BB((i1-1)*8+1:i1*8,(i2-1)*8+1:i2*8)*A;%DFT反变换
     end
end

未完待续

2016-11-09 12:07:55 BaiYH1994 阅读数 2667
  • 携手STM32CubeMX玩转STM32

    本课程教大家如何利用STM32CubeMX玩转STM32(STM32CubeMX支持的所有型号MCU都适用于本课程)。课程内容分为基础内容和扩展内容,例如:讲解串口时会扩展开讲Xmodem通信协议,讲解ADC/DAC时会扩展讲傅里叶计算,讲解完FLASH操作会扩展将bootloader的编写,讲解完M3的bootloader编写会扩展讲解M0的bootloader...... 内容绝对实在,对于学习以及工作都会有很大的帮助。最终的目的就是让大家学会快速开发STM32并收获与STM32有关的实用技术知识。

    1001 人正在学习 去看看 李凯龙

  图像傅里叶变换方法有很多,可以通过空间光调制器输入图像后在通过平行光照明经过傅里叶变换透镜进行傅里叶变换,另一个方法就是利用计算机进行傅里叶变换,其中傅里叶变换有两种算法一种是DFT还有一种是FFT(快速傅里叶变换)。

  首先我介绍一下图像的定义,图像是怎么去得到的呢?图像是物体与点扩散函数卷积的结果加上一个噪声项(具体想了解可以查看“傅里叶光学"-吕乃光)。

  在这里我谈谈离散傅里叶变换的一些问题,以及离散傅里叶变换的MATLAB代码。首先谈谈傅里叶变换,想必大家一听到傅里叶变换整个人都不好了,傅里叶变换是做什么的呢,个人的理解就是通过无数个正交的向量去描述一个任意的曲线或者信号,最简单的理解就是我们可以通过xy直角坐标系通过一个关系建立一个二维曲线,这样我们就可以通过一个正交的向量去描述这个线上的任意一个点。

  在傅里叶变换中所谓的空间频率的高频与低频分别代表什么呢?高频代表的就是图像中灰度突变速度快的地方,说白了就是看起来密集的地方就是高频,看起来平坦的地方就是低频。这是最简单的理解方式。离散傅里叶变换可以处理任意大小的图像,FFT只能处理2^n*2^n大小的图像,当图像大小不够的时候需要填补空缺的地方。

一下为DFT函数的matlab代码,

<span style="font-size:18px;">function [out_dft_image,out_ab_dft_pic]=dft(input_image,mode)
%%  [out_dft_image,out_ab_dft_pic]=dft_test(input_image)     this function can make dft transform
% F(u-M/2,v-N/2)<=>f(x,y)*(-1).^(x+y)   or you can make dft transform like
% F(u,v)<=>f(x,y)
%     input_image:  had batter less than 150*150 large
%     mode:   if mode==1  this function is to do comfortable visable result   
%             else mode=~1 the result maybe make you uncomfortable 
%     out_dft_image: this is the complex matrix it can make the idft and
%                   get the surse image in spetial domain 
%     out_ab_dft_pic: this is the frequency spectrum picture matrix
%     design by baiyinhao 2015.9.28    20:07 Email:792499178@qq.com
%
%     作  者:光电科技协会     2015.9.28    20:07  白银浩
%


%空域变换到频率域
pic=double(input_image);
[u_p,v_p]=size(pic);%  F(u,v)中的u,v
%f(x,y)*(-1).^(x+y)   即对原图进行一次运算
if mode==1
    
    for x=1:u_p
        for y=1:v_p
            pic(x,y)=pic(x,y)*(-1)^(x+y);%在此处对输入的pic进行了改变  即变成f(x,y)*(-1).^(x+y) 白  添加 
        end
    end
    
    %居中傅里叶变换
    [x_p,y_p]=size(pic);
    dft_pic=zeros(u_p,v_p);
    flag=0;
    temp1=0;
    for u=1:u_p
        for v=1:v_p
            for x=1:x_p
                for y=1:y_p
                    temp1=temp1+pic(x,y)*exp(-1j*2*pi*(u*x/u_p+v*y/v_p));
                end
            end
            dft_pic(u,v)=temp1;
            temp1=0;
        end
        flag=flag+1;
        sprintf('运行到了图像的第:%d 行',flag)
    end
    %输出傅里叶变换 后的实部虚部
    R_dft_pic=real(dft_pic);%求出傅里叶变换后的实部
    I_dft_pic=imag(dft_pic);%求出傅里叶变换后的虚部

    %傅里叶谱
    ab_dft_pic(u_p,v_p)=0;
    for u=1:u_p
        for v=1:v_p
            ab_dft_pic(u,v)=sqrt(R_dft_pic(u,v).^2+I_dft_pic(u,v).^2);
       end
    end
    %最后输出值 
    m_dft_pic=max(max(ab_dft_pic));
    ab_dft_pic1=ab_dft_pic/m_dft_pic*255;



else
   %正常傅里叶变换
    [x_p,y_p]=size(pic);
    dft_pic=zeros(u_p,v_p);
    flag=0;
    temp1=0;
    for u=1:u_p
        for v=1:v_p
            for x=1:x_p
                for y=1:y_p
                    temp1=temp1+pic(x,y)*exp(-1j*2*pi*(u*x/u_p+v*y/v_p));
                end
            end
            dft_pic(u,v)=temp1;
            temp1=0;
        end
        flag=flag+1;
        sprintf('运行到了图像的第:%d 行',flag)
    end
    %输出傅里叶变换 后的实部虚部 白银浩添加
    R_dft_pic=real(dft_pic);%求出傅里叶变换后的实部
    I_dft_pic=imag(dft_pic);%求出傅里叶变换后的虚部

    %傅里叶谱
    ab_dft_pic(u_p,v_p)=0;
    for u=1:u_p
        for v=1:v_p
            ab_dft_pic(u,v)=sqrt(R_dft_pic(u,v).^2+I_dft_pic(u,v).^2);
        end
    end
    %最后输出值 
    m_dft_pic=max(max(ab_dft_pic));
    ab_dft_pic1=ab_dft_pic/m_dft_pic*255;
 end


    out_dft_image=dft_pic;
    out_ab_dft_pic=uint8(ab_dft_pic1);


end</span>

由于运行速度慢,有助于理解,如果有实际用途建议使用FFT。


2016.11.9   12:09

白银浩    

E-mail:BaiYH1994@163.com

Q    Q:792499178

2018-12-30 15:24:17 webzhuce 阅读数 2299
  • 携手STM32CubeMX玩转STM32

    本课程教大家如何利用STM32CubeMX玩转STM32(STM32CubeMX支持的所有型号MCU都适用于本课程)。课程内容分为基础内容和扩展内容,例如:讲解串口时会扩展开讲Xmodem通信协议,讲解ADC/DAC时会扩展讲傅里叶计算,讲解完FLASH操作会扩展将bootloader的编写,讲解完M3的bootloader编写会扩展讲解M0的bootloader...... 内容绝对实在,对于学习以及工作都会有很大的帮助。最终的目的就是让大家学会快速开发STM32并收获与STM32有关的实用技术知识。

    1001 人正在学习 去看看 李凯龙

图像傅里叶变换

二维离散傅里叶变换是将图像从空间域转至频域,在图像增强、图像去噪、图像边缘检测、图像特征提取、图像压缩等等应用中都起着极其重要的作用。理论基础是任意函数都可以表示成正弦函数的线性组合的形式。公式如下
在这里插入图片描述
逆变换公式如下
在这里插入图片描述
令 R(u,v) 和 I(u,c) 分别表示 F(u,v) 的实部和虚部。
幅度谱为
在这里插入图片描述
相位谱为
在这里插入图片描述
指数表示
在这里插入图片描述
功率谱为
在这里插入图片描述

示例演示

首先我们演示下,从一幅图像得到其的幅度谱和相位谱,然后再根据幅度谱和相位谱还原图像。代码如下。

void MainWindow::dftTransform(cv::Mat &image)
{
    image.convertTo(image, CV_32F);
    std::vector<cv::Mat> channels;
    split(image, channels);  //分离图像的RGB通道,
    cv::Mat image_B = channels[0]; //OpenCV:BGR
    //expand input image to optimal size
    int m1 = cv::getOptimalDFTSize(image_B.rows);  //选取最适合做fft的宽和高
    int n1 = cv::getOptimalDFTSize(image_B.cols);
    cv::Mat padded;
    //填充0
    cv::copyMakeBorder(image_B, padded, 0, m1 - image_B.rows, 0, n1 - image_B.cols, cv::BORDER_CONSTANT, cv::Scalar::all(0));
    cv::Mat planes[] = { cv::Mat_<float>(padded), cv::Mat::zeros(padded.size(), CV_32F) };
    cv::Mat complexI;
    cv::merge(planes, 2, complexI);  //planes[0], planes[1]是实部和虚部

    cv::dft(complexI, complexI, cv::DFT_SCALE | cv::DFT_COMPLEX_OUTPUT);
    cv::split(complexI, planes);

    //定义幅度谱和相位谱
    cv::Mat ph, mag, idft;
    cv::phase(planes[0], planes[1], ph);
    cv::magnitude(planes[0], planes[1], mag);  //由实部planes[0]和虚部planes[1]得到幅度谱mag和相位谱ph

    cv::imshow("phase", ph);
    cv::imshow("magnitude", mag);
    /*
    如果需要对实部planes[0]和虚部planes[1],或者幅度谱mag和相位谱ph进行操作,在这里进行更改
    */


    cv::polarToCart(mag, ph, planes[0], planes[1]);  //由幅度谱mag和相位谱ph恢复实部planes[0]和虚部planes[1]
    cv::merge(planes, 2, idft);
    cv::dft(idft, idft, cv::DFT_INVERSE | cv::DFT_REAL_OUTPUT);
    image_B = idft(cv::Rect(0, 0, image.cols & -2, image.rows & -2));
    image_B.copyTo(channels[0]);
    merge(channels, image);
    image.convertTo(image, CV_8U);
    cv::imshow("idft", image);
}

运行结果

在这里插入图片描述

2018-11-23 19:39:43 shanwenkang 阅读数 1422
  • 携手STM32CubeMX玩转STM32

    本课程教大家如何利用STM32CubeMX玩转STM32(STM32CubeMX支持的所有型号MCU都适用于本课程)。课程内容分为基础内容和扩展内容,例如:讲解串口时会扩展开讲Xmodem通信协议,讲解ADC/DAC时会扩展讲傅里叶计算,讲解完FLASH操作会扩展将bootloader的编写,讲解完M3的bootloader编写会扩展讲解M0的bootloader...... 内容绝对实在,对于学习以及工作都会有很大的帮助。最终的目的就是让大家学会快速开发STM32并收获与STM32有关的实用技术知识。

    1001 人正在学习 去看看 李凯龙

二维傅里叶变换

我们先来看看一维情况的傅里叶变换。在信号系统中讲过连续时间的傅里叶变换和离散时间的傅里叶变换,连续时间傅里叶变换在频谱上时非周期的,离散时间傅里叶变换(DTFT)在频谱上是周期的。在DSP中讲了离散傅里叶变换,它的思想是将时域周期化,反映在频域上就是对连续的周期频谱进行抽样

有了一维的离散傅里叶变换(DFT),我们可以将其推广到二维的情况

我们其实可以将二维离散傅里叶变换看成两次一维的离散傅里叶变换,在matlab中我们可以用fft2这个函数来计算

和一维DFT类似,二维DFT显示了图像的频率成分组成情况

如下图所示就是不同的频率成分,也就是说图像实际上是由以下各种不同的图像叠加而成

由于在某一幅特定的图像中,频谱值差距很大,因此我们通常会用log来调整。在实际调用的时候我们还可以采用频谱搬移的方法使得频谱特性更容易观察,例如out=fftshift(log(abs(fft2(im))));由于图像频谱具有中心对称性(一维傅里叶变换是轴对称,二维傅里叶变换是中心对称),我们实际上只需要看频谱的1/2就可以了

我们会看到图中会有两条白色的线,在课程中老师解释说是由于DFT会将图像进行周期化,使得图像的边缘不连续(也就是图像下半部分会与下一幅图的上半部分接壤,左半部分会与右半部分接壤),引入了高频成分导致的。但是关于这点我有点不是很理解,我认为对于一幅图像而言,我们直接对他进行DTFT得到的是一个连续的周期谱,我们对图像进行周期化的过程实际上只是对连续谱进行一个采样,而不会引入新的频率成分,也就是说周期化与否并不影响频谱成分,而差别只是频谱由连续变为离散了。因此我认为频谱存在横竖的白线仅仅是因为图像中存在水平或竖直的边缘(例如上图中的海水与海岸形成竖直的线,山峦与天空形成水平的线)导致的

那么为什么图像中的边缘会使得频谱中也出现相应的白线呢,我们先给出结论:如果图像中存在角度为θ的边线,那么在频谱中我们会看到角度为θ+90度的一条白线。我们在此不做数学上的推导而是举个例子让大家能够理解:我们假设有一幅图像是黑白相间的竖条纹,我们对这幅图像进行傅里叶变换,我们知道二维傅里叶变换可以看做两次一维的傅里叶变换,因此我们对产生图像的矩阵分别进行DFT,得到的结果就是只有频谱中央的一条横线上是有值的,而这个值具体是什么,跟条纹的图案有关

下图是一个实际的例子,我们可以看到对于一幅存在倾斜方格的图片,它的频谱也会出现对应角度的白线

 

二维傅里叶变换的性质

以下是二维傅里叶变换的一些性质,在这就不细讲了

要注意的是DTFT中的卷积性质到DFT中变成了循环卷积,也就是将信号周期化后做卷积(每个位置的值会被循环使用)

但是循环卷积出来的结果往往不是我们想要的,因为周期化的过程使得引入的循环部分也参与卷积运算,而这部分是我们不需要的,解决方法是在序列后面补零,使得循环卷积结果与普通卷积相同,好消息是我们在matlab中调用函数时这些函数会自动帮我们完成这些工作

 

 

2018-08-22 15:49:09 Replus_ 阅读数 8644
  • 携手STM32CubeMX玩转STM32

    本课程教大家如何利用STM32CubeMX玩转STM32(STM32CubeMX支持的所有型号MCU都适用于本课程)。课程内容分为基础内容和扩展内容,例如:讲解串口时会扩展开讲Xmodem通信协议,讲解ADC/DAC时会扩展讲傅里叶计算,讲解完FLASH操作会扩展将bootloader的编写,讲解完M3的bootloader编写会扩展讲解M0的bootloader...... 内容绝对实在,对于学习以及工作都会有很大的帮助。最终的目的就是让大家学会快速开发STM32并收获与STM32有关的实用技术知识。

    1001 人正在学习 去看看 李凯龙

声明:       

       这篇文章的主要目的是通过建立一维傅里叶变换与图像傅里叶变换中相关概念的对应关系来帮助读者理解图像处理中的离散傅里叶变换,因此,理解图像中离散傅里叶变换的前提条件是读者需要了解一维傅里叶变换的基本知识,详情可参考:https://zhuanlan.zhihu.com/p/19763358


基本数学概念的对应关系:

       一维傅里叶变换的作用对象是信号,信号是一维连续的,其数学表现形式如图1所示,该图反应的是随着时间不断推移,信号强度的变换情况,可称为时域:

图1

       而图像处理中的傅里叶变换的作用对象是二维矩阵。二维矩阵的数学表现形式如下图所示,反应了随着位置的不断改变,灰度值大小的变化情况。我们在此将其称为“距离-灰度变化图”:

图2

       从正面看去,由x轴与灰度值轴构成的切面图如图3所示:

图3

       图3与图1的本质是类似的,都是一个自变量一个因变量。因此可以构成对应关系:时间<->距离、信号强度<->灰度值。

傅里叶变换结果的对应关系:

       一维傅里叶变换的原理可以通俗的理解为:将一个复杂无规律的信号拆分成多个简单有规律的子信号来表示(如果对泰勒展开有深刻的理解的话,可以将傅里叶变换理解为将任意一个函数分解为任意个多项式的组合)。如图4所示。

图4

       为了定量表示这个结果,我们用下图进行表达。其中,横轴为频率大小,纵轴为振幅(即信号的最高强度),该图可称为频谱

图5

       通过观察频谱,我们可以发现,频谱中的每个点在时域中都对应一个函数(这个特点很重要,说明了频谱和时域的对应关系是点与线)。

       因此,通过类比,可将图像处理中傅里叶变换理解为:将一个复杂无规律的图像拆分成多个简单有规律的子图像来表示(此处画图太麻烦,请读者自行发挥想象力对图4中的众多子信号,想象成不断起伏的平面)。

       那要如何定量表达众多分解后的子图像呢?

       我们先来看一下图像傅里叶变换后的表现形式,即图像的“频谱”。

       现在,我们就通过类比,来理解这上幅图中的各个方向的自变量到底对应信号频谱中的哪个变量。

       在信号的频谱中,频率的定义为:单位时间内完成周期性变化的次数。而在上文“基本数学概念的对应关系”中,我们已经将时间和距离对应起来了。那么此处只需要将频率定义中的“时间”换成“距离”即可。最终得到用于表达图像傅里叶变换结果的“频谱”中频率的定义:单位距离内完成周期性变化的次数。由于图像中表达距离的单位是像素大小,所以对这个定义进一步可理解为:N个像素内灰度值完成周期性变化的次数。因此我们就成功的将图像“频谱”和信号“频谱”中的自变量联立起来了。在信号频谱中的频率是x(横)轴,而在图像的频谱中频率是(xy轴构成的)平面。距离原点越远,则说明频率越大。因此,窗口边缘处即为高频区域,原点周边即为低频区域。

注意:上文提到了对于信号来说,频谱中的一个点对应子信号时域中的一条线。通过类比,我们可以得出结论:图像频谱中的一个点对应子图像的一整张距离-灰度变化图。(而图像傅里叶变换的数学公式也反应了这个特点)

       同样的,信号频谱中的y轴反应子信号,信号强度的变化范围,而图像频谱中的z轴反应子图像的灰度值的变化范围。频谱窗口中对应的点越亮,则说明该点对应频率的变化范围越大。

总结与举例:

       综上,可对图像频谱进行解读:

       距离原点越远=频率越高=原图中灰度值的变化越频繁。

       灰度值越大=幅值越大=原图中灰度值变化的范围越大。

       因此,低通滤波能保留图像的大致轮廓信息是因为,一张图像所记录到的主要信息(由于受到关照等必然因素的影响)在图像上灰度值的变化是缓慢的,因此主要信息集中在低频区域。而噪音等偶然因素是突然附加到图像上使得灰度值快速变化,而且密密麻麻,这导致N个像元内,灰度值的变化不仅频繁,而且变化的范围还很大。因此,噪音就位于图像频谱的高频区域,表现为高灰度值。

 

 

图像的傅里叶变换

阅读数 6644

没有更多推荐了,返回首页