Bonjour,

Je tente de faire un gif annimé d'un graph 3D (matplotlib). J'ai pas mal cherché et je suis suis tombé sur pas mal d'exemples qui soit ne fonctionnaient pas, soit n'étaient pas adpaté à mon besoin.

Je génère un certain nombre de fichier PNG qui sont des "vues" d'un graph. Je cherche ensuite à les assembler en un GIF annimé. Voici un bout de code qui génère un nuage de point (provenant du site de matplotlib):

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import matplotlib.pyplot as plt
 
# Create some random data
def randrange(n, vmin, vmax):
    return (vmax - vmin) * np.random.rand(n) + vmin
n = 100
xx = randrange(n, 23, 32)
yy = randrange(n, 0, 100)
zz = randrange(n, -50, -25)
 
# Create a figure and a 3D Axes
fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(xx,yy,zz, c='k')
Je génère l'ensemble de mes fichiers images comme ceci:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from PIL import Image
 
png_folder = r'c:\users\Bidon\temp\PNG_FILES'
if not os.path.exists(png_folder):
    os.makedirs(png_folder)
 
images = []
for i in xrange(0,360,10):
    ax.view_init(elev=10, azim=i)
    png_name = png_folder + '\\' + 'file' + str(i) + '.png'
    plt.savefig(png_name)
    im = Image.open(png_name)
    im.convert("P") 
    images.append(im)
J'ai trouvé un snippet provenant de la libraire Pillow pemettant de générer mes GIFs:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from PIL import Image, ImageChops
from PIL.GifImagePlugin import getheader, getdata
 
def gifmaker(fp, sequence):
    """Convert list of image frames to a GIF animation file"""
    frames = 0
    previous = None
    for im in sequence:
        #
        # FIXME: write graphics control block before each frame
        if not previous:
            # global header
            for s in getheader(im) + getdata(im):
                fp.write(s)
        else:
            # delta frame
            delta = ImageChops.subtract_modulo(im, previous)
            bbox = delta.getbbox()
            if bbox:
                # compress difference
                for s in getdata(im.crop(bbox), offset = bbox[:2]):
                    fp.write(s)
            else:
                # FIXME: what should we do in this case?
                pass
        previous = im.copy()
        frames += 1
    fp.write(";")
    return frames
Si je fais:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
# write GIF animation
with open('mongif.gif', 'wb') as fp:
    gifmaker(fp, images)
J'obtiens l'erreur suivante:

ImageFile._save(im, fp, [("gif", (0,0)+im.size, 0, RAWMODE[im.mode])])
KeyError: 'RGBA'
Les seules infos en lien avec ce problem indiquent de convertir les images au format 'P', ce que je fais avec :
J'avoue ne rien connaitre en traitement d'images. Si l'un de vous pouvais m'expliquer ce qui est incorrect, ce serait vraiment genial.

Ciao ciao