speed up plotting images in matplotlib

10,145

Solution 1

This version of the code ultimately solved my problem:

import matplotlib.pyplot as plt
import os

def VI_segmentation():
    plt.ion()
    root = os.getcwd()
    NR_dir = root + '\\Neurite_Results\\'
    SO_dir = root + '\\Segmentation_Overlays\\'
    jpgs = os.listdir(NR_dir)
    f = plt.figure(figsize=(22,12))
    ax1 = f.add_subplot(121)
    ax2 = f.add_subplot(122)
    image_NR = plt.imread(NR_dir + jpgs[0])
    image_SO = plt.imread(SO_dir + jpgs[0])
    im1 = ax1.imshow(image_NR)
    im2 = ax2.imshow(image_SO) 
    f.suptitle(jpgs[0] , fontsize=14, fontweight='bold')
    f.show()
    plt.pause(0.01)
    input('Press Enter to continue')

    for jpg in jpgs[1:]:
        f.suptitle(jpg , fontsize=14, fontweight='bold')
        image_NR = plt.imread(NR_dir + jpg)
        image_SO = plt.imread(SO_dir + jpg)
        im1.set_data(image_NR)
        im2.set_data(image_SO)
        f.canvas.draw()
        plt.pause(0.01)
        input('Press Enter to continue')

VI_segmentation()

The key was to change the data in the plot, rather than adding a new plot. This answer was helpful to me.

Why does my pylab animation slow down with each update?

Oddly, when I started changing the plot data instead of replotting, I started getting weird behavior where the figure would enlarge but the surrounding window would not. Somehow, this fig.set_size_inches got broken so I moved around figure creation and axis creation so I could set the figure size when the figure was made.

Solution 2

You can change matplotlib backend and check which is better for your plot.

you can try GTKAgg backend as explained in answer: https://stackoverflow.com/a/30655528/2632856

try adding the second line of code after your matplotlib import statement.

import matplotlib
matplotlib.use('GTKAgg')

There are other backends which you can experiment with. See this link for the available backends, http://matplotlib.org/faq/usage_faq.html#what-is-a-backend

Share:
10,145
Dessie
Author by

Dessie

Updated on July 09, 2022

Comments

  • Dessie
    Dessie almost 2 years

    I wrote some Python in the Spyder IDE to plot a pair of images side by side so I can visually inspect them. I only need 3 seconds to look at them most of the time but every once in a while I need longer to take a closer look. Therefore, I didn't use time.sleep, instead I coded it to wait for me to hit the Enter key as below:

    import matplotlib.pyplot as plt
    import os
    
    def VI_segmentation():
        root = os.getcwd()
        NR_dir = root + '\\Neurite_Results\\'
        SO_dir = root + '\\Segmentation_Overlays\\'
        jpgs = os.listdir(NR_dir)
        fig = plt.figure(figsize=(20,12))
        for jpg in jpgs:
            fig.suptitle(jpg , fontsize=14, fontweight='bold')
            image_NR = plt.imread(NR_dir + jpg)
            image_SO = plt.imread(SO_dir + jpg)
            plt.subplot(121)
            plt.imshow(image_NR)
            plt.subplot(122)
            plt.imshow(image_SO)
            plt.draw()
            plt.pause(0.01)
    
            input('Press Enter to continue')
    
    VI_segmentation()
    

    The problem is that I'm thinking faster than my computer :). It takes the 5 or 6 seconds for the computer to become responsive to the Enter key and another few seconds to update after it responds. Makes for lousy ergonomics when cranking through hundreds of images that are mostly fine. Any ideas to streamline this code would be much appreciated.