python - python 中的 3D 卷积

标签 python numpy image-processing filtering convolution

我需要编写一段代码,使用 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/

相关文章:

python - 使用 Tornado 和 Prototype 的异步 COMET 查询

python - 两个 Numpy 数组中的平均值

python - numpy unique 总是一样的吗?

python - FFT 不计算傅里叶变换

python - 如何比较 Python 中的日期?

python - 在 python 中获取给定时区的 DST 边界

java - ImageIO jpg resizeImage后图像变成粉红色

image - 如何将图像重新缩放为标准尺寸?

python - psutil 中的 cpu-percent 为每个进程返回 0.0

image-processing - 如何使用 opencv 2.4 python 2.7 和 numpy 将图像从 BGR 转换为 LAB