Come leggere il valore RGB di un dato pixel in Python?


140

Se apro un'immagine con open("image.jpg"), come posso ottenere i valori RGB di un pixel supponendo che io abbia le coordinate del pixel?

Quindi, come posso fare il contrario? Partendo da un grafico vuoto, "scrivi" un pixel con un determinato valore RGB?

Preferirei se non dovessi scaricare alcuna libreria aggiuntiva.

Risposte:


213

Probabilmente è meglio usare la libreria di immagini Python per fare ciò, temo sia un download separato.

Il modo più semplice per fare ciò che vuoi è tramite il metodo load () sull'oggetto Image che restituisce un oggetto di accesso ai pixel che puoi manipolare come un array:

from PIL import Image

im = Image.open('dead_parrot.jpg') # Can be many different formats.
pix = im.load()
print im.size  # Get the width and hight of the image for iterating over
print pix[x,y]  # Get the RGBA Value of the a pixel of an image
pix[x,y] = value  # Set the RGBA Value of the image (tuple)
im.save('alive_parrot.png')  # Save the modified pixels as .png

In alternativa, guarda ImageDraw che fornisce un'API molto più ricca per la creazione di immagini.


1
Fortunatamente l'installazione di PIL è molto semplice in Linux e Windows (non so di Mac)
heltonbiker,

6
@ArturSapek, ho installato PIL con il pipquale è stato abbastanza facile.
Michaelliu,

1
L'ho usato sul mio Mac (Pypi):easy_install --find-links http://www.pythonware.com/products/pil/ Imaging
Mazyod il

15
Per i futuri lettori: pip install pillowinstallerà PIL con successo e abbastanza rapidamente (potrebbe essere necessario sudose non in un virtualenv).
Christopher Shroba,

pillow.readthedocs.io/en/latest/… mostra i comandi bash nelle fasi di installazione di Windows. Non so davvero come procedere.
Musixauce3000,

31

Usando Pillow (che funziona con Python 3.X e Python 2.7+), puoi fare quanto segue:

from PIL import Image
im = Image.open('image.jpg', 'r')
width, height = im.size
pixel_values = list(im.getdata())

Ora hai tutti i valori di pixel. Se è RGB o è possibile leggere un'altra modalità im.mode. Quindi puoi ottenere pixel (x, y):

pixel_values[width*y+x]

In alternativa, puoi usare Numpy e rimodellare l'array:

>>> pixel_values = numpy.array(pixel_values).reshape((width, height, 3))
>>> x, y = 0, 1
>>> pixel_values[x][y]
[ 18  18  12]

Una soluzione completa e semplice da usare è

# Third party modules
import numpy
from PIL import Image


def get_image(image_path):
    """Get a numpy array of an image so that one can access values[x][y]."""
    image = Image.open(image_path, "r")
    width, height = image.size
    pixel_values = list(image.getdata())
    if image.mode == "RGB":
        channels = 3
    elif image.mode == "L":
        channels = 1
    else:
        print("Unknown mode: %s" % image.mode)
        return None
    pixel_values = numpy.array(pixel_values).reshape((width, height, channels))
    return pixel_values


image = get_image("gradient.png")

print(image[0])
print(image.shape)

Fumo testare il codice

Potresti essere incerto sull'ordine di larghezza / altezza / canale. Per questo motivo ho creato questo gradiente:

inserisci qui la descrizione dell'immagine

L'immagine ha una larghezza di 100 px e un'altezza di 26 px. Ha una sfumatura di colore che va da #ffaa00(giallo) a #ffffff(bianco). L'output è:

[[255 172   5]
 [255 172   5]
 [255 172   5]
 [255 171   5]
 [255 172   5]
 [255 172   5]
 [255 171   5]
 [255 171   5]
 [255 171   5]
 [255 172   5]
 [255 172   5]
 [255 171   5]
 [255 171   5]
 [255 172   5]
 [255 172   5]
 [255 172   5]
 [255 171   5]
 [255 172   5]
 [255 172   5]
 [255 171   5]
 [255 171   5]
 [255 172   4]
 [255 172   5]
 [255 171   5]
 [255 171   5]
 [255 172   5]]
(100, 26, 3)

Cose da notare:

  • La forma è (larghezza, altezza, canali)
  • La image[0], da qui la prima fila, ha 26 triple dello stesso colore

Pillow supporta python 2.7 su macosx mentre trovo solo il supporto python 2.5 su PIL. Grazie!
Canguro.

2
Fai attenzione, l'elenco dei parametri 'rimodella' dovrebbe essere (altezza, larghezza, canali). e per le immagini rgba potresti includere image.mode = RGBA con canali = 4
gmarsi

Il punto di @gmarsi è vero su larghezza e altezza? È davvero vero che entrambi sono validi? È necessario essere consapevoli di come vengono emessi i dati in modo da sapere quale forma avrà l'array di output e dove saranno i dati dei pixel di riga e colonna dell'immagine.
Kioshiki,

@Kioshiki Ho aggiunto una sezione "test del fumo" nella mia risposta, quindi è più facile dirlo.
Martin Thoma,

24

PyPNG - decodificatore / codificatore PNG leggero

Sebbene la domanda suggerisca JPG, spero che la mia risposta possa essere utile ad alcune persone.

Ecco come leggere e scrivere pixel PNG usando il modulo PyPNG :

import png, array

point = (2, 10) # coordinates of pixel to be painted red

