4

I'm trying to scale a 3D array to size 64x64x64 (from a larger, non cube size), keeping aspect ratio.

I've done the same thing in a 2D array like this:

pad = Input.size[1]-Input.size[0]
padLeft = math.ceil(pad/2)
padRight = math.floor(pad/2)

if(pad > 0):
    paddedInput = np.pad(Input, ((0,0), (padLeft,padRight)), 'constant', constant_values=(0,0))
else:
    paddedInput = np.pad(Input, ((math.fabs(padLeft),math.fabs(padRight)), (0,0)), 'constant', constant_values=(0,0))

Output = misc.imresize(paddedInput,(InputHeight,InputHeight))

Is there a way to achieve the same thing in N (=3) dimensions?

Edit: My attempt at conversion to 3D:

pad = np.zeros((3,1))
pad[0,0] = max(Input.shape) - Input.shape[0]
pad[1,0] = max(Input.shape) - Input.shape[1]
pad[2,0] = max(Input.shape) - Input.shape[2]

paddedInput = np.zeros((max(Input.shape),max(Input.shape),max(Input.shape)))
print(paddedInput.shape)

for dimension in range(0,3):
    padLeft = math.ceil(pad[dimension,0]/2)
    padRight = math.floor(pad[dimension,0]/2)
    if((padLeft > 0) or (padRight > 0)):
        if dimension == 0:
            paddedInput = np.pad(Input, ((padLeft,padRight),(0,0),(0,0)), 'constant', constant_values=0)
        elif dimension == 1:
            paddedInput = np.pad(paddedInput, ((0,0), (padLeft,padRight),(0,0)), 'constant', constant_values=0)
        elif dimension == 2:
            paddedInput = np.pad(paddedInput, ((0,0),(0,0), (padLeft,padRight)), 'constant', constant_values=0)
print(paddedInput.shape)

This runs but the dimensions that get padded are padded with double the amount they need to be...

user2290362
  • 717
  • 2
  • 7
  • 21

2 Answers2

2

Take a look at zoom in scipy.ndimage. Here you provide zooming factors along each axis, rather than final cube size, but that is simple to figure out.

inarr = np.ones((32,32,32))
outarr = ndimage.zoom(inarr, 2)
outarr.shape
(64, 64, 64)
mdurant
  • 27,272
  • 5
  • 45
  • 74
  • Can you provide an example? My try with test = ndimage.interpolation.zoom(Input, float(Input.shape[0])/target.shape[0]) gives a result that's far too big, but flipping the fraction gives (0,0,0) size – user2290362 Mar 23 '15 at 20:13
  • Perhaps you are suffering from integer division? You didn't say what your input dimensions were. – mdurant Mar 23 '15 at 20:36
  • Around 190, 60, 170. Ideally I would like to keep the aspect ratio as well, I don't think that zoom allows that? That's why I had padded in my 2D example – user2290362 Mar 23 '15 at 21:16
  • Also, how do you intend to resize by different amounts on each dimension and also keep the aspect ratio? Perhaps you mean to resize such that the largest dimension length goes to 64? Then you can pad after that. – mdurant Mar 24 '15 at 13:18
2

The answer is to use pad and then numpy.ndarray.resize() :

pad = np.zeros((3,1))
pad[0,0] = max(Input.shape) - Input.shape[0]
pad[1,0] = max(Input.shape) - Input.shape[1]
pad[2,0] = max(Input.shape) - Input.shape[2]

paddedInput = np.zeros((max(Input.shape),max(Input.shape),max(Input.shape)))

paddedInput = np.pad(Input, ((int(math.ceil(pad[0,0]/2)),
    int(math.floor(pad[0,0]/2))),(int(math.ceil(pad[1,0]/2)),
    int(math.floor(pad[1,0]/2))),(int(math.ceil(pad[2,0]/2)),
    int(math.floor(pad[2,0]/2)))), 'constant', constant_values=0)

paddedInput.resize((64,64,64))

Doing the pad all on one line fixes any errors there were.

user2290362
  • 717
  • 2
  • 7
  • 21