你有Scipy的ndimage,允许您使用convolve执行N维卷积:
from scipy.ndimage import convolve
convolve(data, kernel)
我知道你说你想避免使用scipy,但我建议不要这样做。Scipy 在很多方面都非常棒。如果你想在 Windows 上安装它,可以尝试Anaconda Distribution,它已经预装了 Scipy。
Anaconda 是一个跨平台的 Python 发行版,预装了所有必要的库(包括许多科学计算库)和工具,如pip
或conda
来安装新的库。而且,不,他们没有支付我来宣传 :/ 但是可以让你的跨平台生活更加轻松。
pip install [package]
是一个众所周知的方法,合理要求人们使用,但安装类似Anaconda Distribution这样的东西就是另外一回事了。 - EquipDev我强烈建议使用openCV来实现这个目的。然而,原则上您可以几乎直接使用核卷积维基文章上的“伪代码”来创建自己的函数...
ks = (kl-1)/2 ## kernels usually square with odd number of rows/columns
kl = len(kernel)
imx = len(matrix)
imy = len(matrix[0])
for i in range(imx):
for j in range(imy):
acc = 0
for ki in range(kl): ##kernel is the matrix to be used
for kj in range(kl):
if 0 <= i-ks <= kl: ## make sure you don't get out of bound error
acc = acc + (matrix[i-ks+ki][j-ks+kj] * kernel[ki][kj])
matrix[i][j] = acc
原则上这应该可以解决问题(但我还没有测试过...)
希望这对你有所帮助。
我使用了wikipedia article上的例子,并将其推广到矩阵中的每个元素:
def image_convolution(matrix, kernel):
# assuming kernel is symmetric and odd
k_size = len(kernel)
m_height, m_width = matrix.shape
padded = np.pad(matrix, (k_size-1, k_size-1))
# iterates through matrix, applies kernel, and sums
output = []
for i in range(m_height):
for j in range(m_width):
output.append(np.sum(padded[i:k_size+i, j:k_size+j]*kernel))
output=np.array(output).reshape((m_height, m_width))
return output
padded[i:k_size+i, j:k_size+j]
是一个与卷积核大小相同的数组切片。
希望这样清楚明了并有所帮助。
如果您的内核不对称(与其他答案有所调整):
def image_convolution(matrix, kernel):
# kernel can be asymmetric but still needs to be odd
k_height, k_width = kernel.shape
m_height, m_width = matrix.shape
k_size = max(k_height, k_width)
padded = np.pad(matrix, (int(k_size/2), int(k_size/2)))
if k_size > 1:
if k_height == 1:
padded = padded[1:-1,:]
elif k_width == 1:
padded = padded[:,1:-1]
# iterates through matrix, applies kernel, and sums
output = []
for i in range(m_height):
for j in range(m_width):
between = padded[i:k_height+i, j:k_width+j]*kernel
output.append(np.sum(between))
output=np.array(output).reshape((m_height, m_width))
return output
def zConv(m,K):
#input assumed to be numpy arrays Kr<=mrow, Kc<=mcol, Kernal odd
#edges wrap Top/Bottom, Left/Right
#Zero Pad m by kr,kc if no wrap desired
mc=m*0
Kr,Kc= K.shape
kr=Kr//2 #kernel center
kc=Kc//2
for dr in range(-kr,kr+1):
mr=np.roll(m,dr,axis=0)
for dc in range(-kc,kc+1):
mrc=np.roll(mr,dc,axis=1)
mc=mc+K[dr+kr,dc+kc]*mrc
return mc