首页 > 解决方案 > Crop empty arrays (padding) from a volume

问题描述

What I want to do is crop a volume to remove all irrelevant data. For example, say I have a 100x100x100 volume filled with zeros, except for a 50x50x50 volume within that is filled with ones. How do I obtain the cropped 50x50x50 volume from the original ?

Here's the naive method I came up with.

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)

This prints:

10 20 30 76 45 64
(66, 25, 34)
(66, 25, 34)

, which is correct. However, it takes too long and is probably suboptimal. I'm looking for better ways to achieve the same thing.

NB:

标签: pythonnumpy

解决方案


(Edit) Oops, I hadn't seen the comment about keeping the so-called "gaps" between elements! This should be the one, finally.

def get_nonzero_sub(arr):
    arr_slices = tuple(np.s_[curr_arr.min():curr_arr.max() + 1] for curr_arr in arr.nonzero())
    return arr[arr_slices]

推荐阅读