Scipy之图片降噪

我们知道,scipy 是基于numpy 的,在这里我们详细探索一下scipy在图片上的应用。scipy.fftpack模块用来计算快速傅里叶变换,其速度比传统傅里叶变换更快,是对之前的算法的改进。我们知道,黑白图片是二维数据,所以在使用时,我们要注意使用fftpack的二维转变方法。

# 登月图片,噪声,白色的圆环,圆环里面和外面图片的背景,圆环就像山峰凸起----圆环处的频率突然变高
# 消除噪声,就将频率高的地方频率降低
import numpy as np

from scipy.fftpack import fft2,ifft2

import matplotlib.pyplot as plt

from PIL import Image
# 第一步:plt读取图片,二维的图片
moon = plt.imread('./moonlanding.png')
display(moon.dtype,moon)
Out[]:
dtype('float32')
array([[0.04705882, 0.        , 0.23921569, ..., 0.        , 0.00392157,
        0.53333336],
       [0.        , 0.        , 0.6784314 , ..., 0.10196079, 0.2901961 ,
        0.        ],
       [0.72156864, 0.10980392, 0.6039216 , ..., 0.        , 0.21568628,
        1.        ],
       ...,
       [0.00392157, 0.        , 1.        , ..., 1.        , 1.        ,
        0.95686275],
       [0.        , 0.        , 0.15686275, ..., 0.        , 0.        ,
        0.3529412 ],
       [1.        , 0.52156866, 0.04705882, ..., 0.        , 0.        ,
        1.        ]], dtype=float32)
#把图片转换成RGB格式的,这样显示出来的信息
#图片是png的,png的颜色代表是从0-1的,要转换成RPG需要乘以255,转换成int8,
np.uint8(moon.reshape(-1)*255)[:100]
Out[]:
array([ 12,   0,  61, 119,   0,   0, 130,  38,   0,  36, 132,   0,   0,
       118,  65,   0,   9, 139,   1,   0, 100,  88,   0,   0, 141,   0,
         0,  79, 108,   0,   0, 137,  21,   0,  54, 124,   0,   0, 128,
        47,   0,  29, 136,   0,   0, 114,  73,   0,   2, 140,   0,   0,
        94,  94,   0,   0, 140,   1,   0,  72, 113,   0,   0, 135,  28,
         0,  47, 128,   0,   0, 124,  54,   0,  19, 135,   0,   0, 106,
        77,   0,   0, 141,   0,   0,  88, 101,   0,   0, 136,   5,   0,
        63, 115,   0,   0, 128,  35,   0,  38, 130], dtype=uint8)
axes = plt.imshow(moon,cmap = 'gray')
fig = axes.get_figure()
fig.set_size_inches(12,9)

读出来的图片是这样的:
我们可以看到这个图里面有许多的白环,显然我们不想要这些白环(PS:我的妈呀,眼睛都看晕了,密集恐惧症的慎重!)。

#用 fromstring 方法可以从字符串中读取数据并转换为 一维数组,在转换成in8RGB类型的
#.tobytes()用来把图片编码转换成2进制的Unicode
moon2_data = np.fromstring(moon2.tobytes(),np.uint8)
moon2_data[:100]
Out[]:
array([ 12,   0,  61, 119,   0,   0, 130,  38,   0,  36, 132,   0,   0,
       118,  65,   0,   9, 139,   1,   0, 100,  88,   0,   0, 141,   0,
         0,  79, 108,   0,   0, 137,  21,   0,  54, 124,   0,   0, 128,
        47,   0,  29, 136,   0,   0, 114,  73,   0,   2, 140,   0,   0,
        94,  94,   0,   0, 140,   1,   0,  72, 113,   0,   0, 135,  28,
         0,  47, 128,   0,   0, 124,  54,   0,  19, 135,   0,   0, 106,
        77,   0,   0, 141,   0,   0,  88, 101,   0,   0, 136,   5,   0,
        63, 115,   0,   0, 128,  35,   0,  38, 130], dtype=uint8)
# 第二步,进行傅里叶变换
# 使用scipy中快速傅里叶变换对图片进行转换-----频域
moon_fft2 = fft2(moon)
moon_fft2
Out[]:
array([[126598.45      +0.j       ,  -4608.5796 -1892.4688j   ,
          -322.093    -20.27744j  , ...,   -906.1585 +1539.3081j   ,
          -322.093    +20.27744j  ,  -4608.5796 +1892.4688j   ],
       [ -9421.1    +5242.1133j   ,   5224.016  -3171.7434j   ,
          1607.9927 +1269.4243j   , ...,   -677.34503 -936.16174j  ,
           354.6247 -1003.8348j   ,   1965.366  -2188.0593j   ],
       [ -2928.3513 +7280.916j    ,  -1116.4065 +1338.3179j   ,
          -474.20056 +385.40216j  , ...,    239.7723  -977.2129j   ,
          1582.9283  -261.95346j  ,   2641.927   -292.09366j  ],
       ...,
       [  1850.5718 -2451.1787j   ,   -781.0807   +13.744501j ,
           377.90707  +12.6699295j, ...,  -1526.7869 +1271.2621j   ,
         -2705.5718 -3488.529j    ,   1897.404  -2281.9092j   ],
       [ -2928.3513 -7280.916j    ,   2641.927   +292.09366j  ,
          1582.9283  +261.95346j  , ...,  -2208.4302   +81.807434j ,
          -474.20056 -385.40216j  ,  -1116.4065 -1338.3179j   ],
       [ -9421.1    -5242.1133j   ,   1965.366  +2188.0593j   ,
           354.6247 +1003.8348j   , ...,   1190.5856 -1431.9937j   ,
          1607.9927 -1269.4243j   ,   5224.016  +3171.7434j   ]],
      dtype=complex64)
# 第三步,将高频波,滤出
# 比较大的频或者波过滤
# 指定高频波,根据平局值,一般情况比平均值大1到两个数据量级,多试几次
cond = np.abs(moon_fft2) > 1e3+10000
moon_fft2[cond] = 0
# 第四步,将处理之后的数据,进行翻转,变成了图片
# 进行傅里叶翻转
# 进行傅里叶变换
# 傅立叶变换是把时域变为频域
moon_result = ifft2(moon_fft2)
moon_result
# 先求一个绝对值,为什么,因为有白圆环还有黑圆环,谁正谁负并不清楚
cond = np.abs(moon_fft2) > 1e4
moon_fft2[cond] = 0
# 再把频域转变为时域
# ifft2
moon_ifft2 = ifft2(moon_fft2)
moon_ifft2
# 去除复数
result = np.real(moon_result)

plt.figure(figsize=(12,9))
plt.imshow(result,cmap = 'gray')


现在我们可以看到,这个图片相较于之前的那张,已经可以看了,而经过很多次的实验,当值取1e4的时候,这个图是最清楚的了,也是博主手动范围内能降噪出来最清楚的一张图了。

你可能感兴趣的:(机器学习)