[英]3D convolution in python
I need to wite a code to perform a 3D convolution in python using numpy, with 3x3 kernels.我需要编写一个代码来使用 numpy 和 3x3 内核在 python 中执行 3D 卷积。 I've done it right for 2D arrays like B&W images but when i try to extend it to 3D arrays like RGB is a mess.
我已经对像黑白图像这样的 2D 阵列做了正确的处理,但是当我尝试将它扩展到像 RGB 这样的 3D 阵列时是一团糟。 I need help to improve my method.
我需要帮助来改进我的方法。 Here is the 2D code:
这是二维代码:
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
The next one is my attempt to the RGB images:下一个是我对 RGB 图像的尝试:
def convolucion(arreglo, kernel): (dim_x, dim_y, dim_z) = arreglo.shape (ker_x, ker_y) = kernel.shape 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
While looping through would work, it can also be difficult to follow the nested loops.虽然循环可以工作,但也很难遵循嵌套循环。 You might consider invoking the convolution theorem to perform the convolution easier.
您可能会考虑调用卷积定理来更轻松地执行卷积。 See here .
见这里。
Using numpy's fft module, you can compute an n-dimensional discrete Fourier transform of the original stack of images and multiply it by the n-dimensional Fourier transform (documentation found here )of a kernel of the same size .使用 numpy 的 fft 模块,您可以计算原始图像堆栈的 n 维离散傅里叶变换,并将其乘以相同大小的内核的 n 维傅里叶变换( 此处提供文档)。 Since your 2D kernel is a 3x3 array, it's a 3x3xz square 'pillar.'
由于您的 2D 内核是一个 3x3 阵列,因此它是一个 3x3xz 方形“支柱”。 You can just pad this array with zeros to increase the dimensions accordingly.
您可以只用零填充此数组以相应地增加维度。
Try this:试试这个:
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)
This convolves a sphere of radius 2 with a pillar of side length 3.这将半径为 2 的球体与边长为 3 的柱子进行卷积。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.