0

I am plotting images in a loop in the following way:

plt.figure(figsize=(20, 35))
for i in range(len(batchX)): # 32 images
   plt.subplot(8, 4, 1 + i)
   plt.title("IMG{} - Pred: {},  GT: {}".format(i+1, classes[int(pred[i][0])], classes[int(batchy[i])]))
   plt.imshow(batchX[i])
plt.tight_layout()
plt.show()

I'd like to change the background color of each plot depending on a certain condition (as you might have guessed, when the prediction equals the ground truth or not).

I tried adding this in the loop right before the imshow():

if classes[int(pred[i][0])] == classes[int(batchy[i])]:
   plt.gcf().set_facecolor("green")
else:
   plt.gcf().set_facecolor("red")

However, only the last plt.gcf() call will be taken into account since it's when plt.show() runs that it will look at the color setting, making all the backgrounds either green or red.

In what other way could I achieve this?

Nawra C
  • 156
  • 13

1 Answers1

0

You can use subplots() and iterate over the Axes, to finally show all the plots with their correct background colors.

fig, axs = plt.subplots(8,4, figsize=(20, 35))
# Flattens the Axes grid to more easily iterate
axs = axs.flatten()
# You must make sure that len(axes) >= len(batchX) (and batchy)
for i, X in enumerate(batchX):
    ax = axs[i]
    ax.set_title("IMG{} - Pred: {},  GT: {}".format(i+1, classes[int(pred[i][0])],\
        classes[int(batchy[i])]))
    if classes[int(pred[i][0])] == classes[int(batchy[i])]:
        ax.set_facecolor("green")
    else:
        ax.set_facecolor("red")
    ax.imshow(X)

plt.tight_layout()
plt.show()
Whole Brain
  • 2,097
  • 2
  • 8
  • 18
  • The background stays white. Neat trick to flatten the axes grid. – Nawra C Jun 18 '21 at 12:27
  • Before trying to change the background color, do you have any transparency in your images ? – Whole Brain Jun 18 '21 at 12:28
  • No transparency. I might not have been clear enough, I'm talking about the background of the plots, outside of the images, not the images' backgrounds. – Nawra C Jun 18 '21 at 12:30
  • In other words, the area changed when using `facecolor=(x, y, z)` in the creation of the subplots. But using this in `plt.subplots()` will change the whole plot's background color. I'm guessing the whole plot is considered to have a unique background, meaning that the subplots don't have a background region assigned, but only one large common background. – Nawra C Jun 18 '21 at 12:33
  • Does it mean you want to change the figure's facecolor ? That would mean you want as many figures as plots. – Whole Brain Jun 18 '21 at 12:35
  • Yes basically. I guess I shouldn't use subplots then. – Nawra C Jun 18 '21 at 12:37
  • 1
    Indeed, you can't change the figure's color and show it unless you do some kind of animation (or several displays). You could draw a plot A within a plot B, where A's ax has a facecolor, or you could add padding to you plots around the images. The figure will remain white (or uniform) but you would have colored borders. – Whole Brain Jun 18 '21 at 12:44
  • 1
    Thanks for the help. To pad the images I used `img_bordered = cv2.copyMakeBorder(X, border, border, border, border, cv2.BORDER_CONSTANT, value=[0, 255, 0])`. – Nawra C Jun 18 '21 at 12:56
  • Great idea. I hope the rendering satisfies your needs. – Whole Brain Jun 18 '21 at 13:01