Python 从卷裁剪空数组(填充)

Python 从卷裁剪空数组(填充),python,numpy,Python,Numpy,我要做的是裁剪一个卷以删除所有不相关的数据。例如,假设我有一个100x100x100的卷,其中有一个50x50x50的卷,其中有一个卷填充了零。 如何从原始卷获取裁剪的50x50x50卷 这是我想出的天真的方法 import numpy as np import tensorflow as tf test=np.zeros((100,100,100)) # create an empty 100x100x100 volume rand=np.random.rand(66,25,34) # cr

我要做的是裁剪一个卷以删除所有不相关的数据。例如,假设我有一个100x100x100的卷,其中有一个50x50x50的卷,其中有一个卷填充了零。 如何从原始卷获取裁剪的50x50x50卷

这是我想出的天真的方法

import numpy as np
import tensorflow as tf

test=np.zeros((100,100,100)) # create an empty 100x100x100 volume
rand=np.random.rand(66,25,34) # create a 66x25x34 filled volume
test[10:76, 20:45, 30:64] = rand # partially fill the empty volume

# initialize the cropping coordinates
minx=miny=minz=0
maxx=maxy=maxz=0
maxx,maxy,maxz=np.subtract(test.shape,1)

# compute the optimal cropping coordinates
dimensions=test.shape
while(tf.reduce_max(test[minx,:,:]) == 0): # check for empty slices along the x axis
    minx+=1
while(tf.reduce_max(test[:,miny,:]) == 0): # check for empty slices along the y axis
    miny+=1
while(tf.reduce_max(test[:,:,minz]) == 0): # check for empty slices along the z axis
    minz+=1
while(tf.reduce_max(test[maxx,:,:]) == 0):
    maxx-=1
while(tf.reduce_max(test[:,maxy,:]) == 0):
    maxy-=1
while(tf.reduce_max(test[:,:,maxz]) == 0):
    maxz-=1

maxx,maxy,maxz=np.add((maxx,maxy,maxz),1)
crop = test[minx:maxx,miny:maxy,minz:maxz]

print(minx,miny,minz,maxx,maxy,maxz)
print(rand.shape)
print(crop.shape)
这张照片是:

10 20 30 76 45 64
(66, 25, 34)
(66, 25, 34)
,这是正确的。然而,它花费的时间太长,可能是次优的。我正在寻找更好的方法来实现同样的目标

注意:

  • 子体积不一定是长方体,它可以是任何形状

  • 我想保持子体积内的间隙,只删除要裁剪的形状“外部”的部分


    • 当您等待合理的响应时(我猜这是某个图像处理库中的内置函数),这里有一种方法

      y, x = np.where(np.any(test, 0))
      z, _ = np.where(np.any(test, 1))
      test[min(z):max(z)+1, min(y):max(y)+1, min(x):max(x)+1]
      
      我认为把tf排除在外会提高你的表现


      说明(基于二维阵列)

      我们想把它种下来

      [[1, 2]
       [3, 0]]
      
    • np.any(…,0)
      这将在轴0上“迭代”,并返回
      True
      (如果切片中的任何元素是空的)。我在这里的评论中显示了这一结果:

      np.array([
          [0, 0, 0, 0, 0, ],  # False
          [0, 0, 1, 2, 0, ],  # True
          [0, 0, 3, 0, 0, ],  # True
          [0, 0, 0, 0, 0, ],  # False
          [0, 0, 0, 0, 0, ],  # False
      ])
      
      i、 它返回
      np.array([False,True,True,False,False])

    • np.任何(…,1)
      执行与步骤2相同的操作,但通过轴1而不是轴零,即

      np.array([
          [0,     0,     0,     0,     0,    ], 
          [0,     0,     1,     2,     0,    ],
          [0,     0,     3,     0,     0,    ],
          [0,     0,     0,     0,     0,    ],
          [0,     0,     0,     0,     0,    ],
      #    False  False  True   True   False
      ])
      
      请注意,对于三维阵列,这些步骤返回二维阵列

    • (x,)=np。其中(…)返回数组中真实值的索引值。所以
      np.where([False,True,True,False,False])
      返回
      (数组([1,2]),
      。请注意,这是一个元组,因此在2D情况下,我们需要调用
      (x,)=…
      因此
      x
      只是数组
      数组([1,2])
      。2D情况下的语法更好,因为我们可以使用元组解包,即
      x,y=…

    • 注意,在3D情况下,np.where可以一次为我们提供两个轴的值。我选择一次做x-y,然后做z-?第二步。这个要么是x,要么是y,我不想费心去计算,因为我们不需要它,我把它扔进一个名为
      \uu
      的变量中,按照惯例,这个变量是一个合理的地方,用来存储你实际上不想要的垃圾输出。注意,我需要执行
      z,=
      ,因为我希望元组解包,而不仅仅是
      z=
      ,否则
      z
      将成为具有两个数组的元组

    • 嗯,这一步和你在回答结束时做的差不多,所以我想你理解了。在每个维度中从第一个元素(该维度中有一个值)到最后一个元素进行简单切片。您需要
      +1
      ,因为python中的切片不包括
      后面的索引

    • 希望这是清楚的

      (编辑) 哎呀,我还没见过如何在元素之间保持所谓的“间隙”!这应该是最后一个

      def get_nonzero_sub(arr):
      arr\u slices=元组(对于arr\u arr.nonzero()中的curr\u arr.min():curr\u arr.max()+1)
      返回arr[arr_切片]
      
      在您的示例中,您有一个连续的“相关”数据区域-如果中间有间隙会怎样?您只是想裁剪一个numpy数组吗?为什么tensorflow会卷入其中?@Dan我实际上是在使用这个裁剪功能作为tensorflow网络的一部分。但你说得绝对正确,我可以不用。@fuppes先生,如果不清楚的话,很抱歉。我想保持差距。我只想移除“周围”的空白区域。谢谢。你的版本似乎是最快的。在1000x1000x1000卷上进行一次短测试,您可以得到2.5s,@Alexander为16s和9s,@Tensorflow为47s。“我有点不清楚你在做什么,你介意解释一下吗?”杰穆勒补充道。注意,我还从原始答案中取出了
      >0
      s,因为它们不需要。非常感谢,这很有效。然而,这比@Dan的建议慢了很多(10秒对2.8秒)。啊,这太不幸了!我目前正在研究一个更快的解决方案,我相信我会找到一些东西。
      np.array([
          [0,     0,     0,     0,     0,    ], 
          [0,     0,     1,     2,     0,    ],
          [0,     0,     3,     0,     0,    ],
          [0,     0,     0,     0,     0,    ],
          [0,     0,     0,     0,     0,    ],
      #    False  False  True   True   False
      ])