我想嘗試編寫一個簡單的函數來平滑輸入的圖像。我試圖用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