Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add new dimensions to a Numpy array?

People also ask

How do you change the dimension of a NumPy array?

The shape of the array can also be changed using the resize() method. If the specified dimension is larger than the actual array, The extra spaces in the new array will be filled with repeated copies of the original array.

Can you add elements to a NumPy array?

Add array elementYou can add a NumPy array element by using the append() method of the NumPy module. The values will be appended at the end of the array and a new ndarray will be returned with new and old values as shown above.

Can you modify a NumPy array?

Modifying existing NumPy Arrays Unlike Python lists, NumPy doesn't have a append(...) function which effectively means that we can't append data or change the size of NumPy Arrays. For changing the size and / or dimension, we need to create new NumPy arrays by applying utility functions on the old array.

How do you add a dimension?

To create a new dimension. In Solution Explorer, right-click Dimensions, and then click New Dimension. On the Select Creation Method page of the Dimension Wizard, select Use an existing table, and then click Next. You might occasionally have to create a dimension without using an existing table.


You're asking how to add a dimension to a NumPy array, so that that dimension can then be grown to accommodate new data. A dimension can be added as follows:

image = image[..., np.newaxis]

Alternatively to

image = image[..., np.newaxis]

in @dbliss' answer, you can also use numpy.expand_dims like

image = np.expand_dims(image, <your desired dimension>)

For example (taken from the link above):

x = np.array([1, 2])

print(x.shape)  # prints (2,)

Then

y = np.expand_dims(x, axis=0)

yields

array([[1, 2]])

and

y.shape

gives

(1, 2)

You could just create an array of the correct size up-front and fill it:

frames = np.empty((480, 640, 3, 100))

for k in xrange(nframes):
    frames[:,:,:,k] = cv2.imread('frame_{}.jpg'.format(k))

if the frames were individual jpg file that were named in some particular way (in the example, frame_0.jpg, frame_1.jpg, etc).

Just a note, you might consider using a (nframes, 480,640,3) shaped array, instead.


Pythonic

X = X[:, :, None]

which is equivalent to

X = X[:, :, numpy.newaxis] and X = numpy.expand_dims(X, axis=-1)

But as you are explicitly asking about stacking images, I would recommend going for stacking the list of images np.stack([X1, X2, X3]) that you may have collected in a loop.

If you do not like the order of the dimensions you can rearrange with np.transpose()


You can use np.concatenate() specifying which axis to append, using np.newaxis:

import numpy as np
movie = np.concatenate((img1[:,np.newaxis], img2[:,np.newaxis]), axis=3)

If you are reading from many files:

import glob
movie = np.concatenate([cv2.imread(p)[:,np.newaxis] for p in glob.glob('*.jpg')], axis=3)

Consider Approach 1 with reshape method and Approach 2 with np.newaxis method that produce the same outcome:

#Lets suppose, we have:
x = [1,2,3,4,5,6,7,8,9]
print('I. x',x)

xNpArr = np.array(x)
print('II. xNpArr',xNpArr)
print('III. xNpArr', xNpArr.shape)

xNpArr_3x3 = xNpArr.reshape((3,3))
print('IV. xNpArr_3x3.shape', xNpArr_3x3.shape)
print('V. xNpArr_3x3', xNpArr_3x3)

#Approach 1 with reshape method
xNpArrRs_1x3x3x1 = xNpArr_3x3.reshape((1,3,3,1))
print('VI. xNpArrRs_1x3x3x1.shape', xNpArrRs_1x3x3x1.shape)
print('VII. xNpArrRs_1x3x3x1', xNpArrRs_1x3x3x1)

#Approach 2 with np.newaxis method
xNpArrNa_1x3x3x1 = xNpArr_3x3[np.newaxis, ..., np.newaxis]
print('VIII. xNpArrNa_1x3x3x1.shape', xNpArrNa_1x3x3x1.shape)
print('IX. xNpArrNa_1x3x3x1', xNpArrNa_1x3x3x1)

We have as outcome:

I. x [1, 2, 3, 4, 5, 6, 7, 8, 9]

II. xNpArr [1 2 3 4 5 6 7 8 9]

III. xNpArr (9,)

IV. xNpArr_3x3.shape (3, 3)

V. xNpArr_3x3 [[1 2 3]
 [4 5 6]
 [7 8 9]]

VI. xNpArrRs_1x3x3x1.shape (1, 3, 3, 1)

VII. xNpArrRs_1x3x3x1 [[[[1]
   [2]
   [3]]

  [[4]
   [5]
   [6]]

  [[7]
   [8]
   [9]]]]

VIII. xNpArrNa_1x3x3x1.shape (1, 3, 3, 1)

IX. xNpArrNa_1x3x3x1 [[[[1]
   [2]
   [3]]

  [[4]
   [5]
   [6]]

  [[7]
   [8]
   [9]]]]

There is no structure in numpy that allows you to append more data later.

Instead, numpy puts all of your data into a contiguous chunk of numbers (basically; a C array), and any resize requires allocating a new chunk of memory to hold it. Numpy's speed comes from being able to keep all the data in a numpy array in the same chunk of memory; e.g. mathematical operations can be parallelized for speed and you get less cache misses.

So you will have two kinds of solutions:

  1. Pre-allocate the memory for the numpy array and fill in the values, like in JoshAdel's answer, or
  2. Keep your data in a normal python list until it's actually needed to put them all together (see below)

images = []
for i in range(100):
    new_image = # pull image from somewhere
    images.append(new_image)
images = np.stack(images, axis=3)

Note that there is no need to expand the dimensions of the individual image arrays first, nor do you need to know how many images you expect ahead of time.