How to plot a contour of an image in python if I have an image?

Viewed 66

I have an image of an chicken for which I have to plot the contour. I'm getting an error (attached below). What does the error mean and how to rectify it?

This is the error I'm getting for this code:

Code:

img = color.rgb2gray(io.imread('chic1.png'))

img = np.flip(img, axis=0) 

Error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_1956/2147137072.py in <module>
----> 1 img = color.rgb2gray(io.imread('chic1.png'))
      2 img = np.flip(img, axis=0)

~\miniconda3\lib\site-packages\skimage\_shared\utils.py in fixed_func(*args, **kwargs)
    392 
    393             if channel_axis is None:
--> 394                 return func(*args, **kwargs)
    395 
    396             # TODO: convert scalars to a tuple in anticipation of eventually

~\miniconda3\lib\site-packages\skimage\color\colorconv.py in rgb2gray(rgb, channel_axis)
    873     >>> img_gray = rgb2gray(img)
    874     """
--> 875     rgb = _prepare_colorarray(rgb)
    876     coeffs = np.array([0.2125, 0.7154, 0.0721], dtype=rgb.dtype)
    877     return rgb @ coeffs

~\miniconda3\lib\site-packages\skimage\color\colorconv.py in _prepare_colorarray(arr, force_copy, channel_axis)
    138         msg = (f'the input array must have size 3 along `channel_axis`, '
    139                f'got {arr.shape}')
--> 140         raise ValueError(msg)
    141 
    142     float_dtype = _supported_float_type(arr.dtype)

ValueError: the input array must have size 3 along `channel_axis`, got (251, 402, 4)

Error

The image I'm using

2 Answers

Your image includes an alpha channel. Thus, the shape of your input image is (251, 402, 4). But rgb2gray() expects an image with 3 channels only.

You could simply strip the alpha channel (as suggested by @Imielke) or use rgba2rgb() first. The later supports alpha-bleeding (if needed).

from skimage import color, io

img_4d = io.imread('chic1.png')

#alternative 1
img = color.rgba2rgb(img_4d)
img_gray = color.rgb2gray(img)

#alternative 2
img_gray = color.rgb2gray(img_4d[:, :, :3])

...

io.imread says the following in the docstring:

Returns
    -------
    img_array : ndarray
        The different color bands/channels are stored in the
        third dimension, such that a gray-image is MxN, an
        RGB-image MxNx3 and an RGBA-image MxNx4.

You should only provide the colors and not the alpha which io.imread() supplies:

img = color.rgb2gray(io.imread('chic1.png')[:,:,:3])

However you could also just use skimage imread to change it to grayscale in one go:

img = io.imread('chic1.png', as_gray=True)
img = np.flip(img, axis=0) 
Related