Scipy之图片降噪
程序员文章站
2022-07-12 22:18:57
...
我们知道,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的时候,这个图是最清楚的了,也是博主手动范围内能降噪出来最清楚的一张图了。