Làm cách nào để đọc giá trị RGB của một pixel đã cho trong Python?


140

Nếu tôi mở một hình ảnh với open("image.jpg"), làm thế nào tôi có thể nhận được các giá trị RGB của một pixel giả sử tôi có tọa độ của pixel?

Sau đó, làm thế nào tôi có thể làm điều ngược lại? Bắt đầu với một đồ họa trống, 'ghi' một pixel có giá trị RGB nhất định?

Tôi muốn nếu tôi không phải tải xuống bất kỳ thư viện bổ sung nào.

Câu trả lời:


213

Có lẽ tốt nhất là sử dụng Thư viện hình ảnh Python để làm điều này mà tôi sợ là tải xuống riêng biệt.

Cách dễ nhất để làm những gì bạn muốn là thông qua phương thức load () trên đối tượng Image trả về một đối tượng truy cập pixel mà bạn có thể thao tác như một mảng:

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

Ngoài ra, hãy xem ImageDraw cung cấp API phong phú hơn nhiều để tạo hình ảnh.


1
May mắn thay, việc cài đặt PIL rất đơn giản trong Linux và Windows (không biết về Mac)
heltonbiker

6
@ArturSapek, tôi đã cài đặt PIL pipkhá dễ dàng.
michaelliu

1
Tôi đã sử dụng điều này trên máy Mac (Pypi):easy_install --find-links http://www.pythonware.com/products/pil/ Imaging
Mazyod

15
Đối với độc giả trong tương lai: pip install pillowsẽ cài đặt PIL thành công và khá nhanh chóng (có thể cần sudonếu không có trong virtualenv).
Christopher Shroba

gối.readthedocs.io/en/latest/ từ hiển thị các lệnh bash trong các bước cài đặt windows. Không thực sự chắc chắn làm thế nào để tiến hành.
Musixauce3000

31

Sử dụng Gối (hoạt động với Python 3.X cũng như Python 2.7+), bạn có thể thực hiện các thao tác sau:

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

Bây giờ bạn có tất cả các giá trị pixel. Nếu nó là RGB hoặc chế độ khác có thể được đọc bởi im.mode. Sau đó, bạn có thể nhận pixel (x, y)bằng cách:

pixel_values[width*y+x]

Ngoài ra, bạn có thể sử dụng Numpy và định hình lại mảng:

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

Một giải pháp hoàn chỉnh, đơn giản để sử dụng là

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

Khói kiểm tra mã

Bạn có thể không chắc chắn về thứ tự chiều rộng / chiều cao / kênh. Vì lý do này, tôi đã tạo gradient này:

nhập mô tả hình ảnh ở đây

Hình ảnh có chiều rộng 100px và chiều cao 26px. Nó có một dải màu đi từ #ffaa00(vàng) đến #ffffff(trắng). Đầu ra là:

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

Những điều cần lưu ý:

  • Hình dạng là (chiều rộng, chiều cao, kênh)
  • Hàng image[0], do đó, hàng đầu tiên, có 26 bộ ba cùng màu

Gối hỗ trợ python 2.7 trên macosx trong khi tôi chỉ tìm thấy hỗ trợ python 2.5 trên PIL. Cảm ơn!
Kangaroo.H

1
Hãy cẩn thận, danh sách thông số 'định hình lại' phải là (chiều cao, chiều rộng, kênh). và đối với hình ảnh rgba, bạn có thể bao gồm image.mode = RGBA với các kênh = 4
gmarsi

Điểm của @gmarsi có đúng về chiều rộng và chiều cao không? Có thực sự là trường hợp cả hai đều hợp lệ? Bạn cần lưu ý về cách dữ liệu được xuất ra để bạn biết mảng đầu ra sẽ có hình dạng như thế nào và dữ liệu pixel của hàng và cột của hình ảnh sẽ ở đâu.
Kioshiki

@Kioshiki Tôi đã thêm phần "kiểm tra khói" trong câu trả lời của mình để dễ nói hơn.
Martin Thoma

24

PyPNG - bộ giải mã / mã hóa PNG nhẹ

Mặc dù câu hỏi gợi ý ở JPG, tôi hy vọng câu trả lời của tôi sẽ hữu ích với một số người.

Dưới đây là cách đọc và ghi pixel PNG bằng mô-đun 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 là một mô-đun Python đơn thuần dài dưới 4000 dòng, bao gồm các bài kiểm tra và nhận xét.

PIL là một thư viện hình ảnh toàn diện hơn, nhưng nó cũng nặng hơn đáng kể.


12

Như Dave Webb đã nói:

Đây là đoạn mã làm việc của tôi in các màu pixel từ một hình ảnh:

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

Hình ảnh thao tác là một chủ đề phức tạp, và đó là tốt nhất nếu bạn làm sử dụng thư viện. Tôi có thể đề xuất gdmodule cung cấp quyền truy cập dễ dàng vào nhiều định dạng hình ảnh khác nhau từ trong Python.


Bất cứ ai cũng biết tại sao điều này đã bị hạ thấp? Có một vấn đề được biết đến với libgd hoặc một cái gì đó? (Tôi chưa bao giờ nhìn vào nó, nhưng thật tuyệt khi biết có một sự thay thế cho PiL)
Peter Hanley

3

Có một bài viết thực sự hay trên wiki.wxpython.org có tên Làm việc với hình ảnh . Bài viết đề cập đến khả năng sử dụng wxWidgets (wxImage), PIL hoặc PythonMagick. Cá nhân tôi đã sử dụng PIL và wxWidgets và cả hai đều giúp thao tác hình ảnh khá dễ dàng.


3

Bạn có thể sử dụng pygame 's surfarray module. Mô-đun này có một phương thức trả về mảng pixel 3d được gọi là pixel3d (bề mặt). Tôi đã hiển thị cách sử dụng bên dưới:

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

Tôi hy vọng là hữu ích. Từ cuối cùng: màn hình bị khóa suốt đời của screenpix.


2

cài đặt PIL bằng lệnh "sudo apt-get install python-hình ảnh" và chạy chương trình sau. Nó sẽ in các giá trị RGB của hình ảnh. Nếu hình ảnh lớn chuyển hướng đầu ra sang tệp bằng cách sử dụng '>' sau đó mở tệp để xem giá trị 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

Bạn có thể sử dụng mô-đun Tkinter, giao diện Python chuẩn cho bộ công cụ GUI Tk và bạn không cần tải thêm. Xem https://docs.python.org/2/l Library / tnternter.html .

(Đối với Python 3, Tkinter được đổi tên thành tkinter)

Dưới đây là cách đặt giá trị 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()

Và nhận 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
Mặc dù đoạn mã này có thể là giải pháp, bao gồm một lời giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn.
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

Nếu bạn đang tìm kiếm để có ba chữ số ở dạng mã màu RGB, mã sau đây sẽ làm điều đó.

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)

Điều này có thể làm việc cho bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.