web-dev-qa-db-fra.com

Quel est le moyen le plus rapide pour dessiner une image à partir de valeurs de pixels discrets en Python?

Je souhaite dessiner une image basée sur des valeurs de pixels calculées, comme moyen de visualiser certaines données. Essentiellement, je souhaite prendre une matrice bidimensionnelle de triplets de couleurs et la rendre.

Notez que ce n'est pas du traitement d'image, car je ne transforme pas une image existante ni ne fais aucune sorte de transformations de l'image entière, et ce n'est pas non plus des graphiques vectoriels car il n'y a pas de structure prédéterminée à l'image que je rend- Je vais probablement produire des taches de couleur amorphes un pixel à la fois.

J'ai besoin de rendre des images d'environ 1kx1k pixels pour l'instant, mais quelque chose de modulable serait utile. Le format cible final est PNG ou tout autre format sans perte.

J'utilise PIL en ce moment via le point de dessin d'ImageDraw, et je me demandais, étant donné les fonctionnalités très spécifiques et relativement basiques dont j'ai besoin, existe-t-il une bibliothèque plus rapide disponible?

38
saffsd

Si vous avez numpy et scipy disponibles (et si vous manipulez de grands tableaux en Python, je les recommanderais), alors le scipy.misc.pilutil.toimage la fonction est très pratique. Un exemple simple:

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 bonne chose est que toimage gère très bien différents types de données, donc un tableau 2D de nombres à virgule flottante est sensiblement converti en niveaux de gris, etc.

Vous pouvez télécharger numpy et scipy depuis ici . Ou en utilisant pip:

pip install numpy scipy
35
BADC0DE
import Image
im= Image.new('RGB', (1024, 1024))
im.putdata([(255,0,0), (0,255,0), (0,0,255)])
im.save('test.png')

Place un pixel rouge, vert et bleu en haut à gauche de l'image.

im.fromstring() est encore plus rapide si vous préférez traiter les valeurs d'octets.

18
bobince

Exigences

Pour cet exemple, installez Numpy et Pillow .

Exemple

Le but est de représenter d'abord l'image que vous souhaitez créer sous la forme d'un tableau de tableaux d'ensembles de 3 nombres (RVB) - utilisez Numpy's array() , pour des performances et une simplicité:

import numpy

data = numpy.zeros((1024, 1024, 3), dtype=numpy.uint8)

Maintenant, définissez les valeurs RVB des 3 pixels du milieu sur rouge, vert et bleu:

data[512, 511] = [255, 0, 0]
data[512, 512] = [0, 255, 0]
data[512, 513] = [0, 0, 255]

Ensuite, utilisez Pillow's Image.fromarray() pour générer une image à partir du tableau:

from PIL import Image

image = Image.fromarray(data)

Maintenant, "montrez" l'image (sur OS X, cela l'ouvrira comme un fichier temporaire dans Aperçu):

image.show()

Remarque

Cette réponse a été inspirée par la réponse de BADCODE, qui était trop dépassée pour être utilisée et trop différente pour être simplement mise à jour sans réécriture complète.

6
orokusaki

Une approche différente consiste à utiliser Pyxel , une implémentation open source de l'API TIC-8 en Python3 (TIC-80 est l'open source PICO-8).

Voici une application complète qui ne dessine qu'un pixel jaune sur fond noir:

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)

Remarque : La bibliothèque ne permet que jusqu'à seize couleurs, mais vous pouvez changer les couleurs, et vous pourriez probablement la faire prendre en charge davantage sans trop de travail .

2
Carl Smith

Je pense que vous utilisez PIL pour générer un fichier image sur le disque et que vous le chargez plus tard avec un logiciel de lecture d'image.

Vous devriez obtenir une petite amélioration de la vitesse en rendant directement l'image en mémoire (vous économiserez le coût de l'écriture de l'image sur le disque, puis en la rechargeant). Jetez un oeil à ce fil https://stackoverflow.com/questions/326300/python-best-library-for-drawing pour savoir comment rendre cette image avec divers modules python .

J'essaierais personnellement wxpython et la fonction dc.DrawBitmap . Si vous utilisez un tel module plutôt qu'un lecteur d'image externe, vous aurez de nombreux avantages:

  • la vitesse
  • vous pourrez créer une interface utilisateur interactive avec des boutons pour les paramètres.
  • vous pourrez facilement programmer une fonction Zoom et Zoom arrière
  • vous pourrez tracer l'image pendant que vous la calculez, ce qui peut être très utile si le calcul prend beaucoup de temps
1
Mapad