Pazu
Pazu

Reputation: 287

Visualize list of images with matplotlib

I have dataset which consists of 50 images of size 8 x 8 flattened into arrays of size 64. Using the function imshow of matplotlib.pyplot (plt) to visualize the first 16 images (in a 4x4 grid) of the dataset.

I tried the following code:

import matplotlib.pyplot as plt

import numpy as np
data = np.random.rand(50,64) #this will simulate my data

fig=plt.figure(figsize=(8, 8)) 
    
for i in range(16):
        
   img = np.reshape(data[i:(i+1)],(8,8))
   fig.add_subplot(4, 4, i)
   plt.imshow(img)
        
plt.show()

this is the traceback:

<ipython-input-207-7af8d2013358> in plot_first_digits()
     13 
     14         img = np.reshape(X[i:(i+1)],(8,8))
---> 15         fig.add_subplot(4, 4, i)
     16         plt.imshow(img)
     17 

~/anaconda3/lib/python3.8/site-packages/matplotlib/figure.py in add_subplot(self, *args, **kwargs)
   1417                     self._axstack.remove(ax)
   1418 
-> 1419             a = subplot_class_factory(projection_class)(self, *args, **kwargs)
   1420 
   1421         return self._add_axes_internal(key, a)

~/anaconda3/lib/python3.8/site-packages/matplotlib/axes/_subplots.py in __init__(self, fig, *args, **kwargs)
     63             else:
     64                 if num < 1 or num > rows*cols:
---> 65                     raise ValueError(
     66                         f"num must be 1 <= num <= {rows*cols}, not {num}")
     67                 self._subplotspec = GridSpec(

ValueError: num must be 1 <= num <= 16, not 0

<Figure size 576x576 with 0 Axes>

Upvotes: 0

Views: 1663

Answers (2)

L&#233;onard
L&#233;onard

Reputation: 2630

From your script, we can see that the error is due to the call to plt.add_subplot() with i = 0 at the first iteration (this function only accepts positive integer arguments).

Solution 1 with fig.add_subplots

import matplotlib.pyplot as plt
import numpy as np

# simulate data
data = np.random.rand(50, 64)

# create figure
fig = plt.figure(figsize=(8, 8))

# loop over images
for i in range(16):
    print(i)
    img = np.reshape(data[i : (i + 1)], (8, 8))
    fig.add_subplot(4, 4, i + 1)
    plt.imshow(img)

# save image
plt.savefig("subplot_image")

The output image looks like:

subplots show reshaped vectors into images

Solution 2 with plt.subplots (more pythonic)

The following solution produces the same image by directly iterating the subplots generated the plt.subplots(), and the elements of the data matrix.

# create figure
fig, axes = plt.subplots(4, 4, figsize=(8, 8))

# loop over images
for ax, img in zip(axes.ravel(), data):
    ax.imshow(img.reshape(8, 8))

# save image
plt.savefig("subplot_image")

Upvotes: 1

CodingAddict
CodingAddict

Reputation: 223

Try using Image Grid as follows:

from mpl_toolkits.axes_grid1 import ImageGrid

def show_images(images):
  fig = plt.figure(figsize=(12., 12.))
  grid = ImageGrid(fig, 111, nrows_ncols=(1, len(images)),axes_pad=0.1)

  for ax, im in zip(grid, images):
    ax.axis('off')
    ax.imshow(im, cmap="gray")

sample_negative = ~sample1
show_images([sample1, sample_negative])

Pay close attention to the constructor. You are passing your figure, number of rows and columns how you wish to align your images. In the example above, I've aligned all images in a single row. Here is how the output looks like:

enter image description here

Upvotes: 1

Related Questions