skip to Main Content

I have a 3D numpy array, where I threat it like a 2D array with multiple layers. In the example below, I have 2 layer 2d array, with width 4 and height 3.

import numpy
mapTiles=numpy.array(([[1,1,1,1],
                    [1,1,1,1],
                    [1,1,1,1]],
                   [[2,0,2,2],
                    [0,0,2,2],
                    [0,0,0,2]]))

I need to transform this numpy array in a similar way to Gimp/Photoshop/Aseprite canvas. So using height, width, and vertical and horizontal offset values.

  • If the resulting array is bigger, keep dimensions aligned top/left and fill with zeroes.

  • If the resulting array is smaller, just cut.

  • If the offset falls outside of width and height limit, just cut. Fill empty spaces with zeroes.

I could only conceive this with lots of if conditions, below is just one of the possible cases. Is there any already made specialized method for this? To create a new array and copy over, is there an alternative to just use for?

mapResize(mapTiles, width,height,offsetx=0,offsety=0):
    if(width-offsetx < len(mapTiles[0][0]) and height-offsety < len(mapTiles[0])):
        x=min(max(offsetx,0),len(mapTiles[0][0]))
        y=min(max(offsety,0),len(mapTiles[0]))
        return mapTiles[:,y:(y+height),x:(x+width)]

2

Answers


  1. I would create the new array then copy the data into it. This will require slices to be set up for both the source and the destination arrays.

    new_tiles = numpy.zeros((2, height, width), dtype=mapTiles.dtype)
    _, src_height, src_width = mapTiles.shape
    # Source x:
    start = max(0, -offsetx)
    stop = max(0, width - offsetx)  # Going too large here is harmless
    src_x_slice = slice(start, stop)
    
    # Source y:
    start = max(0, -offsety)
    stop = max(0, height - offsety)
    src_y_slice = slice(start, stop)
    
    # Dest x:
    start = max(0, offsetx)
    stop = max(0, offsetx + src_width)  # Going past the end is harmless
    dest_x_slice = slice(start, stop)
    
    # Dest y:
    start = max(0, offsety)
    stop = max(0, offsety + src_height)
    dest_y_slice = slice(start, stop)
    
    new_tiles[:, dest_y_slice, dest_x_slice] = mapTiles[:, src_y_slice, src_x_slice]
    
    Login or Signup to reply.
  2. I think this does it (next time try to show expected output):

    def mapResize(m, w, h, xo, yo):
        pads=((0,0),(abs(yo),abs(yo)+h),(abs(xo),abs(xo)+w))
        bigMap=np.lib.pad(m,pads,'constant',constant_values=0)
        return bigMap[:,yo+abs(yo):yo+abs(yo)+h,xo+abs(xo):xo+abs(xo)+w]
    
    mapResize(mapTiles,3,5,1,-2)
    array([[[0, 0, 0],
            [0, 0, 0],
            [1, 1, 1],
            [1, 1, 1],
            [1, 1, 1]],
    
           [[0, 0, 0],
            [0, 0, 0],
            [0, 2, 2],
            [0, 2, 2],
            [0, 0, 2]]])
    

    Basically, make a big padded array and slice it to size.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search