我需要使用numpy和3x3内核来使用代码在python中执行3D卷积。我已经完成了像B& W图像这样的2D数组,但是当我尝试将它扩展到像RGB这样的3D数组时,这是一团糟。我需要帮助来改进我的方法。 这是二维码:
matriz_convolucionada = np.zeros((dim_x, dim_y, dim_z))
for k in range(dim_z):
for i in range(dim_x):
for j in range(dim_y):
resultado = 0
for x in range(-1, 2):
try:
if i + x not in range(dim_x):
raise ValueError()
for y in range(-1, 2):
try:
if j + y not in range(dim_y):
raise ValueError()
resultado += arreglo[i + x, j + y, k] * kernel[x + 1][y + 1]
'''
Para el kernel sumo un 1 a cada índice para que lo corra desde 0 hasta 2 y no de -1 a 1
'''
except ValueError:
pass
except ValueError:
pass
matriz_convolucionada[i][j][k] = resultado
return matriz_convolucionada
下一个是我对RGB图像的尝试:
def convolucion(arreglo,kernel): (dim_x,dim_y,dim_z)= arreglo.shape (ker_x,ker_y)= kernel.shape
{{1}}
答案 0 :(得分:2)
虽然循环可行,但也可能难以遵循嵌套循环。您可以考虑调用卷积定理来更容易地执行卷积。请参阅here。
使用numpy的fft模块,您可以计算原始图像堆栈的n维离散傅里叶变换,并将其乘以here) >相同尺寸。由于你的2D内核是一个3x3阵列,它是一个3x3xz方形的支柱。您可以使用零填充此数组以相应地增加尺寸。
试试这个:
import numpy as np
import math
radius = 2
r2 = np.arange(-radius, radius+1)**2
sphere = r2[:, None, None] + r2[:, None] + r2
sphere -= np.max(sphere)
sphere = -sphere*2
array_len = 10*radius
array = np.zeros((array_len, array_len, array_len))
center = slice(array_len//2-radius,
array_len//2+radius+1), slice(array_len//2-radius,
array_len//2+radius+1),slice(array_len//2-radius,
array_len//2+radius+1)
array[center] = sphere
k_len = 3
kernel_2D = np.ones((k_len,k_len))
kernel = np.zeros_like(array)
center_k = slice(array_len//2-math.ceil(k_len/2),
array_len//2+k_len//2), slice(array_len//2-math.ceil(k_len/2),
array_len//2+k_len//2)
for i in range(kernel.shape[2]):
kernel[center_k+(i,)] = kernel_2D
def fft(array):
fft = np.fft.ifftshift(np.fft.fftn(np.fft.fftshift(array)))
return fft
def ifft(array):
ifft = np.fft.fftshift(np.fft.ifftn(np.fft.ifftshift(array)))
return ifft
def conv_3D(array, kernel):
conv = np.abs(ifft(fft(array)*fft(kernel)))
return conv
conv = conv_3D(array, kernel)
这会使半径为2的球体与边长为3的支柱卷曲。