5

I want to do something like this inside a function:

if image.shape == 2 dimensions
    return image # this image is grayscale
else if image.shape = 3 dimensions
    return image # image is either RGB or YCbCr colorspace

Here, the image is a numpy array. I am not able to define that checking condition. I am really stuck at this point. Can anyone please help?

2
  • What if you use the title for google search?
    – Divakar
    Commented Sep 7, 2017 at 16:23
  • Did you even try to look at the documentation for numpy arrays?
    – crazyGamer
    Commented Sep 7, 2017 at 16:24

2 Answers 2

15

numpy.array.shape is a tuple of array dimensions. You can compute the length of a tuple and that will give the number of dimensions.

if len(image.shape) == 2:
    return image # this image is grayscale
elif len(image.shape) == 3:
    return image # image is either RGB or YCbCr colorspace

Numpy arrays also have a ndim attribute.

if image.ndim == 2:
    return image # this image is grayscale
elif image.ndim == 3:
    return image # image is either RGB or YCbCr colorspace
0
0

THERE IS ONE MORE "hidden-DIMENSION" OF THE PROBLEM :

Numpy has a few performance-motivated tricks, that may confuse you, if not taking due care of:

There are tricks that np.view() creates, as a view into a "foreign"-owned data, which actually means there has appeared a form of hidden sharing, which may pretty ugly surprise you if some operations on already "return()-ed" image store any modification into a just-.view()-created view. In such cases your code will silently damage the "foreign"-data, because you did not realise or notice that while the image reports correctly both the image.{shape|ndim}, yet it does not "have" its own data, but provides just a view through a "periscope-alike-window" into the original data, still "owned" somewhere else by someone else ( here, a write into image, like in an exemplary assignment of image[0,0] = -1 will actually "write-through" the -1 to get it stored into the "throat" of A-s A.data, being actually a <read-write buffer for 0x7efe9ff73800, size 7372800, offset 0 at 0x7efe9ff6cbf0> implementor-zone of the actual write-storage operation resulting in modification taking place in A's data )

This side-effect of .view()-s is both very powerful (if used knowingly, where intended, for performance or other reasons) yet also very awful to detect/debug (if not detected in the code design phase and just hunting the devils tail once the "source"-data get damaged without knowing who does turned the so far clear and sound design wreck havoc "foreign&safely-owned"-data from behind a curtain ... that may take and indeed takes pretty long to detect such hidden sharing write-throughs ... if they take place without your prior intent )

>>> A = np.arange( 3*640*480 ).reshape( 3, 640, 480 )
>>> A.shape
(3, 640, 480)
>>> A.ndim
3

>>> B = A.view()  # ENFORCE B BECOME A VIEW() ON AN ARRAY
>>> B.shape       #         B MIMICS AN ARRAY, WHILE IT IS NOT AN ARRAY
(3, 640, 480)
>>> B.ndim        #         B MIMICS AN ARRAY, WHILE IT IS NOT AN ARRAY
3
>>> B.flags       #         B MIMICS AN ARRAY, WHILE IT IS NOT AN ARRAY
  C_CONTIGUOUS    : True
  F_CONTIGUOUS    : False
  OWNDATA         : False <------------------- a view() on array, not the array itself
  WRITEABLE       : True
  ALIGNED         : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY    : False

>>> image = B[0,:,:] #   slice B into an IMAGE, which will still look as if it is an array
>>> image.flags
  C_CONTIGUOUS    : True
  F_CONTIGUOUS    : False
  OWNDATA         : False <----------------- a view() onto an array, not the array itself
  WRITEABLE       : True
  ALIGNED         : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY    : False
>>> image.ndim
2
>>> image.shape
(640, 480)

Hope you will enjoy the .view()-s, where used for performance or other reasons and hope you will never have to back-track the hidden-sharing side-effects in production.

Not the answer you're looking for? Browse other questions tagged or ask your own question.