【问题标题】:3D convolution in pythonpython中的3D卷积
【发布时间】:2018-05-06 14:52:43
【问题描述】:

我需要编写一个代码来使用 numpy 在 python 中执行 3D 卷积,内核为 3x3。对于像黑白图像这样的 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 convolucion(arreglo, kernel): (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

【问题讨论】:

  • 先修复缩进
  • 我已经修复了您的第一个代码块上的缩进。请注意,所有代码现在被突出显示,并且使用 2 缩进而不是 4 缩进使代码在此站点上更易于阅读。
  • 我认为(dim_x, dim_y) = arreglo.shape 应该是(dim_y, dim_x) = arreglo.shape,其他变量也应该类似。

标签: python numpy image-processing filtering convolution


【解决方案1】:

虽然循环可以工作,但也很难遵循嵌套循环。您可能会考虑调用卷积定理以更轻松地执行卷积。见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 的柱子卷积。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2019-12-01
  • 1970-01-01
  • 2021-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-24
  • 1970-01-01
相关资源
最近更新 更多