Qual è il modo più veloce per disegnare un'immagine da valori di pixel discreti in Python?

StackOverflow https://stackoverflow.com/questions/434583

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?

È stato utile?

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

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top