Як прочитати значення RGB заданого пікселя в Python?


140

Якщо я відкрию зображення за допомогою open("image.jpg"), як я можу отримати значення RGB пікселя, якщо у мене є координати пікселя?

Тоді, як я можу зробити зворотне це? Починаючи з порожньої графіки, "записувати" піксель із певним значенням RGB?

Я вважаю за краще, якби мені не довелося завантажувати додаткові бібліотеки.

Відповіді:


213

Напевно, найкраще використовувати бібліотеку зображень Python, щоб зробити це, бо, боюся, це окреме завантаження.

Найпростіший спосіб зробити те, що ви хочете, це за допомогою методу load () на об’єкт Image, який повертає піксельний об'єкт доступу, яким ви можете маніпулювати як масив:

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

Крім того, подивіться на ImageDraw, який дає набагато більш багатий API для створення зображень.


1
На щастя, встановити PIL дуже просто в Linux та Windows (не знаю про Mac)
heltonbiker

6
@ArturSapek, я встановив PIL, за допомогою pipякого було досить просто.
michaelliu

1
Я використовував це на своєму Mac (Pypi):easy_install --find-links http://www.pythonware.com/products/pil/ Imaging
Mazyod

15
Для майбутніх читачів: pip install pillowвстановіть PIL успішно та досить швидко (може знадобитися, sudoякщо не у virtualenv).
Крістофер Шроба

pillow.readthedocs.io/en/latest/… показує команди bash у кроках встановлення Windows. Не дуже впевнений, як діяти далі.
Musixauce3000

31

Використовуючи Подушку (яка працює з Python 3.X, а також Python 2.7+), ви можете зробити наступне:

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

Тепер у вас є всі значення пікселів. Якщо це RGB або інший режим може бути прочитаний im.mode. Тоді ви можете отримати піксель (x, y):

pixel_values[width*y+x]

Крім того, ви можете використовувати Numpy та змінити масив:

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

Повне, просте у використанні рішення

# 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)

Дим тестує код

Можливо, ви не впевнені в порядку ширини / висоти / каналу. З цієї причини я створив цей градієнт:

введіть тут опис зображення

Зображення має ширину 100 пікселів і висоту 26 пікселів. Він має кольоровий градієнт від #ffaa00(жовтий) до #ffffff(білий). Вихід:

[[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)

Що слід зазначити:

  • Форма (ширина, висота, канали)
  • image[0], Отже , перший ряд, має 26 трійок одного і того ж кольору

Подушка підтримує python 2.7 на macosx, тоді як я знаходжу лише підтримку python 2.5 на PIL. Дякую!
Кенгуру.H

2
Будьте уважні, список параметрів "переформатування" повинен бути (висота, ширина, канали). а для зображень rgba можна включити image.mode = RGBA з каналами = 4
gmarsi

Чи правда @gmarsi щодо ширини та висоти? Чи дійсно так, що обидва дійсні? Вам потрібно знати, як виводяться дані, щоб ви знали, яку форму матиме вихідний масив і де будуть знаходитись дані пікселів рядків та стовпців зображення.
Кіошики,

@Kioshiki У свою відповідь я додав розділ "тестування на дим", щоб це було легше сказати.
Мартін Тома

24

PyPNG - легкий PNG-декодер / кодер

Хоча питання натякає на JPG, я сподіваюся, що моя відповідь буде корисна деяким людям.

Ось як читати та записувати пікселі PNG за допомогою модуля 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 - це єдиний чистий модуль Python довжиною менше 4000 рядків, включаючи тести та коментарі.

PIL - це більш всебічна бібліотека зображень, але вона також значно важча.


12

Як сказав Дейв Вебб:

Ось мій фрагмент робочого коду, що друкує піксельні кольори із зображення:

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

Обробка зображення є складною задачею , і це краще за все, якщо ви дійсно використовуєте бібліотеку. Я можу порекомендувати gdmodule, який забезпечує легкий доступ до багатьох різних форматів зображень зсередини Python.


Хтось знає, чому це було знято? Чи є відома проблема з libgd чи щось? (Я ніколи на це не дивився, але завжди приємно знати, що є альтернатива PiL)
Peter Hanley

3

На wiki.wxpython.org є дійсно гарна стаття під назвою Робота зі зображеннями . У статті згадується можливість використання wxWidgets (wxImage), PIL або PythonMagick. Особисто я використовував PIL і wxWidgets, і обидва роблять зображення маніпуляціями досить просто.


3

Ви можете використовувати модуль surfarray pygame . Цей модуль має метод повернення масиву 3d пікселів, який називається pixels3d (поверхня). Я показав використання нижче:

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

Я сподіваюся, що це було корисно. Останнє слово: екран заблокований протягом усього життя screenpix.


2

встановіть PIL за допомогою команди "sudo apt-get install python-imaging" та запустіть наступну програму. Він буде друкувати значення RGB зображення. Якщо зображення є великим, перенаправляйте вихід у файл, використовуючи '>' пізніше, відкрийте файл, щоб побачити значення 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

Ви можете використовувати модуль Tkinter, який є стандартним інтерфейсом Python для набору інструментів Tk GUI, і додаткове завантаження вам не потрібно. Див. Https://docs.python.org/2/library/tkinter.html .

(Для Python 3 Tkinter перейменовано на tkinter)

Ось як встановити значення 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()

І отримати 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
Хоча цей фрагмент коду може бути вирішенням, зокрема пояснення дійсно допомагає покращити якість вашої публікації. Пам'ятайте, що ви відповідаєте на запитання читачів у майбутньому, і ці люди можуть не знати причини вашої пропозиції щодо коду.
Нарендра Ядхав


1

Якщо ви хочете мати три цифри у вигляді кольорового коду RGB, наступний код повинен робити саме це.

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)

Це може допомогти вам.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.