Qual è il modo più veloce per disegnare un'immagine da valori di pixel discreti in Python?
-
10-07-2019 - |
Domanda
Desidero disegnare un'immagine basata su valori di pixel calcolati, come mezzo per visualizzare alcuni dati. In sostanza, desidero prendere una matrice bidimensionale di triplette di colore e renderla.
Nota che non si tratta di elaborazione di immagini, dal momento che non sto trasformando un'immagine esistente né sto facendo alcun tipo di trasformazione di immagine intera, e non è nemmeno grafica vettoriale in quanto non esiste una struttura predeterminata per l'immagine ' m rendering- probabilmente produrrò macchie di colore amorfe un pixel alla volta.
Per ora devo renderizzare le immagini di circa 1kx1k pixel, ma sarebbe utile qualcosa di scalabile. Il formato di destinazione finale è PNG o qualsiasi altro formato senza perdita di dati.
Al momento sto usando PIL tramite il draw.point di ImageDraw e mi chiedevo, date le caratteristiche molto specifiche e relativamente basilari di cui ho bisogno, c'è qualche libreria più veloce disponibile?
Soluzione
Se hai numpy
e scipy
disponibili (e se stai manipolando grandi array in Python, li consiglierei), quindi scipy.misc.pilutil.toimage
è molto utile.
Un semplice esempio:
import numpy as np
import scipy.misc as smp
# Create a 1024x1024x3 array of 8 bit unsigned integers
data = np.zeros( (1024,1024,3), dtype=np.uint8 )
data[512,512] = [254,0,0] # Makes the middle pixel red
data[512,513] = [0,0,255] # Makes the next pixel blue
img = smp.toimage( data ) # Create a PIL image
img.show() # View in default viewer
La cosa bella è che toimage
gestisce molto bene diversi tipi di dati, quindi un array 2D di numeri in virgola mobile viene sensibilmente convertito in scala di grigi ecc.
Puoi scaricare numpy
e scipy
da qui . O usando pip:
pip install numpy scipy
Altri suggerimenti
import Image
im= Image.new('RGB', (1024, 1024))
im.putdata([(255,0,0), (0,255,0), (0,0,255)])
im.save('test.png')
Mette un pixel rosso, verde e blu nella parte superiore sinistra dell'immagine.
im.fromstring ()
è ancora più veloce se preferisci gestire i valori dei byte.
Requisiti
Per questo esempio, installa Numpy e Cuscino .
Esempio
L'obiettivo è innanzitutto rappresentare l'immagine che si desidera creare come una matrice di array di set di 3 numeri (RGB): utilizzare Numpy array ()
, per prestazioni e semplicità:
import numpy
data = numpy.zeros((1024, 1024, 3), dtype=numpy.uint8)
Ora, imposta i valori RGB dei 3 pixel centrali su rosso, verde e blu:
data[512, 511] = [255, 0, 0]
data[512, 512] = [0, 255, 0]
data[512, 513] = [0, 0, 255]
Quindi, utilizza di Pillow Image.fromarray ()
per generare un'immagine dall'array:
from PIL import Image
image = Image.fromarray(data)
Ora, " mostra " l'immagine (su OS X, questo lo aprirà come file temporaneo in Anteprima):
image.show()
Nota ??h3>
Questa risposta è stata ispirata dalla risposta di BADCODE, che era troppo obsoleta da usare e troppo diversa per aggiornarsi semplicemente senza riscrivere completamente.
Un approccio diverso consiste nell'utilizzare Pyxel , un'implementazione open source di l'API TIC-80 in Python3 (TIC-80 è il PICO-8 open source).
Ecco un'app completa che disegna solo un pixel giallo su uno sfondo nero:
import pyxel
def update():
"""This function just maps the Q key to `pyxel.quit`,
which works just like `sys.exit`."""
if pyxel.btnp(pyxel.KEY_Q): pyxel.quit()
def draw():
"""This function clears the screen and draws a single
pixel, whenever the buffer needs updating. Note that
colors are specified as palette indexes (0-15)."""
pyxel.cls(0) # clear screen (color)
pyxel.pix(10, 10, 10) # blit a pixel (x, y, color)
pyxel.init(160, 120) # initilize gui (width, height)
pyxel.run(update, draw) # run the game (*callbacks)
Nota : la libreria consente solo fino a sedici colori, ma è possibile cambiare i colori e probabilmente è possibile ottenerne il supporto di più senza troppo lavoro.
Penso che usi PIL per generare un file di immagine sul disco e successivamente lo carichi con un software di lettura delle immagini.
Dovresti ottenere un piccolo miglioramento della velocità eseguendo il rendering diretto dell'immagine in memoria (risparmierai il costo di scrivere l'immagine sul disco e quindi ricaricarla). Dai un'occhiata a questa discussione https://stackoverflow.com/questions/326300/python-best- libreria-per-disegno per come rendere l'immagine con vari moduli Python.
Proverei personalmente wxpython e la funzione dc.DrawBitmap . Se usi un modulo del genere piuttosto che un lettore di immagini esterno avrai molti vantaggi:
- Velocità
- sarai in grado di creare un'interfaccia utente interattiva con pulsanti per i parametri.
- sarai in grado di programmare facilmente una funzione Zoomin e Zoomout
- sarai in grado di tracciare l'immagine mentre la calcoli, il che può essere molto utile se il calcolo richiede molto tempo