lr100
lr100

Reputation: 600

Creating a New Numpy Array from Elements in a Numpy Array

Can't seem to figure this one out. Very new to numpy.

I have a numpy array of shape (200,1,1000,1000) which corresponds to (number of images, channel, x_of_image, y_of_image). So I have 200 images with 1 channel that are 1000x1000 pixels each.

I want to take each of the 200 images (1,1000,1000), do a operation on the image portion (1000,1000), and append/concatenate it to a brand new array.

new_array = np.array([])
for image in original_array:
    new_array = np.concatenate(new_array,original_array[0].operation())

New array would end up being the exact same shape as the original (200,1,1000,1000) just with different images because of the operation performed.

Bonus: How would I just do the operation on some percentage of the array, say 50%? This would output an array of (100,1,1000,1000)

Upvotes: 1

Views: 153

Answers (1)

MB-F
MB-F

Reputation: 23637

Avoid calling np.concatenatein a loop. It allocates a new array and copies everything. This is slow and you may run into memory problems if the discarded copies pile up without being garbage collected.

How this should be done depends mostly on the operations you perform on the images. Most numpy operations are designed to work very well with multi-dimensional arrays.

  1. Try to express the operation with numpy array functions. For example, normalizing the images to a range of 0..1 could be done like this:

    new_array = original_array - original_array.min(axis=(-1, -2), keepdims=True) 
    new_array /= new_array.max(axis=(-1, -2), keepdims=True)
    
  2. If the image operations are too complex to be broken down into numpy functions, allocate the new array first and modify it in place.

    new_array = np.empty_like(original_array)
    for i in range(new_array.shape[0]):
        new_array[i] = complicated_operation(original_array[i])
    

    Or copy the original array and work only on the copy:

    new_array = original_array.copy()
    for image in new_array:
        image[:] = complicated_operation(image)
    
  3. For some reason you do not want to pre-allocate, then store the images in a temporary list of arrays and concatenate them in the end:

    new_images = []
    for image in original_array:
        new_images.append(image.operation())
    new_array = np.stack(new_images)
    
  4. If you really want to successively concatenate arrays, note that the arrays-to-be-concatenated are passed to the function as one sequence, like this:

    new_array = np.array([])
    for image in original_array:
        new_array = np.concatenate([new_array, image.operation()])
    

Bonus: look up slicing. This is very basic numpy/Python and should definitely be in your toolbox.

  original_array[::2, :, :, :]  # take every second image

Upvotes: 3

Related Questions