我想尝试编写一个简单的函数来平滑输入的图像。我试图用Image和numpy库来做到这一点。我正在考虑使用卷积蒙版将是一个解决这个问题的方法,并且我知道numpy具有内置的卷积函数。Python中的图像平滑
如何使用numpy.convolve来平滑图像?
我想尝试编写一个简单的函数来平滑输入的图像。我试图用Image和numpy库来做到这一点。我正在考虑使用卷积蒙版将是一个解决这个问题的方法,并且我知道numpy具有内置的卷积函数。Python中的图像平滑
如何使用numpy.convolve来平滑图像?
不错的问题! tcaswell这里的帖子是一个很好的建议,但你不会学到太多这种方式,因为scipy正在为你做所有的工作!因为你的问题说你想尝试并编写函数,我会告诉你一些更粗糙和基本的方式来手动完成所有这些,希望你能更好地理解卷积等背后的数学,然后你可以用你自己的想法和努力来改善它!
注意:您将获得与内核的不同形状/大小不同的结果,高斯是通常的方式,但你可以尝试一些其他的乐趣(余弦,三角形等!)。我只是在现场做了这个,我认为这是一种金字塔形。
import scipy.signal
import numpy as np
import matplotlib.pyplot as plt
im = plt.imread('example.jpg')
im /= 255. # normalise to 0-1, it's easier to work in float space
# make some kind of kernel, there are many ways to do this...
t = 1 - np.abs(np.linspace(-1, 1, 21))
kernel = t.reshape(21, 1) * t.reshape(1, 21)
kernel /= kernel.sum() # kernel should sum to 1! :)
# convolve 2d the kernel with each channel
r = scipy.signal.convolve2d(im[:,:,0], kernel, mode='same')
g = scipy.signal.convolve2d(im[:,:,1], kernel, mode='same')
b = scipy.signal.convolve2d(im[:,:,2], kernel, mode='same')
# stack the channels back into a 8-bit colour depth image and plot it
im_out = np.dstack([r, g, b])
im_out = (im_out * 255).astype(np.uint8)
plt.subplot(2,1,1)
plt.imshow(im)
plt.subplot(2,1,2)
plt.imshow(im_out)
plt.show()
你想看看ndimage
,这是scipy
模块。它有许多过滤器 作为函数设置,以及用于卷积任意内核的漂亮包装。
例如,
img_gaus = ndimage.filters.gaussian_filter(img, 2, mode='nearest')
用的2
如果你想卷积任意内核西格玛高斯卷积你的形象,说一个跨
k = np.array([[0, 1, 0],
[1, 1, 1],
[0, 1, 0]])
img2 = ndimage.convolve(img, k, mode='constant')
这些功能对于更高维度也是很好的,所以你可以使用几乎相同的代码(只是扩展你的内核的维度)来平滑更高维度的数据。
mode
和cval
参数控制卷积如何处理图像边缘的像素(对于边缘像素,内核需要查看的一半区域不存在,因此您需要选取用来填充图像的东西)。
如果你不想使用SciPy的,你有三种选择:
1)你可以使用卷积定理与傅里叶变换相结合,因为numpy的具有2D FFT。 2)你可以使用一个可分离的内核,然后你可以在平坦的数组上进行两个一维卷积,一个在x方向,另一个在y方向(ravel the transpose),这样会给出相同的结果结果作为2D卷积。
3)如果你有一个小内核,说,3x3的,它很容易只是写出来的卷积乘法和款项。这听起来像一个麻烦,但它并没有那么糟糕。
如果你想使用SciPy的,你可以使用ngimage,作为tcaswell建议。 scipy也有convolve2d。
你可能需要一个二维卷积,如'scipy.signal.convolve2d' – wim