reader = png.Reader(filename='image.png')
w, h, pixels, metadata = reader.read_flat()
pixel_byte_width = 4 if metadata['alpha'] else 3
pixel_position = point[0] + point[1] * w
new_pixel_value = (255, 0, 0, 0) if metadata['alpha'] else (255, 0, 0)
pixels[
  pixel_position * pixel_byte_width :
  (pixel_position + 1) * pixel_byte_width] = array.array('B', new_pixel_value)

output = open('image-with-red-dot.png', 'wb')
writer = png.Writer(w, h, **metadata)
writer.write_array(output, pixels)
output.close()

PyPNG è un singolo modulo Python puro lungo meno di 4000 righe, inclusi test e commenti.

PIL è una libreria di imaging più completa, ma è anche significativamente più pesante.


12

Come diceva Dave Webb:

Ecco il mio frammento di codice funzionante che stampa i colori dei pixel da un'immagine:

import os, sys
import Image

im = Image.open("image.jpg")
x = 3
y = 4

pix = im.load()
print pix[x,y]

6
photo = Image.open('IN.jpg') #your image
photo = photo.convert('RGB')

width = photo.size[0] #define W and H
height = photo.size[1]

for y in range(0, height): #each pixel has coordinates
    row = ""
    for x in range(0, width):

        RGB = photo.getpixel((x,y))
        R,G,B = RGB  #now you can use the RGB value

3

La manipolazione delle immagini è un argomento complesso, ed è meglio se non usa una libreria. Posso consigliare gdmodule che fornisce un facile accesso a molti diversi formati di immagine da Python.


Qualcuno sa perché questo è stato downvoted? C'è un problema noto con libgd o qualcosa del genere? (Non l'ho mai visto, ma è sempre bello sapere che c'è un'alternativa a PiL)
Peter Hanley,

3

C'è un ottimo articolo su wiki.wxpython.org intitolato Lavorare con le immagini . L'articolo menziona la possibilità di usare wxWidgets (wxImage), PIL o PythonMagick. Personalmente, ho usato PIL e wxWidgets ed entrambi rendono la manipolazione delle immagini abbastanza semplice.


3

È possibile utilizzare Pygame 's surfarray modulo. Questo modulo ha un metodo di restituzione di array di pixel 3d chiamato pixels3d (superficie). Ho mostrato l'utilizzo di seguito:

from pygame import surfarray, image, display
import pygame
import numpy #important to import

pygame.init()
image = image.load("myimagefile.jpg") #surface to render
resolution = (image.get_width(),image.get_height())
screen = display.set_mode(resolution) #create space for display
screen.blit(image, (0,0)) #superpose image on screen
display.flip()
surfarray.use_arraytype("numpy") #important!
screenpix = surfarray.pixels3d(image) #pixels in 3d array:
#[x][y][rgb]
for y in range(resolution[1]):
    for x in range(resolution[0]):
        for color in range(3):
            screenpix[x][y][color] += 128
            #reverting colors
screen.blit(surfarray.make_surface(screenpix), (0,0)) #superpose on screen
display.flip() #update display
while 1:
    print finished

Spero sia stato utile. Ultima parola: lo schermo è bloccato per tutta la vita di screenpix.


2

installare PIL usando il comando "sudo apt-get install python-imaging" ed eseguire il seguente programma. Stampa i valori RGB dell'immagine. Se l'immagine è grande reindirizzare l'output su un file usando '>' in seguito aprire il file per vedere i valori RGB

import PIL
import Image
FILENAME='fn.gif' #image can be in gif jpeg or png format 
im=Image.open(FILENAME).convert('RGB')
pix=im.load()
w=im.size[0]
h=im.size[1]
for i in range(w):
  for j in range(h):
    print pix[i,j]

2

È possibile utilizzare il modulo Tkinter, che è l'interfaccia standard di Python per il toolkit della GUI di Tk e non è necessario un ulteriore download. Vedi https://docs.python.org/2/library/tkinter.html .

(Per Python 3, Tkinter viene rinominato in tkinter)

Ecco come impostare i valori RGB:

#from http://tkinter.unpythonic.net/wiki/PhotoImage
from Tkinter import *

root = Tk()

def pixel(image, pos, color):
    """Place pixel at pos=(x,y) on image, with color=(r,g,b)."""
    r,g,b = color
    x,y = pos
    image.put("#%02x%02x%02x" % (r,g,b), (y, x))

photo = PhotoImage(width=32, height=32)

pixel(photo, (16,16), (255,0,0))  # One lone pixel in the middle...

label = Label(root, image=photo)
label.grid()
root.mainloop()

E ottieni RGB:

#from http://www.kosbie.net/cmu/spring-14/15-112/handouts/steganographyEncoder.py
def getRGB(image, x, y):
    value = image.get(x, y)
    return tuple(map(int, value.split(" ")))

2
from PIL import Image
def rgb_of_pixel(img_path, x, y):
    im = Image.open(img_path).convert('RGB')
    r, g, b = im.getpixel((x, y))
    a = (r, g, b)
    return a

1
Sebbene questo frammento di codice possa essere la soluzione, includendo una spiegazione aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro e quelle persone potrebbero non conoscere i motivi del tuo suggerimento sul codice.
Narendra Jadhav,

1
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

img=mpimg.imread('Cricket_ACT_official_logo.png')
imgplot = plt.imshow(img)

1

Se stai cercando di avere tre cifre sotto forma di un codice colore RGB, il seguente codice dovrebbe fare proprio questo.

i = Image.open(path)
pixels = i.load() # this is not a list, nor is it list()'able
width, height = i.size

all_pixels = []
for x in range(width):
    for y in range(height):
        cpixel = pixels[x, y]
        all_pixels.append(cpixel)

Questo potrebbe funzionare per te.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.