How can I add new dimensions to a Numpy array?

249,334

Solution 1

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]

Solution 2

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)

Solution 3

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.

Solution 4

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()

Solution 5

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)
Share:
249,334
Chris
Author by

Chris

Updated on July 08, 2022

Comments

  • Chris
    Chris almost 2 years

    I'm starting off with a numpy array of an image.

    In[1]:img = cv2.imread('test.jpg')
    

    The shape is what you might expect for a 640x480 RGB image.

    In[2]:img.shape
    Out[2]: (480, 640, 3)
    

    However, this image that I have is a frame of a video, which is 100 frames long. Ideally, I would like to have a single array that contains all the data from this video such that img.shape returns (480, 640, 3, 100).

    What is the best way to add the next frame -- that is, the next set of image data, another 480 x 640 x 3 array -- to my initial array?

  • Magellan88
    Magellan88 about 10 years
    I think this is the way to go. if you use the concatenation you will need to move the array in memory every time you add to it. for 100 frames that should not matter at all, but if you want to go to larger videos. BTW, I would have used the number of frames as the first dimension so have a (100,480,640,3) array that way you can access individual frames (what is usually want you will want to look at, right?) easier (F[1] instead of F[:,:,:,1]). Of course performance wise it should not matter at all.
  • Ray
    Ray about 8 years
    Currently, numpy.newaxis is defined to be None (in file numeric.py), so equivalently you could use `image = image[..., None].
  • weima
    weima almost 7 years
    how to add values in the new dimention? if i do y[1,0] it gives index out of bounds error. y[0,1] is accessible
  • Cleb
    Cleb almost 7 years
    @weima: Not fully sure what you are after. What is your desired output?
  • Neil G
    Neil G about 6 years
    Don't use None. Use np.newaxis because explicit is better than implicit.
  • Pedro Rodrigues
    Pedro Rodrigues over 4 years
    How can that be? None does not imply anything. It is explicit. It is None. Stated clearly.None is a thing in python. There is no doubt. None is the last detail, you cannot go deeper. On the other hand, numpy.newaxis implies None. It is, essentially, None. It is None. But is None implicitly. It is None though not directly expressed as None. Explicit stated clearly and in detail, leaving no room for confusion or doubt. Implicit suggested though not directly expressed. I must add, that, from an API perspective, it is safer to use numpy.newaxis.
  • Gabrer
    Gabrer almost 4 years
    Guess here, being explicit refers to the "coder intent" rather than to the syntactical/semantical clarity.
  • Dan Boschen
    Dan Boschen over 3 years
    JoshAdel's answer should be selected as the right answer in this case and needs more votes. His point is significant in that the OP is looking to add to the higher dimensioned nparray as he goes. ndarray's cannot be increased in size once created, a copy must be made. This answer will only make the shape (480, 640, 3, 1) and every time you add a new frame you will be making another copy. Not good.
  • Dan Boschen
    Dan Boschen over 3 years
    I agree with JoshAdel and Magellan88, the other answers are very inefficient memory wise and processing time-- ndarrays cannot be increased in size once created, so a copy will always be made if you think you are appending to it.
  • chikitin
    chikitin about 3 years
    where is the reference to this, please?
  • Kaniee
    Kaniee about 3 years
    Since the title asks about adding (multiple) dimensions, I would like to add a way to add n dimensions: a[(..., *([np.newaxis] * n))]. The parentheses constructing a tuple are necessary to unpack the list of n times np.newaxis
  • KansaiRobot
    KansaiRobot over 2 years
    Where is the value of "your desired dimension" go? I can see only the value 1