Get pixel's RGB using PIL

PythonImagePython Imaging-LibraryRgbPixel

Python Problem Overview


Is it possible to get the RGB color of a pixel using PIL? I'm using this code:

im = Image.open("image.gif")
pix = im.load()
print(pix[1,1])

However, it only outputs a number (e.g. 0 or 1) and not three numbers (e.g. 60,60,60 for R,G,B). I guess I'm not understanding something about the function. I'd love some explanation.

Thanks a lot.

Python Solutions


Solution 1 - Python

Yes, this way:

im = Image.open('image.gif')
rgb_im = im.convert('RGB')
r, g, b = rgb_im.getpixel((1, 1))

print(r, g, b)
(65, 100, 137)

The reason you were getting a single value before with pix[1, 1] is because GIF pixels refer to one of the 256 values in the GIF color palette.

See also this SO post: https://stackoverflow.com/questions/5800009/python-and-pil-pixel-values-different-for-gif-and-jpeg and this PIL Reference page contains more information on the convert() function.

By the way, your code would work just fine for .jpg images.

Solution 2 - Python

GIFs store colors as one of x number of possible colors in a palette. Read about the gif limited color palette. So PIL is giving you the palette index, rather than the color information of that palette color.

Edit: Removed link to a blog post solution that had a typo. Other answers do the same thing without the typo.

Solution 3 - Python

With numpy :

im = Image.open('image.gif')
im_matrix = np.array(im)
print(im_matrix[0][0])

Give RGB vector of the pixel in position (0,0)

Solution 4 - Python

An alternative to converting the image is to create an RGB index from the palette.

from PIL import Image

def chunk(seq, size, groupByList=True):
	"""Returns list of lists/tuples broken up by size input"""
	func = tuple
	if groupByList:
		func = list
	return [func(seq[i:i + size]) for i in range(0, len(seq), size)]


def getPaletteInRgb(img):
	"""
	Returns list of RGB tuples found in the image palette
	:type img: Image.Image
    :rtype: list[tuple]
	"""
	assert img.mode == 'P', "image should be palette mode"
	pal = img.getpalette()
	colors = chunk(pal, 3, False)
	return colors

# Usage
im = Image.open("image.gif")
pal = getPalletteInRgb(im)

Solution 5 - Python

Not PIL, but imageio.imread might still be interesting:

import imageio
im = scipy.misc.imread('um_000000.png', flatten=False, mode='RGB')
im = imageio.imread('Figure_1.png', pilmode='RGB')
print(im.shape)

gives

(480, 640, 3)

so it is (height, width, channels). So the pixel at position (x, y) is

color = tuple(im[y][x])
r, g, b = color

Outdated

scipy.misc.imread is deprecated in SciPy 1.0.0 (thanks for the reminder, fbahr!)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGermainZView Question on Stackoverflow
Solution 1 - PythonLevonView Answer on Stackoverflow
Solution 2 - PythonKobeJohnView Answer on Stackoverflow
Solution 3 - PythonRaphaël GervilliéView Answer on Stackoverflow
Solution 4 - PythonMarcel WilsonView Answer on Stackoverflow
Solution 5 - PythonMartin ThomaView Answer on Stackoverflow