32

The answers at Can I determine the number of channels in cv::Mat Opencv answer this question for OpenCV 1: you use the Mat.channels() method of the image.

But in cv2 (I'm using 2.4.6), the image data structure I have doesn't have a channels() method. I'm using Python 2.7.

Code snippet:

cam = cv2.VideoCapture(source)
ret, img = cam.read()
# Here's where I would like to find the number of channels in img.

Interactive attempt:

>>> img.channels()
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
AttributeError: 'numpy.ndarray' object has no attribute 'channels'
>>> type(img)
<type 'numpy.ndarray'>
>>> img.dtype
dtype('uint8')
>>> dir(img)
['T',
 '__abs__',
 '__add__',
...
 'transpose',
 'var',
 'view']
# Nothing obvious that would expose the number of channels.

Thanks for any help.

Community
  • 1
  • 1
LarsH
  • 27,481
  • 8
  • 94
  • 152

4 Answers4

53

Use img.shape

It provides you the shape of img in all directions. ie number of rows, number of columns for a 2D array (grayscale image). For 3D array, it gives you number of channels also.

So if len(img.shape) gives you two, it has a single channel.

If len(img.shape) gives you three, third element gives you number of channels.

For more details, visit here

Abid Rahman K
  • 51,886
  • 31
  • 146
  • 157
19

I'm kind of late but there is another simple way out there:

Use image.ndim Source, will give your right number of channels as below:


if image.ndim == 2:

    channels = 1 #single (grayscale)

if image.ndim == 3:

    channels = image.shape[-1]

Edit: In one-liners:

channels = image.shape[-1] if image.ndim == 3 else 1

Since a image is a nothing but a numpy array. Checkout OpenCV docs here: docs

abhiTronix
  • 1,248
  • 13
  • 17
  • Good technique, thank you. I implemented it as: `channels = 0 if img.ndim == 2 else img.shape[2]`. So if the image is grayscale then channels is 0, else channels is a number representing how many channels are in the 3rd array dimension (that's the correct place to read the data since dim 1 = height, dim 2 = width, dim 3 = color channels). – Mitch McMabers Sep 28 '19 at 01:53
  • Should be `channels = image.shape[-1] if image.ndim > 1 else 1`, for RGBA images and others – Ivan Aug 22 '23 at 12:52
1

As i know, u should use image.shape[2] to determine number of channels, not len(img.shape), the latter gives the dimensions of the array.

songofhawk
  • 91
  • 7
  • 3
    Please read Abid's answer more closely ... he agrees that image.shape[2] gives the number of channels *when image.shape[2] exists*, which is when len(image.shape) == 3. – LarsH Jun 28 '19 at 12:36
  • 1
    u r right, LarsH. sorry for Abid, he's answer is more general. – songofhawk Jul 03 '19 at 10:36
0

I would like to add here a self-contained script using the PIL library and another one using the cv2 library

CV2 Library script

import cv2
import numpy as np

img = cv2.imread("full_path_to_image")

img_np = np.asarray(img)

print("img_np.shape: ", img_np.shape)

The last column of the last print will show the number of channels, for example

img_np.shape: (1200, 1920, 4)

PIL Library script

from PIL import Image
import numpy as np

img = Image.imread("full_path_to_image")

img_np = np.asarray(img)

print("img_np.shape: ", img_np.shape)

The last column of the last print will show the number of channels, for example

img_np.shape: (1200, 1920, 4)

Note: from the scripts above you would be tempted (I was) to use img_np.shape[2] to retrieve the number of channels. However, if your image contains 1 channel (e.g., grayscale), that line would give you a problem (IndexError: tuple index out of range). Instead with just a simple print of shape (as I did in my script) you will get something like this

img_np.shape: (1200, 1920)

Dharman
  • 30,962
  • 25
  • 85
  • 135
desmond13
  • 2,913
  • 3
  • 29
  • 46