Sick Gaming
[Tut] Matplotlib Imshow — A Helpful Illustrated Guide - Printable Version

+- Sick Gaming (https://www.sickgaming.net)
+-- Forum: Programming (https://www.sickgaming.net/forum-76.html)
+--- Forum: Python (https://www.sickgaming.net/forum-83.html)
+--- Thread: [Tut] Matplotlib Imshow — A Helpful Illustrated Guide (/thread-93845.html)



[Tut] Matplotlib Imshow — A Helpful Illustrated Guide - xSicKxBot - 03-03-2020

Matplotlib Imshow — A Helpful Illustrated Guide

<div><p>I always struggled with the <code>plt.imshow()</code> method of Python’s <a rel="noreferrer noopener" aria-label=" (opens in a new tab)" href="https://matplotlib.org/" target="_blank">matplotlib </a>library. To help you and me master it, I committed to write the most in-depth resource about it on the web. </p>
<p>As you study the resource, you can play my explainer video that leads you through the code in this article:</p>
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio">
<div class="wp-block-embed__wrapper">
<div class="ast-oembed-container"><iframe title="Matplotlib Imshow -- A Helpful Illustrated Guide" width="1100" height="825" src="https://www.youtube.com/embed/4R7mA_AJxK8?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
</figure>
<p>To show an image in matplotlib, first read it in using <code>plt.imread()</code>, then display it with <code>plt.imshow()</code>. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import matplotlib.pyplot as plt cat_img = plt.imread('Figures/cat.jpeg')
plt.imshow(cat_img)</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img0.png" alt=""/></figure>
<p>To turn the (annoying) axis ticks off, call <code>plt.axis('off')</code>.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">cat_img = plt.imread('Figures/cat.jpeg')
plt.axis('off')
plt.imshow(cat_img)</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img1.png" alt=""/></figure>
<p>Much better! But there is a lot more you can do than just show images. Let’s look at how this works in more detail.</p>
<h2>Matplotlib Imshow Example</h2>
<p>When you display an in image in <a href="https://blog.finxter.com/matplotlib-scatter-plot/" target="_blank" rel="noreferrer noopener" aria-label="matplotlib (opens in a new tab)">matplotlib</a>, there are 2 steps you need to take: first you read the image and then you show it.</p>
<p>You read in the image using <code>plt.imread()</code> and pass it a string. I have the images stored in a directory called <em>Figures</em>, so I first write <code>Figures/</code> followed by the name of the image with its file extension – <code>cat.jpeg</code>. If your images are stored in your current working directory, you can omit <code>Figures/</code>.</p>
<p>I store the output of <code>plt.imread()</code> in a variable with a descriptive name because you need to pass this to <code>plt.imshow()</code>. So, the first line is <code>cat_img = plt.imread('Figures/cat.jpeg')</code>.</p>
<p>Images are made up of pixels and each pixel is a dot of color. The cat image is 1200×800 pixels. When an image is loaded into a computer, it is saved as an array of numbers. Each pixel in a color image is made up of a Red, Green and Blue (RGB) part. It can take any value between 0 and 255 with 0 being the darkest and 255 being the brightest. In a grayscale image, each pixel is represented by just a single number between 0 and 1. If a pixel is 0, it is completely black, if it is 1 it is completely white. Everything in between is a shade of gray.</p>
<p>So, if the cat image was black and white, it would be a 2D <a href="https://blog.finxter.com/numpy-tutorial/" target="_blank" rel="noreferrer noopener" aria-label="numpy array (opens in a new tab)">numpy array</a> with shape <code>(800, 1200)</code>. As it is a color image, it is in fact a 3D numpy array (to represent the three different color channels) with shape <code>(800, 1200, 3)</code>.</p>
<p>Note that Numpy writes image sizes is the opposite way to matplotlib and the ‘real world’. Numpy is from the world of mathematics and matrices where you always write the number of rows (height) first followed by the columns (width). If you need a quick NumPy refresher, check out my <a rel="noreferrer noopener" aria-label="in-depth NumPy tutorial (opens in a new tab)" href="https://blog.finxter.com/numpy-tutorial/" target="_blank">in-depth NumPy tutorial</a> on this blog. </p>
<p>Matplotlib bases its image functions on the ‘real world’ and so displays the width first followed by the height.</p>
<p>Let’s look at the type and size of <code>cat_img</code>. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">cat_img = plt.imread('Figures/cat.jpeg') print(type(cat_img))
# &lt;class 'numpy.ndarray'> print(cat_img.shape)
# (800, 1200, 3) &lt;class 'numpy.ndarray'>
(800, 1200, 3)
</pre>
<p>Once you’ve read your image into a numpy array, it’s time to display it using <code>plt.imshow()</code>. This is similar to <code>plt.show()</code> which you call at the end of any matplotlib plot. However, unlike <code>plt.show()</code>, you must pass the image you want to display as an argument. This is helpful if you have read in multiple images but only want to display a certain number of them.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">plt.imshow(cat_img)</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img2.png" alt=""/></figure>
<p>I’m not sure why but, by default, all images are shown with axis ticks and labels. This can be quite annoying, so call <code>plt.axis('off')</code> to remove them.</p>
<p>However, ticks and labels can be helpful if you only want to select part of the image. By using them as guides, I’ll slice <code>cat_img</code> to just get the head of our cute kitten. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># Slicing found by using axis ticks and lables on image above
cat_head = cat_img[150:450, 275:675, :]
plt.imshow(cat_head)</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img3.png" alt=""/></figure>
<p>The above image is a jpeg but you can also display other types of image files such as pngs. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># A png image
snow_img = plt.imread('Figures/snowboarder.png')
plt.axis('off')
plt.imshow(snow_img)</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img4.png" alt=""/></figure>
<p>You can display gifs but it is slightly more complicated to do so and so is outside the scope of this article. If you read in and show a gif using the above steps, matplotlib will just show one of its frames. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">janice = plt.imread('Figures/janice.gif')
plt.axis('off')
plt.imshow(janice)</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img5.png" alt=""/></figure>
<h2>Matplotlib Imshow Grayscale</h2>
<p>You can turn any color image into a grayscale image in matplotlib. Since grayscale images are 2D numpy arrays, use slicing to turn your 3D array into a 2D one. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">cat_img = plt.imread('Figures/cat.jpeg') # Turn 3D array into 2D by selecting just one of the three dimensions
grayscale_cat = cat_img[:, :, 0]
</pre>
<p>If you write <code>cat_img[:, :, 1]</code> or <code>cat_img[:, :, 2]</code> you will get different arrays but the final image will still look the same. This is because grayscale images just care about the relative difference of intensity between each pixel and this is the same over each RGB channel.</p>
<p>Let’s plot it and see what happens. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">plt.axis('off')
plt.imshow(grayscale_cat)</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img6.png" alt=""/></figure>
<p>Wait, what?</p>
<p>Don’t worry, you haven’t done anything wrong! You created a grayscale image but matplotlib applied a colormap to it automatically. This happens even if you pick the second or third dimension in your <code>grayscale_cat</code> definition.</p>
<p>To make it grayscale, set the <code>cmap</code> keyword argument to <code>'gray'</code> in <code>plt.imshow()</code>.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">plt.axis('off')
plt.imshow(grayscale_cat, cmap='gray')</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img7.png" alt=""/></figure>
<p>Perfect! Now you can easily turn any color image into a grayscale one in matplotlib. But there are many more colors you can choose from. Let’s look at all the colormaps in detail.</p>
<h2>Matplotlib Imshow Colormap</h2>
<p>There are <a href="https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">many different colormaps</a> you can apply to your images. Simply pass the name to the <code>cmap</code> keyword argument in <code>plt.imshow()</code> and you’re good to go. I recommend you play around with them since most of the names won’t mean anything to you on first reading.</p>
<p>The default colormap is <em>viridis</em>. Let’s explicitly apply it to our cat image. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># Turn cat_img into a 2D numpy array colored_cat = cat_img[:, :, 0]
plt.axis('off')
plt.imshow(colored_cat, cmap='viridis')</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img8.png" alt=""/></figure>
<p>I could write a whole article on colormaps – in fact, the creator of Seaborn <a href="https://seaborn.pydata.org/tutorial/color_palettes.html">did</a>. It’s a fascinating topic. Choosing the right one can make your plot incredible and choosing a bad one can ruin it.</p>
<p>For beginners, matplotlib recommends the <code>Perceptually Uniform Sequential</code> colormaps as they work well and are easy on the eyes. Here’s a list of them all.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">percp_uniform_seq_cmaps = ['viridis', 'plasma', 'inferno', 'magma', 'cividis']</pre>
<p>You’ve already seen <code>viridis</code>, so let’s display the others on a 2×2 grid (if you don’t know <a href="http://blog.finxter.com/matplotlib-subplots">how to make subplots in matplotlib</a> check out my article). </p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fig, axes = plt.subplots(nrows=2, ncols=2)
cmaps = ['plasma', 'inferno', 'magma', 'cividis'] for ax, cmap in zip(axes.flat, cmaps): ax.imshow(colored_cat, cmap=cmap) ax.set(title=cmap) ax.axis('off')
plt.show()</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img9.png" alt=""/></figure>
<p>The colormaps are quite similar and easy to look at. They don’t distort the image and the highs and lows can still be seen.</p>
<p>Here are some other colormaps I’ve randomly chosen. Note how odd some of them are, especially <code>flag</code>! </p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fig, axes = plt.subplots(nrows=2, ncols=3, figsize=plt.figaspect(1/2))
cmaps = ['jet', 'binary', 'RdYlGn', 'twilight', 'Pastel1', 'flag'] for ax, cmap in zip(axes.flat, cmaps): ax.imshow(colored_cat, cmap=cmap, label=cmap) ax.set(title=cmap) ax.axis('off')
plt.show()</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img10.png" alt=""/></figure>
<h2>Matplotlib Imshow Colorbar</h2>
<p>If your image has a colormap applied to it, you may want to tell the reader what each color means by providing a colorbar. Use <code>plt.colorbar()</code> to add one.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">plt.imshow(colored_cat, cmap='hot')
plt.axis('off')
plt.colorbar()</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img11.png" alt=""/></figure>
<p>Remember that every value in an array representing a colored image is a number between 0 and 255 and so the colorbar reflects this.</p>
<p>Note that I called <code>plt.imshow()</code> on the first line. Unlike <code>plt.show()</code>, you can modify images after calling <code>plt.imshow()</code> and the changes will be applied to the output.</p>
<h2>Matplotlib Imshow Size</h2>
<p>As with every <a href="https://blog.finxter.com/matplotlib-subplots/#Matplotlib_Figures_and_Axes"><code>Figure</code> in matplotlib</a>, you can manually set the <code>Figure</code>‘s size. Simply call <code>plt.figure()</code> at the top and set the <code>figsize</code> argument. You can either set it to a specific size in inches or set the aspect ratio:</p>
<ol>
<li><code>plt.figure(figsize=(8, 6))</code> – 8 inches wide, 6 inches tall</li>
<li><code>plt.figure(figsize=plt.figaspect(2))</code> – aspect ratio of 2, i.e. twice as tall as it is wide.</li>
</ol>
<p>Note: the default figsize can be found by calling <code>plt.rcParams['figure.figsize']</code> and is <code>(6.4, 4.8)</code> inches.</p>
<p>Let’s see what happens when we modify the <code>Figure</code> size of our cat image.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># 1 inch wide x 1 inch tall...?
plt.figure(figsize=(1, 1)) cat_img = plt.imread('Figures/cat.jpeg')
plt.axis('off')
plt.imshow(cat_img)</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img12.png" alt=""/></figure>
<p>This is certainly smaller than the original. But it doesn’t look like it is 1×1 inches – it’s clearly wider that it is tall. But it looks like one of the sides is correct which is better than nothing.</p>
<p>Let’s try to make it 1 inch wide and 3 inches tall. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># 1 inch wide x 3 inches tall...?
plt.figure(figsize=(1, 3)) cat_img = plt.imread('Figures/cat.jpeg')
plt.axis('off')
plt.imshow(cat_img)</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img13.png" alt=""/></figure>
<p>Now the image hasn’t changed at all. What’s going on?</p>
<p>When you resize images in most programs like Microsoft Word or Google Sheets, they maintain their original height/width ratios. This is called preserving the aspect ratio of the image and is usually a very good thing. It ensures that pixels in the image are not distorted when you resize them. This is also the default behavior in matplotlib.</p>
<p>If you actually want to distort the image and to fill up the entire space available in the <code>Figure</code>, change the <code>aspect</code> keyword argument in <code>plt.imshow()</code>.</p>
<p>There are only two possible values for <code>aspect</code>:</p>
<ol>
<li>‘equal’ – (default) preserves the aspect ratio, i.e. the side lengths of the pixels are equal (square)</li>
<li>‘auto’ – does not preserve the aspect ratio</li>
</ol>
<p>Let’s look at the same examples as above but set <code>aspect='auto'</code>. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># 1 inch wide x 1 inch tall (definitely)
plt.figure(figsize=(1, 1)) cat_img = plt.imread('Figures/cat.jpeg')
plt.axis('off')
plt.imshow(cat_img, aspect='auto')
</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img14.png" alt=""/></figure>
<p>Great! Now, the image is clearly 1×1 inches but it has come at the expense of slight image distortion.</p>
<p>Let’s distort it even further. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># 1 inch wide x 3 inches tall (definitely)
plt.figure(figsize=(1, 3)) cat_img = plt.imread('Figures/cat.jpeg')
plt.axis('off')
plt.imshow(cat_img, aspect='auto')
</pre>
<figure class="wp-block-image"><img src="https://raw.githubusercontent.com/theadammurphy/matplotlib_articles/master/imshow/final_html/img/img15.png" alt=""/></figure>
<p>Perfect! Clearly the image is distorted but now you know how to do it.</p>
<p>Note the default aspect value can be changed for all images by setting <code>plt.rcParams['image.aspect'] = 'auto'</code>.</p>
<h2>Summary</h2>
<p>Now you know the basics of displaying images with matplotlib.</p>
<p>You understand why you need to first read images in from a file and store them as a numpy array (<a href="https://blog.finxter.com/numpy-tutorial/" target="_blank" rel="noreferrer noopener" aria-label="NumPy tutorial here (opens in a new tab)">NumPy tutorial here</a>) before displaying them with <code>plt.imshow()</code>. You know how to read in different types of image files (hint – if it’s a still image, it’s the same process regardless of the file type!).</p>
<p>If you want to set a specific colormap, you use the <code>cmap</code> keyword argument and you can also turn your color image to a grayscale one. Finally, you can add a colorbar and change the size of your image to be anything you want.</p>
<p>There are some more advanced topics to learn about such as interpolation, adding legends and using log scales for your axes but I’ll leave them for another article.</p>
<h2>Where To Go From Here?</h2>
<p>Do you wish you could be a programmer full-time but don’t know how to start?</p>
<p>Check out the pure value-packed webinar where Chris – creator of Finxter.com – teaches you to become a Python freelancer in 60 days or your money back!</p>
<p><a href="https://tinyurl.com/become-a-python-freelancer">https://tinyurl.com/become-a-python-freelancer</a></p>
<p>It doesn’t matter if you’re a Python novice or Python pro. If you are not making six figures/year with Python right now, you will learn something from this webinar.</p>
<p>These are proven, no-BS methods that get you results fast.</p>
<p>This webinar won’t be online forever. Click the link below before the seats fill up and learn how to become a Python freelancer, guaranteed.</p>
<p><a href="https://tinyurl.com/become-a-python-freelancer">https://tinyurl.com/become-a-python-freelancer</a></p>
<p>WordPress conversion from imshow.ipynb by <a href="https://github.com/bennylp/nb2wp">nb2wp</a> v0.3.1</p>
</div>


https://www.sickgaming.net/blog/2020/03/02/matplotlib-imshow-a-helpful-illustrated-guide/