Display NumPy array as continuously updating image with Glumpy

后端 未结 2 1435
北恋
北恋 2021-02-08 23:31

I\'ve got a simulation model running in Python using NumPy and SciPy and it produces a 2D NumPy array as the output each iteration. I\'ve been displaying this output as an image

相关标签:
2条回答
  • 2021-02-09 00:06

    The Glumpy documentation is fairly nonexistent! Here's an example of a simple simulation, comparing array visualisation with glumpy against matplotlib:

    import numpy as np
    import glumpy
    from OpenGL import GLUT as glut
    from time import time
    from matplotlib.pyplot import subplots,close
    from matplotlib import cm
    
    def randomwalk(dims=(256,256),n=3,sigma=10,alpha=0.95,seed=1):
        """ A simple random walk with memory """
        M = np.zeros(dims,dtype=np.float32)
        r,c = dims
        gen = np.random.RandomState(seed)
        pos = gen.rand(2,n)*((r,),(c,))
        old_delta = gen.randn(2,n)*sigma
        while 1:
            delta = (1.-alpha)*gen.randn(2,n)*sigma + alpha*old_delta
            pos += delta
            for ri,ci in pos.T:
                if not (0. <= ri < r) : ri = abs(ri % r)
                if not (0. <= ci < c) : ci = abs(ci % c)
                M[ri,ci] += 1
            old_delta = delta
            yield M
    
    def mplrun(niter=1000):
        """ Visualise the simulation using matplotlib, using blit for 
        improved speed"""
        fig,ax = subplots(1,1)
        rw = randomwalk()
        im = ax.imshow(rw.next(),interpolation='nearest',cmap=cm.hot,animated=True)
        fig.canvas.draw()
        background = fig.canvas.copy_from_bbox(ax.bbox) # cache the background
    
        tic = time()
        for ii in xrange(niter):
            im.set_data(rw.next())          # update the image data
            fig.canvas.restore_region(background)   # restore background
            ax.draw_artist(im)          # redraw the image
            fig.canvas.blit(ax.bbox)        # redraw the axes rectangle
    
        close(fig)
        print "Matplotlib average FPS: %.2f" %(niter/(time()-tic))
    
    def gprun(niter=1000):
        """ Visualise the same simulation using Glumpy """
        rw = randomwalk()
        M = rw.next()
    
        # create a glumpy figure
        fig = glumpy.figure((512,512))
    
        # the Image.data attribute is a referenced copy of M - when M
        # changes, the image data also gets updated
        im = glumpy.image.Image(M,colormap=glumpy.colormap.Hot)
    
        @fig.event
        def on_draw():
            """ called in the simulation loop, and also when the
            figure is resized """
            fig.clear()
            im.update()
            im.draw( x=0, y=0, z=0, width=fig.width, height=fig.height )
    
        tic = time()
        for ii in xrange(niter):
            M = rw.next()           # update the array          
            glut.glutMainLoopEvent()    # dispatch queued window events
            on_draw()           # update the image in the back buffer
            glut.glutSwapBuffers()      # swap the buffers so image is displayed
    
        fig.window.hide()
        print "Glumpy average FPS: %.2f" %(niter/(time()-tic))
    
    if __name__ == "__main__":
        mplrun()
        gprun()
    

    Using matplotlib with GTKAgg as my backend and using blit to avoid drawing the background each time, I can hit about 95 FPS. With Glumpy I get about 250-300 FPS, even though I currently a fairly crappy graphics setup on my laptop. Having said that, Glumpy is a bit more fiddly to get working, and unless you are dealing with huge matrices, or you need a very high framerate for whatever reason, I would stick with using matplotlib with blit.

    0 讨论(0)
  • 2021-02-09 00:21

    Using pyformulas 0.2.8 you can use pf.screen to create a non-blocking screen:

    import pyformulas as pf
    import numpy as np
    
    canvas = np.floor(np.random.normal(scale=50, size=(480,640,3)) % 256).astype(np.uint8)
    screen = pf.screen(canvas)
    
    while screen.exists():
        canvas = np.floor(np.random.normal(scale=50, size=(480,640,3)) % 256).astype(np.uint8)
        screen.update(canvas)
    
    #screen.close()
    

    Disclaimer: I am the maintainer for pyformulas

    0 讨论(0)
提交回复
热议问题