I am trying to draw these pretty boxes but instead of drawing them vertically, I want each box to overwrite the previous, so it looks like one box with changing colours every .5 seconds
I am using Jupyter notebooks and Python 3.6.
I have read about 50 similar questions and answers but can't get it to display as desired. Anyone who can help please?
from PIL import Image
import random
import time
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow, show, clf
sq_size = 20
num_squares = 5
im_size = sq_size * num_squares
im = Image.new('RGB', (im_size, im_size), color = 'white')
pix = im.load()
#Create new colourful boxes 4 times
for _ in range(4):
startx, starty = 0, 0
#move to the right place to plot each small square
for i in range(num_squares):
startx += sq_size
for j in range(num_squares):
starty += sq_size
rshade = np.random.randint(0, 256)
gshade = np.random.randint(0, 256)
bshade = np.random.randint(0, 256)
#plot each small square
for x in range(sq_size):
for y in range(sq_size):
value = (rshade, gshade, bshade)
pix[(startx + x) % im_size, (starty + y) % im_size] = value
plt.imshow(im)
plt.show()
time.sleep(.5)
Currently this plots as follows...
but I want each box to overwrite the previous, so it looks like one box with changing colours every .5 seconds
OK. I found a solution. it is based on https://matplotlib.org/examples/animation/dynamic_image2.html
from PIL import Image
import random
import time
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow, show
import matplotlib.animation as animation
%matplotlib notebook
def next_shape(im, num_squares, sq_size):
pix = im.load()
#initialise plot location
startx, starty = 0, 0
for i in range(num_squares):
startx += sq_size
for j in range(num_squares):
starty += sq_size
rshade = np.random.randint(0, 256)
gshade = np.random.randint(0, 256)
bshade = np.random.randint(0, 256)
for x in range(sq_size):
for y in range(sq_size):
value = (rshade, gshade, bshade)
pix[(startx + x) % im_size, (starty + y) % im_size] = value
#return list of pixel tuples
return list(im.getdata())
# First set up the figure, the axis, and the plot element we want to animate
sq_size = 20
num_squares = 5
#create a figure to animate
fig = plt.figure()
#create the image withi the figure to animate
im_size = sq_size * num_squares
im = Image.new('RGB', (im_size, im_size))
#create a list to store all the images in the format of a list of RGB pixels
im_list_pix = []
#generate a bunch of images in the form of a list of RGB pixels
for pic in range(10):
im_list_pix.append(next_shape(im, 5, 20))
#create a list to store images converted from RGB pixel tuples to image format
img_array = []
#convert list of pixel tuples back to image
for i, v in enumerate(im_list_pix):
im = Image.new('RGB', (100, 100))
#put the pixel data into the image container
im.putdata(im_list_pix[i])
im = plt.imshow(im)
img_array.append([im])
ani = animation.ArtistAnimation(fig, img_array, interval=500)
plt.show()
It took me a long time to work out the square brackets in ...
img_array.append([im])
... is crucial. It must be the way matplotlib.animate parses the list.
I hope this is useful for others wanting to pay with matplot.animate and have some fun creating art.
PS - thank you to the commenters who pointed me towards matplotlib.animate and thanks also to the author of this great blog post that gave me some clues and also shows how far you can push this stuff http://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.