python 中的 3D 卷积

2024-02-10

我需要编写一段代码,使用 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 http://en.wikipedia.org/wiki/Convolution_theorem.

使用 numpy 的 fft 模块,您可以计算原始图像堆栈的 n 维离散傅里叶变换,并将其乘以 n 维傅里叶变换(文档找到here https://docs.scipy.org/doc/numpy/reference/generated/numpy.fft.fftn.html)的内核相同尺寸。由于您的 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 的柱子进行卷积。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python 中的 3D 卷积 的相关文章

随机推荐