Reputation:
I am trying to understand how the value of the matrix fed to matplotlib's imshow()
function determines the intensity of the pixel in grey scale mode. Consider the example code:
import random
import matplotlib.pyplot as plt
import matplotlib.cm as cm
def pixels(n=3):
pixel_data = []
for _ in range(n):
row = []
for _ in range(n):
row.append(random.randint(1, 10))
pixel_data.append(row)
return pixel_data
if __name__ == '__main__':
pixel_data = pixels()
print(pixel_data)
plt.imshow(pixel_data, origin='lower', cmap=cm.Greys_r)
plt.show()
The pixel_data here is the 3*3 "matrix":
[[7, 4, 6], [7, 7, 6], [4, 7, 9]]
How does the values here determine what shade of grey I see in the image?
Upvotes: 6
Views: 32503
Reputation: 15889
Just a quick example:
import numpy as np
data = array([[7, 4, 6], [7, 7, 6], [4, 7, 9]])
imshow(data, 'gray', origin='lower')
Matplotlib's imshow
has 3 parameters that control the graycolor of each pixel:
vmin
: sets the minimum intensity value for the image (the black color in grayscale) and by default is set to the minimum value of your image array.vmax
: sets the maximum intensity value for the image (white color in grayscale) and is set by default to the maximum value of your array.If you want to see a true grayscale image, you need to manually set vmin=0
and vmax=255
(for 8 bit grayscale image). Or re-escale your array to [0, 255].
interpolation
: by default set to bilinear interpolation, this controls the value of the pixels interpolated if the image size is bigger or smaller than the size of your image matrix.This is a result of what would happen if you turn interpolation off:
imshow(data, 'gray', origin='lower', interpolation='none')
And this is an example of the function of vmin
and vmax
parameters:
imshow(data, 'gray', origin='lower', interpolation='none', vmin=0, vmax=20)
For more information about bilinear interpolation or interpolation methods refer to wikipedia or:
http://matplotlib.org/examples/images_contours_and_fields/interpolation_methods.html
where none = nearest
reflect the origina 4x4
array with no interpolation.
EDIT: Basically there are 2 key factors when you visualize an image:
If the above two sizes are the same, then the image is visualized in it's original size with no problem at all, however, this happens very rarely in real world. Imagine just a quick example where two people are looking to the same image in two monitors (suppose same model) with different resolutions: one with 1280x768 and the other with 800x600. The monitors actually have the same size, the image is the same one in both cases, but, the pixel density is not the same in two monitors (the first one has more pixels per inch than the second one), therefore, the guy with the 800x600 monitor will be looking to a bigger (worse quality) picture.
Is not the same case, but something similar happens with matplotlib. Matplotlib by default is not optimized to display images in their original size. Actually, if you display your 3x3
matrix, you wouldn't even be able to see it (too small) and yet, matplotlib by default shows you a (say 256x256) big smooth-like image (first image above).
What's happening behind all this? figure
's figsize
and dpi
parameters control the size and pixel density of the output image. If not manually given, matplotlib will try to estimate ones by default.
So, either by given manually or created by default, you end up with a 256x256 pixels for your 3x3
matrix. As stated above, vmin
and vmax
control the minimum and maximum values for colors (grayscale in this case, so vmin = black
and vmax = white
).
So, how to determine the value of each pixel? That depends in the interpolation method used. First, your matrix's (3x3
in this case) points are uniformly distributed along the image's size (256x256
for example). Then, the rest of the points of the new image (256x256
) are estimated using an interpolation method:
No interpolation: the pixels get the value of their closest element of the matrix
Bilinear interpolation: the pixels get a value averaged within their closest 4 neighbours of the matrix
And many more.. refer to interpolation methods above for more details.
As an example, look at the following image from wikipedia:
Imagine that the points with color are the data from your matrix, and the black dot represent one of the pixel that needs to be estimated when you make the image size bigger than your matrix size. In the particular case of the image the value of the black dot (for the new image) is estimated using bilinear interpolation. As you can see, the value of the pixel is set to a weighted average of the points in your matrix surrounding that pixel. If the interpolation method was set to 'none' or 'nearest' in matplotlib, the value for the black dot would have been given by the yellow pixel only (it's nearest one).
Look here for a bit more about interpolation: http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
Additionally, look here to realize how complicated actually is to visualize an image in its original pixel size with matplotlib.
Upvotes: 14
Reputation: 87386
The color mapping process (which applies to anything which subclasses from ColorMappable
, not just AxesImage
(which is what imshow
creates)) is a two step process.
Normalize
and it's subclasses instances) Colormap
instances).The available norm classes are:
Normalize
(linear)BoundaryNorm
('binned', discrete values out)LogNorm
(log)PowerNorm
(gamma correction)SymLogNorm
(log with linear near 0)All of the color map instances have a __call__
method which does the mapping from [0, 1] -> RGB.
imshow
exposes kwargs for vmin
, vmax
, norm
and cmap
. If not specified, a Normalize
(linear) instance is used. If you do not specify vmin
and vmax
(or set them toNone
) vmin
and vmax
are set to the min/max of the input data. If you do not specify cmap
it (sadly) defaults to 'jet'
.
Upvotes: 0