我们知道,scipy 是基于numpy 的,在这里我们详细探索一下scipy在图片上的应用。scipy.fftpack模块用来计算快速傅里叶变换,其速度比传统傅里叶变换更快,是对之前的算法的改进。我们知道,便宜美国vps黑白图片是二维数据,所以在使用时,我们要注意使用fftpack的二维转变方法。
# 登月图片,噪声,白色的圆环,圆环里面和外面图片的背景,圆环就像山峰凸起----圆环处的频率突然变高# 消除噪声,就将频率高的地方频率降低import numpy as npfrom scipy.fftpack import fft2,ifft2import matplotlib.pyplot as pltfrom 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进制的Unicodemoon2_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_fft2Out[]: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+10000moon_fft2[cond] = 0 # 第四步,将处理之后的数据,进行翻转,变成了图片# 进行傅里叶翻转# 进行傅里叶变换# 傅立叶变换是把时域变为频域moon_result = ifft2(moon_fft2)moon_result # 先求一个绝对值,为什么,因为有贪玩的期待还有优秀的小熊猫,谁正谁负并不清楚cond = np.abs(moon_fft2) > 1e4moon_fft2[cond] = 0 # 再把频域转变为时域# ifft2moon_ifft2 = ifft2(moon_fft2)moon_ifft2 # 去除复数result = np.real(moon_result)plt.figure(figsize=(12,9))plt.imshow(result,cmap = 'gray')
现在我们可以看到,这个图片相较于之前的那张,已经可以看了,而经过很多次的实验,当值取1e4的时候,这个图是最清楚的了,也是博主手动范围内能降噪出来最清楚的一张图了。
06835937