Search code examples
pythonmatplotlibmatplotlib-animation

How to update a shape


I have a rectangular shape which is drawn on an image. I would like to move that shape around, ie change its coordinates, plot the new shape and remove the old one (the background image stays the same)

Something similar to this code. It shows a rectangle three times but I want when the green shape is drawn, the red one to be deleted and similarly for the blue. When the blue appears to remove the green.

import matplotlib.pyplot as plt
import numpy as np

# Get an example image
image_file = r"image_splash.jpg"
img = plt.imread(image_file)

# Make some example data
x = np.array([475, 475, 675, 675, 475])
y = np.array([100, 200, 200, 100, 100])

# Create a figure
_dpi = 72
fig = plt.figure(1, figsize=(1000/_dpi, 1000/_dpi), dpi=_dpi)
ax = fig.add_subplot(1, 1, 1)
ax.set_aspect('equal')

# Show the image
ax.imshow(img)

# Now, loop through the offset array and update the shape 
# (This obviously doesnt work, it plots all three shapes)
rgb = ['r', 'g', 'b']
offset = [0, 150, 300]
plt.plot(x, y + offset[0], c=rgb[0]) # draw the red rect
plt.plot(x, y + offset[1], c=rgb[1]) # should remove the red and draw the green
plt.plot(x, y + offset[2], c=rgb[2]) # should remove the green and draw the blue

enter image description here


Solution

  • You can try the animation api of matplotlib like shown below

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.animation import FuncAnimation
    
    fig, ax = plt.subplots()
    xdata, ydata = [], []
    (ln,) = plt.plot([], [], "r")
    
    x = np.array([475, 475, 675, 675, 475])
    y = np.array([100, 200, 200, 100, 100])
    offset = [0, 150, 300]
    colors = {
        0: "red",
        150: "green",
        300: "blue",
    }
    
    
    def init():
        ax.set_xlim(0, 1000)
        ax.set_ylim(0, 1000)
        return (ln,)
    
    
    def update(_offset):
        ln.set_data(x, y + _offset)
        ln.set_color(colors[_offset])
        return (ln,)
    
    
    def gety():
        for i in range(1000):
            yield offset[i % 3]
    
    
    ani = FuncAnimation(fig, update, frames=gety(), init_func=init, blit=True)
    plt.show()