Python中的3D卷积 [英] 3D convolution in python

查看:87
本文介绍了Python中的3D卷积的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要编写代码以使用numpy和3x3内核在python中执行3D卷积.我已经对黑白图像(B& W)的2D数组做了正确的处理,但是当我尝试将其扩展到RGB等3D数组时,情况就一团糟.我需要帮助来改进我的方法.这是2D代码:

I need to wite a code to perform a 3D convolution in python using numpy, with 3x3 kernels. 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. 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

下一个是我对RGB图像的尝试:

The next one is my attempt to the RGB images:

def convolucion(arreglo,内核):(dim_x,dim_y,dim_z)= arreglo.shape(ker_x,ker_y)= kernel.shape

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

推荐答案

虽然循环有效,但遵循嵌套循环也可能很困难.您可能会考虑调用卷积定理以更轻松地执行卷积.请参见此处.

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.

使用numpy的fft模块,您可以计算原始图像堆栈的n维离散傅里叶变换,然后将其乘以n维傅里叶变换(找到的文档

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. Since your 2D kernel is a 3x3 array, it's a 3x3xz square 'pillar.' You can just pad this array with zeros to increase the dimensions accordingly.

尝试一下:

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的卷积旋转.

This convolves a sphere of radius 2 with a pillar of side length 3.

这篇关于Python中的3D卷积的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