Reputation: 2210
When I try to load an image that has three channels with matplotlib it only has one channel when I issue the numpy shape
command. This shows the following image:
Here is the code I used:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
img = mpimg.imread('dolphin.png')
plt.imshow(img)
plt.show()
img.shape
(320, 500)
I also followed the matplotlib image tutorial which uses the same commands as above.
Loading the image with opencv the result is an image with three channels, as expected.
import cv2
imgcv = cv2.imread('dolphin.png')
plt.imshow(imgcv)
plt.show()
imgcv.shape
(320, 500, 3)
I am using Python 3.5.6 with anaconda.
Here is a short output of the conda list
command:
...
matplotlib 3.0.0
...
opencv3 3.1.0
...
pillow 5.2.0
...
The original image I used:
Am I missing a package or is there another command to load a *.png file? Everything seems to work with *.jpg images
Upvotes: 1
Views: 2089
Reputation: 339300
As I see it, matplotlib's imread
correctly reads in the image. If the image contains only a single channel, the resulting numpy array will be 2D. If the image contains 3 or 4 channels, the numpy array will be 3D.
Taking the dolphin image from the question you get
plt.imread("https://i.sstatic.net/cInHj.png").shape
> (320, 500)
Concerning the stinkbug image from the matplotlib documentation there is indeed a little problem. The image you see is a grey scale image as well,
plt.imread("https://matplotlib.org/_images/stinkbug.png").shape
> (375, 500)
However the tutorial claims it to be a 3 channel image. This is correct from the point of view of the tutorial, because it takes the image from the doc
on the github repository folder.
plt.imread("https://raw.githubusercontent.com/matplotlib/matplotlib/master/doc/_static/stinkbug.png").shape
> (375, 500, 3)
The problem is that the documentation is built through sphinx and sphinx-gallery and in addition may use some other libraries. In the course of this, the image is not copied in its raw format to the output folder. This problem has been reported already here, the reason is not yet fully tracked down.
In any case, the remaining open question is then, why does cv2.imread
give you a 3D array for a greyscale image?
From the OpenCV imread
documentation:
Second argument is a flag which specifies the way image should be read.
- cv2.IMREAD_COLOR : Loads a color image. Any transparency of image will be neglected. It is the default flag.
- cv2.IMREAD_GRAYSCALE : Loads image in grayscale mode
- cv2.IMREAD_UNCHANGED : Loads image as such including alpha channel
Note Instead of these three flags, you can simply pass integers 1, 0 or -1 respectively.
So here you need to specify yourself, which mode you want to use.
Let's verify:
import cv2
import urllib.request as req
dolphinurl ="https://i.sstatic.net/cInHj.png"
stinkbugweburl = "https://matplotlib.org/_images/stinkbug.png"
stinkbuggiturl = "https://raw.githubusercontent.com/matplotlib/matplotlib/master/doc/_static/stinkbug.png"
def printshape(url, **kw):
req.urlretrieve(url, "image_name.png")
im = cv2.imread("image_name.png", **kw)
print(im.shape)
printshape(dolphinurl)
printshape(stinkbugweburl)
printshape(stinkbugweburl)
This prints
(320, 500, 3)
(375, 500, 3)
(375, 500, 3)
while if you specify greyscale,
printshape(dolphinurl,0)
printshape(stinkbugweburl,0)
printshape(stinkbugweburl,0)
it'll print
(320, 500)
(375, 500)
(375, 500)
In that sense it's up to the user to decide how they want to read in the image.
Upvotes: 2