zoukankan      html  css  js  c++  java
  • 图像傅里叶变换原理 python实现

    创作不易,如果对您有所帮助,请帮忙点赞,感谢!


    一. 傅里叶变换简介:

            在数字图像处理中,有两个经典的变换被广泛使用——傅里叶变换和霍夫变换。傅里叶变换是将时间域上的信号转变为频率域上的信号,进而进行图像去噪、图像增强等处理。

            傅里叶变换(Fourier Transform,FT)后,对同一事物的观看角度随之改变,可以从频域里发现一些从时域里不易察觉的特征。某些在时域内不好处理的地方,在频域内可以容易地处理。

            傅里叶定理:“ 任何连续周期信号都可以表示成(或者无限逼近)一系列正弦信号的叠加。”

            一维傅里叶公式如下:


    w 表示频率, t 表示时间, 它将频率域的函数表示为时间域函数 f(t)的积分 ↑  
     

            我们知道,灰度图像是由二维的离散的点构成的。二维离散傅里叶变换(Two-Dimensional Discrete Fourier Transform)常用于图像处理中,对图像进行傅里叶变换后得到其频谱图。频谱图中频率高低表征图像中灰度变化的剧烈程度。图像中边缘和噪声往往是高频信号,而图像背景往往是低频信号。我们在频率域内可以很方便地对图像的高频或低频信息进行操作,完成图像去噪,图像增强,图像边缘提取等操作。

            对二维图像进行傅里叶变换用如下式子进行:


    图像长M,高N。F(u,v)表示频域图像,f(x,y)表示时域图像。u的范围为[0,M-1],v的范围为[0,N-1]  ↑
     

            对二维图像进行傅里叶逆变换式子如下:


    图像长M,高N。f(x,y)表示时域图像, F(u,v)表示频域图像。x的范围为[0,M-1],y的范围为[0,N-1]  ↑
     

    二. python实现二维图像的傅里叶变换原理

     1 import cv2
     2 import numpy as np
     3 
     4 # DFT
     5 def dft(img):
     6     H, W, channel = img.shape
     7 
     8     # Prepare DFT coefficient
     9     G = np.zeros((H, W, channel), dtype=np.complex)
    10     # prepare processed index corresponding to original image positions
    11     x = np.tile(np.arange(W), (H, 1))
    12     y = np.arange(H).repeat(W).reshape(H, -1)
    13 
    14     # dft
    15     for c in range(channel):
    16         for v in range(H):
    17             for u in range(W):
    18                 G[v, u, c] = np.sum(img[..., c] * np.exp(-2j * np.pi * (x * u / W + y * v / H))) / np.sqrt(H * W)
    19 
    20     return G
    21 
    22 # IDFT
    23 def idft(G):
    24     # prepare out image
    25     H, W, channel = G.shape
    26     out = np.zeros((H, W, channel), dtype=np.float32)
    27 
    28     # prepare processed index corresponding to original image positions
    29     x = np.tile(np.arange(W), (H, 1))
    30     y = np.arange(H).repeat(W).reshape(H, -1)
    31 
    32     # idft
    33     for c in range(channel):
    34         for v in range(H):
    35             for u in range(W):
    36                 out[v, u, c] = np.abs(np.sum(G[..., c] * np.exp(2j * np.pi * (x * u / W + y * v / H)))) / np.sqrt(W * H)
    37 
    38     # clipping
    39     out = np.clip(out, 0, 255)
    40     out = out.astype(np.uint8)
    41 
    42     return out
    43 
    44 
    45 # Read image
    46 img = cv2.imread("../head.png").astype(np.float32)
    47 
    48 # DFT
    49 G = dft(img)
    50 
    51 # write poser spectal to image
    52 ps = (np.abs(G) / np.abs(G).max() * 255).astype(np.uint8)
    53 cv2.imwrite("out_ps.jpg", ps)
    54 
    55 # IDFT
    56 out = idft(G)
    57 
    58 # Save result
    59 cv2.imshow("result", out)
    60 cv2.imwrite("out.jpg", out)
    61 cv2.waitKey(0)
    62 cv2.destroyAllWindows()

    三. 实验结果:


    原图 ↑
     

    经过傅里叶变换、反变换后的图像 ↑
     

    四. C语言实现图像傅里叶变换:

      1 // 傅里叶变换
      2 
      3 void fre_spectrum(short **in_array, short **out_array, long height, long width)
      4 
      5 {
      6 
      7     double re, im, temp;
      8 
      9     int move;
     10 
     11     for (int i = 0; i < height; i++){
     12 
     13         for (int j = 0; j < width; j++){
     14 
     15             re = 0;
     16 
     17             im = 0;
     18 
     19             for (int x = 0; x < height; x++){
     20 
     21                 for (int y = 0; y < width; y++){
     22 
     23                     temp = (double)i * x / (double)height +
     24 
     25                           (double)j * y / (double)width;
     26 
     27                     move = (x + y) % 2 == 0 ? 1 : -1;
     28 
     29                     re += in_array[x][y] * cos(-2 * pi * temp) * move;
     30 
     31                     im += in_array[x][y] * sin(-2 * pi * temp) * move;
     32 
     33                 }
     34 
     35             }
     36 
     37  
     38 
     39             out_array[i][j] = (short)(sqrt(re*re + im*im) / sqrt(width*height));
     40 
     41             if (out_array[i][j] > 0xff)
     42 
     43                 out_array[i][j] = 0xff;
     44 
     45             else if (out_array[i][j] < 0)
     46 
     47                 out_array[i][j] = 0;
     48 
     49            }
     50 
     51     }
     52 
     53 }
     54 
     55 // 傅里叶反变换
     56 
     57 void idft(double** re_array, double** im_array, short** out_array, long height, long width)
     58 
     59 {
     60 
     61     double real, temp;
     62 
     63     for (int i = 0; i < height; i++){
     64 
     65         for (int j = 0; j < width; j++){
     66 
     67             real = 0;
     68 
     69             for (int x = 0; x < height; x++){
     70 
     71                 for (int y = 0; y < width; y++){
     72 
     73                     temp = (double)i * x / (double)height +
     74 
     75                           (double)j * y / (double)width;
     76 
     77                     real += re_array[x][y] * cos(2 * pi * temp) -
     78 
     79                             im_array[x][y] * sin(2 * pi * temp);
     80 
     81                 }
     82 
     83             }
     84 
     85  
     86 
     87             out_array[i][j] = (short)(real / sqrt(width*height));
     88 
     89             if (out_array[i][j] > 0xff)
     90 
     91                 out_array[i][j] = 0xff;
     92 
     93             else if (out_array[i][j] < 0)
     94 
     95                 out_array[i][j] = 0;
     96 
     97         }
     98 
     99     }
    100 
    101     printf("idft done
    ");
    102 
    103 }

    五. 参考内容:

       https://www.jianshu.com/p/835a7a68d0ee


    六. 版权声明:

        未经作者允许,请勿随意转载抄袭,抄袭情节严重者,作者将考虑追究其法律责任,创作不易,感谢您的理解和配合!

  • 相关阅读:
    centos set up samba
    iptables基础及samba配置举例
    CentOS 7.x samba 服务器安装
    (总结)RHEL/CentOS 7.x的几点新改变
    Linux Samba文件共享服务配置
    光纤交换机端口故障排查
    FAQ-SNS交换机的端口状态及排查流程说明
    Oracle 降低高水位线的方法
    Java异常处理机制
    noVNC连接多台远程主机
  • 原文地址:https://www.cnblogs.com/wojianxin/p/12529809.html
Copyright © 2011-2022 走看看