精华内容
下载资源
问答
  • 如果输入二维图像数据,则显示的图像是输入的灰度分布,傅立叶频谱是输入的频率分布,频谱图中心对称。 图像频谱即二维频谱图通过对原图像进行水平和竖直两个方向的所有扫描线处一维傅立叶变换的叠加得到 频谱图中以...

    图像傅立叶频谱分析


    参考:http://cns-alumni.bu.edu/~slehar/fourier/fourier.html#filtering 很棒

    分析:

    如果输入二维图像数据,则显示的图像是输入的灰度分布,傅立叶频谱是输入的频率分布,频谱图中心对称。

    图像频谱即二维频谱图通过对原图像进行水平和竖直两个方向的所有扫描线处一维傅立叶变换的叠加得到

    频谱图中以图中心为圆心,圆的相位对应原图中频率分量的相位,半径对应频率高低,低频半径小,高频半径大,中心为直流分量,某点亮度对应该频率能量高低。

    从测试案例中更清楚的提现以上几点

    以下为几个测试案例:

    1.水平方向为sin函数,竖直方向没有变化,对应频谱如图为零相位相对低频的一个亮点,而其他位置基本为黑色,说明没有其他频率分量(水平方向其他小亮点是由于原图不是严格的sin函数而产生的噪声)

     

    2.相对1频率变高,频谱图中亮点位置半径变大

    3.sin函数方向改变,频谱图的方向也改变,两种解释。可以理解为水平方向和竖直方向单独扫描都是sin函数,对应频谱叠加所得。也可是理解为原图sin函数方向(相位)改变,频谱图相位变化

    4.3图叠加1图

     

    5.频率再次升高,频谱图半径再次增大

    6.1图叠加2图,频谱图也叠加

    7.原图为一条竖直线,每个行扫描需要若干频率(几乎所有频率)正弦曲线去叠加逼近,所以频谱图包含了所有频率,竖直扫描依然没有变化,频谱图只有一条横线。

     

    8.以下两图对比,第一个图变化不明显,对比度低,频谱图中心亮周围暗,主要为低频分量

    第二个图相对对比度高,频谱周围部分比第一张图的频谱要亮的多,第二张图高频分量更多,但原图背景仍然是灰色图,所以频谱图也是中心最亮,低频分量最高。



    代码:


    1.图像的傅里叶频谱的意义

    之前的博文其实已经归纳过这方面的内容了。我们常用的图像平滑处理,其实就是一个低通滤波,一定程度上去除高频信号,可以使得图像变得柔和(也就是平滑)。但是,在去除周期性噪声时候,空间域内的滤波(卷积)就不是那么好操作了。所以,这里时候,无论是理解起来方便,还是其他原因,都需要在频域内进行滤波。 
    详细的叙述还是在下面的博文里面啦!!!! 
    [数字图像处理]频域滤波(1)–基础与低通滤波器 
    [数字图像处理]频域滤波(2)–高通滤波器,带阻滤波器与陷波滤波器

    2. 傅里叶频谱的计算

    这部分的内容,主要就是使用OpenCV自带的函数 
    void cvDFT( const CvArr* src, CvArr* dst, int flags, int nonzero_rows=0 ) 
    去求取图像的傅里叶变换。这里,输出结果CvArr* dst由两个通道组成,分别代表了实部与虚部。我们再根据如下算式,就可以得到傅里叶频谱了。 
    |F(u,v)|=R2(u,v)+F2(u,v)2 
    我自己也参考了很多人的代码,然后实现的代码如下。

    <code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">IplImage* fft2(IplImage* image_input)
    {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> dftWidth  = getOptimalDFTSize(image_input->width);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> dftHeight = getOptimalDFTSize(image_input->height);
    
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//cout<< " Width" <<  image_input->width << "    " <<  dftWidth  << "\n";</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//cout<< "Height" << image_input->height << "    " <<  dftHeight << "\n";</span>
    
        IplImage* image_padded = cvCreateImage(cvSize(dftWidth,dftHeight),
                                               IPL_DEPTH_8U,
                                               <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        cvCopyMakeBorder( image_input, image_padded, cvPoint(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>), IPL_BORDER_CONSTANT,cvScalarAll(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)); 
    
        IplImage *image_Re =<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> , *image_Im = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, *image_Fourier = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; 
    
        image_Re = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        image_Im = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        image_Fourier = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);
    
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//image_Re <--- image_padded </span>
        cvConvertScale(image_padded,image_Re);   
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//image_Im <--- 0</span>
        cvZero(image_Im);                 
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//image_Fourier[0] <--- image_Re</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//image_Fourier[1] <--- image_Im</span>
        cvMerge(image_Re,image_Im,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,image_Fourier); 
    
        cvDFT(image_Fourier,image_Fourier,CV_DXT_FORWARD);
    
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//image_Fourier[0] ---> image_Re</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//image_Fourier[1] ---> image_Im</span>
        cvSplit(image_Fourier,image_Re,image_Im,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
    
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Mag = sqrt(Re^2 + Im^2)</span>
        cvPow(image_Re,image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.0</span>);
        cvPow(image_Im,image_Im,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.0</span>);
        cvAdd(image_Re,image_Im,image_Re);
        cvPow(image_Re,image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.5</span>);
    
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// log (1 + Mag)</span>
        cvAddS(image_Re,cvScalar(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>),image_Re ); 
        cvLog (image_Re,image_Re); 
    
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//  |-----|-----|           |-----|-----|   </span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//  |  1  |  3  |           |  4  |  2  |</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//  |-----|-----|   --->    |-----|-----|</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//  |  2  |  4  |           |  3  |  1  |</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//  |-----|-----|           |-----|-----|</span>
    
        IplImage *Fourier = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        cvZero(image_Fourier);
    
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> cx = image_Re->width/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> cy = image_Re->height/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;
    
        cvSetImageROI(image_Re,cvRect( <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,cx,cy));  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1 </span>
        cvSetImageROI( Fourier,cvRect(cx,cy,cx,cy));  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 4 </span>
        cvAddWeighted(image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,Fourier,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,Fourier);
    
        cvSetImageROI(image_Re,cvRect(cx,cy,cx,cy));  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 4 </span>
        cvSetImageROI( Fourier,cvRect( <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,cx,cy));  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1 </span>
        cvAddWeighted(image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,Fourier,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,Fourier);
    
        cvSetImageROI(image_Re,cvRect(cx, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,cx,cy));  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 3 </span>
        cvSetImageROI( Fourier,cvRect( <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,cy,cx,cy));  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 2 </span>
        cvAddWeighted(image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,Fourier,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,Fourier);
    
        cvSetImageROI(image_Re,cvRect( <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,cy,cx,cy));  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 2 </span>
        cvSetImageROI( Fourier,cvRect(cx, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,cx,cy));  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 3 </span>
        cvAddWeighted(image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,Fourier,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,Fourier);
    
        cvResetImageROI(image_Re);
        cvResetImageROI( Fourier);
    
        cvNormalize(Fourier,Fourier,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,CV_C,<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">NULL</span>);
    
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>(Fourier);
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li></ul>

    从这里开始,还是简单的分析一下代码吧。

    <code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> dftWidth  = getOptimalDFTSize(image_input->width);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> dftHeight = getOptimalDFTSize(image_input->height);
    IplImage* image_padded = cvCreateImage(cvSize(dftWidth,dftHeight),
                                           IPL_DEPTH_8U,
                                           <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
    cvCopyMakeBorder( image_input, image_padded, cvPoint(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>), IPL_BORDER_CONSTANT,cvScalarAll(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)); </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

    这里参考了文献[2]中的说法,在尺寸数为2,3,5的倍数的场合,计算的速度是最快的。所以使用函数getOptimalDFTSize()来寻找最匹配的尺寸,然后再同伙cvCopyMakeBorder()进行多余部分的填充,这里选的配置是将图放在从点(0,0)开始的位置,其余不足的地方,用0进行填充。

    <code class="hljs haskell has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">IplImage</span> *image_Re =<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> , *image_Im = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, *image_Fourier = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; 
    
    <span class="hljs-title" style="box-sizing: border-box;">image_Re</span> = cvCreateImage(cvSize(dftWidth,dftHeight),<span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">IPL_DEPTH_64F</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
    <span class="hljs-title" style="box-sizing: border-box;">image_Im</span> = cvCreateImage(cvSize(dftWidth,dftHeight),<span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">IPL_DEPTH_64F</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
    <span class="hljs-title" style="box-sizing: border-box;">image_Fourier</span> = cvCreateImage(cvSize(dftWidth,dftHeight),<span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">IPL_DEPTH_64F</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);
    
    //image_Re <-<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">-- image_padded </span>
    <span class="hljs-title" style="box-sizing: border-box;">cvConvertScale</span>(image_padded,image_Re);   
    //image_Im <-<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">-- 0</span>
    <span class="hljs-title" style="box-sizing: border-box;">cvZero</span>(image_Im);                 
    //image_Fourier[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] <-<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">-- image_Re</span>
    //image_Fourier[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] <-<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">-- image_Im</span>
    <span class="hljs-title" style="box-sizing: border-box;">cvMerge</span>(image_Re,image_Im,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,image_Fourier); 
    
    <span class="hljs-title" style="box-sizing: border-box;">cvDFT</span>(image_Fourier,image_Fourier,<span class="hljs-type" style="box-sizing: border-box; color: rgb(102, 0, 102);">CV_DXT_FORWARD</span>);
    
    //image_Fourier[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">---> image_Re</span>
    //image_Fourier[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">---> image_Im</span>
    <span class="hljs-title" style="box-sizing: border-box;">cvSplit</span>(image_Fourier,image_Re,image_Im,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul>

    其实这里的很好理解的,将填充到最适尺寸的图像赋值给image_Re,将image_Im赋值为0。让后将这两层图复制到image_Fourier的两个通道里,然后使用函数cvDFT()进行傅里叶变换。得到结果还是存在于image_Fourier的两个通道里,分别代表实部与虚部,然后通过cvSplit()将其抽出到image_Re与image_Im里。

    <code class="hljs scss has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Mag = sqrt(Re^2 + Im^2)</span>
    <span class="hljs-function" style="box-sizing: border-box;">cvPow(image_Re,image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.0</span>)</span>;
    <span class="hljs-function" style="box-sizing: border-box;">cvPow(image_Im,image_Im,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.0</span>)</span>;
    <span class="hljs-function" style="box-sizing: border-box;">cvAdd(image_Re,image_Im,image_Re)</span>;
    <span class="hljs-function" style="box-sizing: border-box;">cvPow(image_Re,image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.5</span>)</span>;
    
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// log (1 + Mag)</span>
    <span class="hljs-function" style="box-sizing: border-box;">cvAddS(image_Re,<span class="hljs-function" style="box-sizing: border-box;">cvScalar(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)</span>,image_Re )</span>; 
    cvLog (image_Re,image_Re); </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

    以上代码,实现了以下计算。 
    |F(u,v)|=R2(u,v)+F2(u,v)2 
    还有就是进行了一个对数变换,这个也没的说,看傅里叶频谱的标配操作。

    <code class="hljs mathematica has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">//  |-----|-----|           |-----|-----|   
    //  |  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>  |  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>  |           |  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>  |  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>  |
    //  |-----|-----|   --->    |-----|-----|
    //  |  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>  |  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>  |           |  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>  |  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>  |
    //  |-----|-----|           |-----|-----|
    
    IplImage *<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span> = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
    cvZero(image_Fourier);
    
    int cx = image_Re->width/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;
    int cy = image_Re->height/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;
    
    cvSetImageROI(image_Re,cvRect( <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,cx,cy));  // <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> 
    cvSetImageROI( <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>,cvRect(cx,cy,cx,cy));  // <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span> 
    cvAddWeighted(image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>);
    
    cvSetImageROI(image_Re,cvRect(cx,cy,cx,cy));  // <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span> 
    cvSetImageROI( <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>,cvRect( <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,cx,cy));  // <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> 
    cvAddWeighted(image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>);
    
    cvSetImageROI(image_Re,cvRect(cx, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,cx,cy));  // <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> 
    cvSetImageROI( <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>,cvRect( <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,cy,cx,cy));  // <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> 
    cvAddWeighted(image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>);
    
    cvSetImageROI(image_Re,cvRect( <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,cy,cx,cy));  // <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> 
    cvSetImageROI( <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>,cvRect(cx, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,cx,cy));  // <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> 
    cvAddWeighted(image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>);
    
    cvResetImageROI(image_Re);
    cvResetImageROI( <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>);
    
    cvNormalize(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,CV_C,NULL);
    
    return(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Fourier</span>);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li></ul>

    其实重头戏在这里,这里需要一个交换操作。至于为何所求得的傅里叶频谱为什么需要交换的原因是,这个代码求得的结果其实是范围[0,2π]内的傅里叶变换。而我们所需要的是[π,π]内的结果。详细的原因,还是在我以前的博客里有说明。 
    [数字图像处理]频域滤波(1)–基础与低通滤波器

    这里,我使用了ROI操作与cvAddWeighted()函数进行了实现。其运行的结果如下所示。 
    这里写图片描述
    恩,基本可以看出来,直流分量也被我移动到了中心,以上代码实现了傅里叶频谱的计算与显示。

    3. 不用交换操作的代码

    使用MATLAB去求取尺寸为M×N图像f的傅里叶频谱时候,通常会用fft2(f,2*M,2*N)。使用此函数求得的福利叶变换,其实还是[0,2π]范围内的傅里叶变换。要想使得傅里叶频谱的DC分量位于中心的话,其实还是需要一些别的操作的。冈萨雷斯的《数字图像处理》一书中,对于这个问题,是利用了傅里叶变换的评议特性,即 
    f(x,y)=f(x,y)×(1)x+y 
    然后再对函数f(x,y)进行福利叶变换,所得到结果,就是所需要的是[π,π]内傅里叶变换的结果。具体的原理与推导,还是参看冈萨雷斯的《数字图像处理》英文原本的p258页左右,中文译本的p148左右。当然,嫌麻烦的话,还可以看我的博文,博文中也简明推导了平移特性。 
    [数字图像处理]频域滤波(1)–基础与低通滤波器 
    为此,实现的代码变为了如下形式。

    <code class="hljs cpp has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">IplImage* fft2_New(IplImage* image_input)
    {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> dftWidth  = getOptimalDFTSize(image_input->width);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> dftHeight = getOptimalDFTSize(image_input->height);
    
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><< <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" Width"</span> <<  image_input->width << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"    "</span> <<  dftWidth  << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"\n"</span>;
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><< <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Height"</span> << image_input->height << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"    "</span> <<  dftHeight << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"\n"</span>;
    
        IplImage* image_padded = cvCreateImage(cvSize(dftWidth,dftHeight),
                                               IPL_DEPTH_8U,
                                               <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        cvCopyMakeBorder( image_input, image_padded, cvPoint(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>), IPL_BORDER_CONSTANT,cvScalarAll(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)); 
    
        IplImage *image_Re =<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> , *image_Im = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, *image_Fourier = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; 
    
        image_Re = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        image_Im = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        image_Fourier = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);
    
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//image_Re = image_padded .* (-1)^(x+y);  </span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> pixel;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> y=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;y<image_padded->height;y++)
        {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> x=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;x<image_padded->width;x++)
            {
                pixel = cvGetReal2D(image_padded,x,y);
                pixel = ((x+y)%<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)?(pixel):((-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)*pixel);
                cvSetReal2D(image_Re,x,y,pixel);
            }
        }
    
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//image_Im <--- 0</span>
        cvZero(image_Im);                 
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//image_Fourier[0] <--- image_Re</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//image_Fourier[1] <--- image_Im</span>
        cvMerge(image_Re,image_Im,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,image_Fourier); 
    
        cvDFT(image_Fourier,image_Fourier,CV_DXT_FORWARD);
    
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//image_Fourier[0] ---> image_Re</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//image_Fourier[1] ---> image_Im</span>
        cvSplit(image_Fourier,image_Re,image_Im,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
    
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Mag = sqrt(Re^2 + Im^2)</span>
        cvPow(image_Re,image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.0</span>);
        cvPow(image_Im,image_Im,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.0</span>);
        cvAdd(image_Re,image_Im,image_Re);
        cvPow(image_Re,image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.5</span>);
    
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// log (1 + Mag)</span>
        cvAddS(image_Re,cvScalar(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>),image_Re ); 
        cvLog (image_Re,image_Re); 
    
        cvNormalize(image_Re,image_Re,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,CV_C,NULL);
    
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>(image_Re);
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li></ul>

    在这里,由于考虑到计算的原因,我将f(x,y)=f(x,y)×(1)x+y这个计算,用下面代码去进行了实现。

    <code class="hljs perl has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">y</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">y</span><image_padded->height;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">y</span>++)
    {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">x</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">x</span><image_padded->width;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">x</span>++)
        {
            pixel = cvGetReal2D(image_padded,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">x</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">y</span>);
            pixel = ((<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">x</span>+<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">y</span>)<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%2</span> == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)?(pixel):((-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*pixel</span>);
            cvSetReal2D(image_Re,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">x</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">y</span>,pixel);
        }
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

    其实也就相当于,x+y是偶数的话f(x,y)不变,x+y是奇数的话f(x,y)变为负。用这样一个简单的判断去实现。其运行的结果,如下所示。

    原图的傅里叶频谱 
    原图的结果
    使用11×11高斯滤波器后的傅里叶频谱 
    这里写图片描述

    从实验结果看来,可以看出以下两点

    1. 对于原图而言两个函数的结果基本一致,两个函数都得到了正确的结果。
    2. 使用平滑处理后,频谱的高频成分明显变小,对于空间域的图像而言,图像变得模糊了。


    展开全文
  • 图像傅里叶变换频谱分析

    千次阅读 2019-09-29 09:44:19
    图像的傅里叶频谱特性分析 图像傅里叶频谱关于(/,/)的对称性 图像傅里叶频谱特性及其频谱图 傅里叶变换在图像处理中的应用

     图像的傅里叶频谱特性分析

    图像傅里叶频谱关于(/,/)的对称性

    图像傅里叶频谱特性及其频谱图

    傅里叶变换在图像处理中的应用

     

     

    展开全文
  • 如何用VC++编写信号频率为30Hz的傅里叶频谱分析程序,并且可以画出频谱图~
  • 1、为什么要进行傅里叶变换,其物理意义是什么? 傅立叶变换是数字信号处理领域一种很重要的算法。要知道傅立叶变换算法的意义,首先要了解傅立叶原理的意义。 傅立叶原理表明:任何连续测量的时序或信号,都可以...

    1为什么要进行傅里叶变换,其物理意义是什么?

    傅立叶变换是数字信号处理领域一种很重要的算法。要知道傅立叶变换算法的意义,首先要了解傅立叶原理的意义。

    傅立叶原理表明:任何连续测量的时序或信号,都可以表示为不同频率的正弦波信号的无限叠加。而根据该原理创立的傅立叶变换算法利用直接测量到的原始信号,以累加方式来计算该信号中不同正弦波信号的频率、振幅和相位。

    和傅立叶变换算法对应的是反傅立叶变换算法。该反变换从本质上说也是一种累加处理,这样就可以将单独改变的正弦波信号转换成一个信号。

    因此,可以说,傅立叶变换将原来难以处理的时域信号转换成了易于分析的频域信号(信号的频谱),可以利用一些工具对这些频域信号进行处理、加工。最后还可以利用傅立叶反变换将这些频域信号转换成时域信号。

    从现代数学的眼光来看,傅里叶变换是一种特殊的积分变换。它能将满足一定条件的某个函数表示成正弦基函数的线性组合或者积分。在不同的研究领域,傅里叶变换具有多种不同的变体形式,如连续傅里叶变换和离散傅里叶变换。

    在数学领域,尽管最初傅立叶分析是作为热过程的解析分析的工具,但是其思想方法仍然具有典型的还原论和分析主义的特征。"任意"的函数通过一定的分解,都能够表示为正弦函数的线性组合的形式,而正弦函数在物理上是被充分研究而相对简单的函数类:1. 傅立叶变换是线性算子,若赋予适当的范数,它还是酉算子;2. 傅立叶变换的逆变换容易求出,而且形式与正变换非常类似;3. 正弦基函数是微分运算的本征函数,从而使得线性微分方程的求解可以转化为常系数的代数方程的求解.在线性时不变杂的卷积运算为简单的乘积运算,从而提供了计算卷积的一种简单手段;5. 离散形式的傅立叶的物理系统内,频率是个不变的性质,从而系统对于复杂激励的响应可以通过组合其对不同频率正弦信号的响应来获取;4. 著名的卷积定理指出:傅立叶变换可以化复变换可以利用数字计算机快速的算出(其算法称为快速傅立叶变换算法(FFT))。

    正是由于上述的良好性质,傅里叶变换在物理学、数论、组合数学、信号处理、概率、统计、密码学、声学、光学等领域都有着广泛的应用。

    2、图像傅立叶变换的物理意义

    图像的频率是表征图像中灰度变化剧烈程度的指标,是灰度在平面空间上的梯度。如:大面积的沙漠在图像中是一片灰度变化缓慢的区域,对应的频率值很低;而对于地表属性变换剧烈的边缘区域在图像中是一片灰度变化剧烈的区域,对应的频率值较高。傅立叶变换在实际中有非常明显的物理意义,设f是一个能量有限的模拟信号,则其傅立叶变换就表示f的谱。从纯粹的数学意义上看,傅立叶变换是将一个函数转换为一系列周期函数来处理的。从物理效果看,傅立叶变换是将图像从空间域转换到频率域,其逆变换是将图像从频率域转换到空间域。换句话说,傅立叶变换的物理意义是将图像的灰度分布函数变换为图像的频率分布函数,傅立叶逆变换是将图像的频率分布函数变换为灰度分布函数

    傅立叶变换以前,图像(未压缩的位图)是由对在连续空间(现实空间)上的采样得到一系列点的集合,我们习惯用一个二维矩阵表示空间上各点,则图像可由z=f(x,y)来表示。由于空间是三维的,图像是二维的,因此空间中物体在另一个维度上的关系就由梯度来表示,这样我们可以通过观察图像得知物体在三维空间中的对应关系。为什么要提梯度?因为实际上对图像进行二维傅立叶变换得到频谱图,就是图像梯度的分布图,当然频谱图上的各点与图像上各点并不存在一一对应的关系,即使在不移频的情况下也是没有。傅立叶频谱图上我们看到的明暗不一的亮点,实际上图像上某一点与邻域点差异的强弱,即梯度的大小,也即该点的频率的大小(可以这么理解,图像中的低频部分指低梯度的点,高频部分相反)。一般来讲,梯度大则该点的亮度强,否则该点亮度弱。这样通过观察傅立叶变换后的频谱图,也叫功率图,我们首先就可以看出,图像的能量分布,如果频谱图中暗的点数更多,那么实际图像是比较柔和的(因为各点与邻域差异都不大,梯度相对较小),反之,如果频谱图中亮的点数多,那么实际图像一定是尖锐的,边界分明且边界两边像素差异较大的。对频谱移频到原点以后,可以看出图像的频率分布是以原点为圆心,对称分布的。将频谱移频到圆心除了可以清晰地看出图像频率分布以外,还有一个好处,它可以分离出有周期性规律的干扰信号,比如正弦干扰,一副带有正弦干扰,移频到原点的频谱图上可以看出除了中心以外还存在以某一点为中心,对称分布的亮点集合,这个集合就是干扰噪音产生的,这时可以很直观的通过在该位置放置带阻滤波器消除干扰

    另外我还想说明以下几点:

    1图像经过二维傅立叶变换后,其变换系数矩阵表明:

    若变换矩阵Fn原点设在中心,其频谱能量集中分布在变换系数短阵的中心附近(图中阴影区)。若所用的二维傅立叶变换矩阵Fn的原点设在左上角,那么图像信号能量将集中在系数矩阵的四个角上。这是由二维傅立叶变换本身性质决定的。同时也表明一股图像能量集中低频区域。

    、变换之后的图像在原点平移之前四角是低频,最亮,平移之后中间部分是低频,最亮,亮度大说明低频的能量大(幅角比较大)


    展开全文
  • 图像的傅里叶频谱

    千次阅读 2017-03-25 16:47:59
    1.图像的傅里叶频谱的意义 之前的博文其实已经归纳过这方面的内容了。我们常用的图像平滑处理,其实就是一个低通滤波,一定程度上去除高频信号,可以使得图像变得柔和(也就是平滑)。但是,在去除周期性噪声时候,...

    1.图像的傅里叶频谱的意义

    之前的博文其实已经归纳过这方面的内容了。我们常用的图像平滑处理,其实就是一个低通滤波,一定程度上去除高频信号,可以使得图像变得柔和(也就是平滑)。但是,在去除周期性噪声时候,空间域内的滤波(卷积)就不是那么好操作了。所以,这里时候,无论是理解起来方便,还是其他原因,都需要在频域内进行滤波。 
    详细的叙述还是在下面的博文里面啦!!!! 

    2. 傅里叶频谱的计算

    这部分的内容,主要就是使用OpenCV自带的函数 
    void cvDFT( const CvArr* src, CvArr* dst, int flags, int nonzero_rows=0 ) 
    去求取图像的傅里叶变换。这里,输出结果CvArr* dst由两个通道组成,分别代表了实部与虚部。我们再根据如下算式,就可以得到傅里叶频谱了。 
    |F(u,v)|=R2(u,v)+F2(u,v)2 
    我自己也参考了很多人的代码,然后实现的代码如下。

    IplImage* fft2(IplImage* image_input)
    {
        int dftWidth  = getOptimalDFTSize(image_input->width);
        int dftHeight = getOptimalDFTSize(image_input->height);
    
        //cout<< " Width" <<  image_input->width << "    " <<  dftWidth  << "\n";
        //cout<< "Height" << image_input->height << "    " <<  dftHeight << "\n";
    
        IplImage* image_padded = cvCreateImage(cvSize(dftWidth,dftHeight),
                                               IPL_DEPTH_8U,
                                               1);
        cvCopyMakeBorder( image_input, image_padded, cvPoint(0,0), IPL_BORDER_CONSTANT,cvScalarAll(0)); 
    
        IplImage *image_Re =0 , *image_Im = 0, *image_Fourier = 0; 
    
        image_Re = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,1);
        image_Im = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,1);
        image_Fourier = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,2);
    
        //image_Re <--- image_padded 
        cvConvertScale(image_padded,image_Re);   
        //image_Im <--- 0
        cvZero(image_Im);                 
        //image_Fourier[0] <--- image_Re
        //image_Fourier[1] <--- image_Im
        cvMerge(image_Re,image_Im,0,0,image_Fourier); 
    
        cvDFT(image_Fourier,image_Fourier,CV_DXT_FORWARD);
    
        //image_Fourier[0] ---> image_Re
        //image_Fourier[1] ---> image_Im
        cvSplit(image_Fourier,image_Re,image_Im,0,0);
    
        //Mag = sqrt(Re^2 + Im^2)
        cvPow(image_Re,image_Re,2.0);
        cvPow(image_Im,image_Im,2.0);
        cvAdd(image_Re,image_Im,image_Re);
        cvPow(image_Re,image_Re,0.5);
    
        // log (1 + Mag)
        cvAddS(image_Re,cvScalar(1),image_Re ); 
        cvLog (image_Re,image_Re); 
    
        //  |-----|-----|           |-----|-----|   
        //  |  1  |  3  |           |  4  |  2  |
        //  |-----|-----|   --->    |-----|-----|
        //  |  2  |  4  |           |  3  |  1  |
        //  |-----|-----|           |-----|-----|
    
        IplImage *Fourier = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,1);
        cvZero(image_Fourier);
    
        int cx = image_Re->width/2;
        int cy = image_Re->height/2;
    
        cvSetImageROI(image_Re,cvRect( 0, 0,cx,cy));  // 1 
        cvSetImageROI( Fourier,cvRect(cx,cy,cx,cy));  // 4 
        cvAddWeighted(image_Re,1,Fourier,0,0,Fourier);
    
        cvSetImageROI(image_Re,cvRect(cx,cy,cx,cy));  // 4 
        cvSetImageROI( Fourier,cvRect( 0, 0,cx,cy));  // 1 
        cvAddWeighted(image_Re,1,Fourier,0,0,Fourier);
    
        cvSetImageROI(image_Re,cvRect(cx, 0,cx,cy));  // 3 
        cvSetImageROI( Fourier,cvRect( 0,cy,cx,cy));  // 2 
        cvAddWeighted(image_Re,1,Fourier,0,0,Fourier);
    
        cvSetImageROI(image_Re,cvRect( 0,cy,cx,cy));  // 2 
        cvSetImageROI( Fourier,cvRect(cx, 0,cx,cy));  // 3 
        cvAddWeighted(image_Re,1,Fourier,0,0,Fourier);
    
        cvResetImageROI(image_Re);
        cvResetImageROI( Fourier);
    
        cvNormalize(Fourier,Fourier,1,0,CV_C,NULL);
    
        return(Fourier);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    从这里开始,还是简单的分析一下代码吧。

    int dftWidth  = getOptimalDFTSize(image_input->width);
    int dftHeight = getOptimalDFTSize(image_input->height);
    IplImage* image_padded = cvCreateImage(cvSize(dftWidth,dftHeight),
                                           IPL_DEPTH_8U,
                                           1);
    cvCopyMakeBorder( image_input, image_padded, cvPoint(0,0), IPL_BORDER_CONSTANT,cvScalarAll(0)); 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这里参考了文献[2]中的说法,在尺寸数为2,3,5的倍数的场合,计算的速度是最快的。所以使用函数getOptimalDFTSize()来寻找最匹配的尺寸,然后再同伙cvCopyMakeBorder()进行多余部分的填充,这里选的配置是将图放在从点(0,0)开始的位置,其余不足的地方,用0进行填充。

    IplImage *image_Re =0 , *image_Im = 0, *image_Fourier = 0; 
    
    image_Re = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,1);
    image_Im = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,1);
    image_Fourier = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,2);
    
    //image_Re <--- image_padded 
    cvConvertScale(image_padded,image_Re);   
    //image_Im <--- 0
    cvZero(image_Im);                 
    //image_Fourier[0] <--- image_Re
    //image_Fourier[1] <--- image_Im
    cvMerge(image_Re,image_Im,0,0,image_Fourier); 
    
    cvDFT(image_Fourier,image_Fourier,CV_DXT_FORWARD);
    
    //image_Fourier[0] ---> image_Re
    //image_Fourier[1] ---> image_Im
    cvSplit(image_Fourier,image_Re,image_Im,0,0);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    其实这里的很好理解的,将填充到最适尺寸的图像赋值给image_Re,将image_Im赋值为0。让后将这两层图复制到image_Fourier的两个通道里,然后使用函数cvDFT()进行傅里叶变换。得到结果还是存在于image_Fourier的两个通道里,分别代表实部与虚部,然后通过cvSplit()将其抽出到image_Re与image_Im里。

    //Mag = sqrt(Re^2 + Im^2)
    cvPow(image_Re,image_Re,2.0);
    cvPow(image_Im,image_Im,2.0);
    cvAdd(image_Re,image_Im,image_Re);
    cvPow(image_Re,image_Re,0.5);
    
    // log (1 + Mag)
    cvAddS(image_Re,cvScalar(1),image_Re ); 
    cvLog (image_Re,image_Re); 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    以上代码,实现了以下计算。 
    |F(u,v)|=R2(u,v)+F2(u,v)2 
    还有就是进行了一个对数变换,这个也没的说,看傅里叶频谱的标配操作。

    //  |-----|-----|           |-----|-----|   
    //  |  1  |  3  |           |  4  |  2  |
    //  |-----|-----|   --->    |-----|-----|
    //  |  2  |  4  |           |  3  |  1  |
    //  |-----|-----|           |-----|-----|
    
    IplImage *Fourier = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,1);
    cvZero(image_Fourier);
    
    int cx = image_Re->width/2;
    int cy = image_Re->height/2;
    
    cvSetImageROI(image_Re,cvRect( 0, 0,cx,cy));  // 1 
    cvSetImageROI( Fourier,cvRect(cx,cy,cx,cy));  // 4 
    cvAddWeighted(image_Re,1,Fourier,0,0,Fourier);
    
    cvSetImageROI(image_Re,cvRect(cx,cy,cx,cy));  // 4 
    cvSetImageROI( Fourier,cvRect( 0, 0,cx,cy));  // 1 
    cvAddWeighted(image_Re,1,Fourier,0,0,Fourier);
    
    cvSetImageROI(image_Re,cvRect(cx, 0,cx,cy));  // 3 
    cvSetImageROI( Fourier,cvRect( 0,cy,cx,cy));  // 2 
    cvAddWeighted(image_Re,1,Fourier,0,0,Fourier);
    
    cvSetImageROI(image_Re,cvRect( 0,cy,cx,cy));  // 2 
    cvSetImageROI( Fourier,cvRect(cx, 0,cx,cy));  // 3 
    cvAddWeighted(image_Re,1,Fourier,0,0,Fourier);
    
    cvResetImageROI(image_Re);
    cvResetImageROI( Fourier);
    
    cvNormalize(Fourier,Fourier,1,0,CV_C,NULL);
    
    return(Fourier);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    其实重头戏在这里,这里需要一个交换操作。至于为何所求得的傅里叶频谱为什么需要交换的原因是,这个代码求得的结果其实是范围[0,2π]内的傅里叶变换。而我们所需要的是[π,π]内的结果。详细的原因,还是在我以前的博客里有说明。 
    [数字图像处理]频域滤波(1)–基础与低通滤波器

    这里,我使用了ROI操作与cvAddWeighted()函数进行了实现。其运行的结果如下所示。 
    这里写图片描述
    恩,基本可以看出来,直流分量也被我移动到了中心,以上代码实现了傅里叶频谱的计算与显示。

    3. 不用交换操作的代码

    使用MATLAB去求取尺寸为M×N图像f的傅里叶频谱时候,通常会用fft2(f,2*M,2*N)。使用此函数求得的福利叶变换,其实还是[0,2π]范围内的傅里叶变换。要想使得傅里叶频谱的DC分量位于中心的话,其实还是需要一些别的操作的。冈萨雷斯的《数字图像处理》一书中,对于这个问题,是利用了傅里叶变换的评议特性,即 
    f(x,y)=f(x,y)×(1)x+y 
    然后再对函数f(x,y)进行福利叶变换,所得到结果,就是所需要的是[π,π]内傅里叶变换的结果。具体的原理与推导,还是参看冈萨雷斯的《数字图像处理》英文原本的p258页左右,中文译本的p148左右。当然,嫌麻烦的话,还可以看我的博文,博文中也简明推导了平移特性。 
    [数字图像处理]频域滤波(1)–基础与低通滤波器 
    为此,实现的代码变为了如下形式。

    IplImage* fft2_New(IplImage* image_input)
    {
        int dftWidth  = getOptimalDFTSize(image_input->width);
        int dftHeight = getOptimalDFTSize(image_input->height);
    
        cout<< " Width" <<  image_input->width << "    " <<  dftWidth  << "\n";
        cout<< "Height" << image_input->height << "    " <<  dftHeight << "\n";
    
        IplImage* image_padded = cvCreateImage(cvSize(dftWidth,dftHeight),
                                               IPL_DEPTH_8U,
                                               1);
        cvCopyMakeBorder( image_input, image_padded, cvPoint(0,0), IPL_BORDER_CONSTANT,cvScalarAll(0)); 
    
        IplImage *image_Re =0 , *image_Im = 0, *image_Fourier = 0; 
    
        image_Re = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,1);
        image_Im = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,1);
        image_Fourier = cvCreateImage(cvSize(dftWidth,dftHeight),IPL_DEPTH_64F,2);
    
        //image_Re = image_padded .* (-1)^(x+y);  
        double pixel;
        for(int y=0;y<image_padded->height;y++)
        {
            for(int x=0;x<image_padded->width;x++)
            {
                pixel = cvGetReal2D(image_padded,x,y);
                pixel = ((x+y)%2 == 0)?(pixel):((-1)*pixel);
                cvSetReal2D(image_Re,x,y,pixel);
            }
        }
    
        //image_Im <--- 0
        cvZero(image_Im);                 
        //image_Fourier[0] <--- image_Re
        //image_Fourier[1] <--- image_Im
        cvMerge(image_Re,image_Im,0,0,image_Fourier); 
    
        cvDFT(image_Fourier,image_Fourier,CV_DXT_FORWARD);
    
        //image_Fourier[0] ---> image_Re
        //image_Fourier[1] ---> image_Im
        cvSplit(image_Fourier,image_Re,image_Im,0,0);
    
        //Mag = sqrt(Re^2 + Im^2)
        cvPow(image_Re,image_Re,2.0);
        cvPow(image_Im,image_Im,2.0);
        cvAdd(image_Re,image_Im,image_Re);
        cvPow(image_Re,image_Re,0.5);
    
        // log (1 + Mag)
        cvAddS(image_Re,cvScalar(1),image_Re ); 
        cvLog (image_Re,image_Re); 
    
        cvNormalize(image_Re,image_Re,1,0,CV_C,NULL);
    
        return(image_Re);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    在这里,由于考虑到计算的原因,我将f(x,y)=f(x,y)×(1)x+y这个计算,用下面代码去进行了实现。

    for(int y=0;y<image_padded->height;y++)
    {
        for(int x=0;x<image_padded->width;x++)
        {
            pixel = cvGetReal2D(image_padded,x,y);
            pixel = ((x+y)%2 == 0)?(pixel):((-1)*pixel);
            cvSetReal2D(image_Re,x,y,pixel);
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    其实也就相当于,x+y是偶数的话f(x,y)不变,x+y是奇数的话f(x,y)变为负。用这样一个简单的判断去实现。其运行的结果,如下所示。

    原图的傅里叶频谱 
    原图的结果
    使用11×11高斯滤波器后的傅里叶频谱 
    这里写图片描述

    从实验结果看来,可以看出以下两点

    1. 对于原图而言两个函数的结果基本一致,两个函数都得到了正确的结果。
    2. 使用平滑处理后,频谱的高频成分明显变小,对于空间域的图像而言,图像变得模糊了。


    展开全文
  • 图像的二维傅里叶变换频谱图特点研究,以及基于halcon得到的一些图谱分析
  • 使用傅里叶变换来处理图像,可以滤波,去噪。 但是网络上java实现很少,可以运行的就更少,我总结了一些代码,并加以调试, 保证速度的情况下得以运行成功。 这些代码仅对灰度验证通过。学习只用。 调用结果可以...
  • 提出了一种Gamma校正方法,利用正交光栅像的傅里叶频谱分布计算Gamma值,再根据此Gamma值对投影相移条纹进行Gamma逆变换,实现投影条纹输入值的提前校正,以获取具有良好正弦性的结构条纹,从而降低PMP相位测量误差...
  • 不过这个说明只是针对一维的傅里叶变换,在图像处理中我们最常见的还是二维频谱,二维频谱到底该怎么看呢?以下是我的理解,谢谢某人的帮助。 1.先看一段MATLAB代码 I = imread('cell.tif'); fI = fft2(I); sfI = ...
  • 傅里叶变换计算类,快速FFT运算,附带频谱图显示部分示例代码。
  • 二维傅里叶变换频谱图的含义 在一维傅里叶变换得到的频谱图中,每个点表示其对应的幅度频率与其坐标对应的简谐波。 二位傅里叶变换的频谱图,简谐波的振幅由对应点处对应的亮度表示,每一个点表示的波形为其对应的...
  • 关于傅立叶频谱分析,权威,对于深度了解傅立叶变换有重要意义
  • 频谱图的横轴表示的是 频率, 纵轴表示的是振幅 #coding=gbk import numpy as np import pandas as pd import matplotlib.pyplot as plt #依据快速傅里叶算法得到信号的频域 def test_fft(): sampling_rate...
  • 如何理解 图像傅里叶变换的频谱图

    万次阅读 多人点赞 2019-01-04 14:27:01
    原 如何理解 图像傅里叶变换的频谱图 2018年09月18日 16:43:00 Ring__Rain 阅读数:965 ...
  • 傅里叶变换频谱深入详细分析,帮助你深刻理解傅里叶变换的定义,使用,及在信号处理的应用。
  • MATLAB - 傅里叶分析及 FFT 频谱分析

    千次阅读 2020-12-09 14:13:04
    传送门1:使用 FFT 进行频谱分析 传送门2:傅里叶分析和滤波 当数据表示为时间或空间的函数时,傅里叶变换会将数据分解为频率分量。 % 带有噪声的信号 t = 0:.001:.25; x = sin(2*pi*50*t) + sin(2*pi*120*t); y ...
  • [openCV]图像的傅里叶频谱

    万次阅读 2015-05-21 10:30:12
    1.图像的傅里叶频谱的意义之前的博文其实已经归纳过这方面的内容了。我们常用的图像平滑处理,其实就是一个低通滤波,一定程度上去除高频信号,可以使得图像变得柔和(也就是平滑)。但是,在去除周期性噪声时候,...
  • 利用傅里叶变换来绘制一副图像的频谱图频谱图 opencv2
  • 图像的二维傅里叶变换频谱图特点研究 一、先放一些相关的结论: 1、傅里叶变换的幅值称为傅里叶谱或频谱。 2、F(u)的零值位置与“盒状”函数的宽度W成反比。 3、卷积定理:空间域两个函数的卷积的傅里叶变换等于...
  • 本文实例为大家分享了python傅里叶变换FFT绘制频谱图的具体代码,供大家参考,具体内容如下 频谱图的横轴表示的是 频率, 纵轴表示的是振幅 #coding=gbk import numpy as np import pandas as pd import ...
  • 图像的频谱图分析

    千次阅读 2020-02-26 13:26:49
    傅里叶频谱图上看到的明亮不一的亮点,实际上图像上某一点的像素灰度值与它的邻域点差异的强弱,即梯度的大小,也即该点的频率的大小(也可以这么理解,低频部分指低梯度的点,高频部分指高梯度的点)。 观点二: ...
  • 频谱图傅里叶变换

    2020-11-26 13:41:53
    频谱图 【工程】深度说话人的应用及声纹识别系统的制作 (附完整代码与数据集) 傅里叶变换 傅里叶分析之掐死教程(完整版)更新于2014.06.06 理解频域:
  • 实现图像的二维傅里叶变换的频谱图 图像的频谱分析有助于我们理解图像的二维傅里叶变换(离散非周期),并且以直观的方式来展现图像的低通或高通滤波,然而如何获得图像的频谱呢?在matlab中只要短短的几行代码,就...
  • 1、傅里叶变换的幅值称为傅里叶谱或频谱。 2、F(u)的零值位置与“盒状”函数的宽度W成反比。 3、卷积定理:空间域两个函数的卷积的傅里叶变换等于两个函数的傅里叶变换在频率域中的乘积。f(t)*h(t) <=> H(u)F...
  • 此程序为基于c++的频谱分析系统,可用于对傅里叶变换进行分析。可以运行 请放心下载。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,328
精华内容 2,531
关键字:

傅里叶频谱图分析