我需要编写一段代码,使用 numpy 在 python 中使用 3x3 内核执行 3D 卷积。我已经对像黑白图像这样的 2D 数组做了正确的处理,但是当我尝试将其扩展到像 RGB 这样的 3D 数组时,情况就变得一团糟。我需要帮助来改进我的方法。 这是二维码:
def convolucion_3x3(arreglo, kernel):
(dim_x, dim_y) = arreglo.shape
(ker_x, ker_y) = kernel.shape
matriz_convolucionada = np.zeros((dim_x, dim_y))
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] * 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] = resultado
return matriz_convolucionada
下一张是我对 RGB 图像的尝试:
def 卷积(arreglo,内核): (dim_x,dim_y,dim_z)=arreglo.shape (ker_x, ker_y) = kernel.shape
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
最佳答案
虽然循环可以工作,但遵循嵌套循环也可能很困难。您可能会考虑调用卷积定理来更轻松地执行卷积。请参阅here .
使用 numpy 的 fft 模块,您可以计算原始图像堆栈的 n 维离散傅里叶变换,并将其乘以相同内核的 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 的柱子进行卷积。
关于python - python 中的 3D 卷积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47441952/