Getting pixels from an image using PIL
You can read pixels with Image.getpixel()
from PIL.
The code below will give you all non-white pixels in the form of a 2D list.
from PIL import Image
im = Image.open('x.bmp')
imageSizeW, imageSizeH = im.size
nonWhitePixels = []
for i in range(1, imageSizeW):
for j in range(1, imageSizeH):
pixVal = im.getpixel((i, j))
if pixVal != (255, 255, 255):
nonWhitePixels.append([i, j])
print(nonWhitePixels)
Get pixel's RGB using PIL
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: 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.
How to create image from a list of pixel values in Python3?
PIL
and numpy
are your friends here:
from PIL import Image
import numpy as np
pixels = [
[(54, 54, 54), (232, 23, 93), (71, 71, 71), (168, 167, 167)],
[(204, 82, 122), (54, 54, 54), (168, 167, 167), (232, 23, 93)],
[(71, 71, 71), (168, 167, 167), (54, 54, 54), (204, 82, 122)],
[(168, 167, 167), (204, 82, 122), (232, 23, 93), (54, 54, 54)]
]
# Convert the pixels into an array using numpy
array = np.array(pixels, dtype=np.uint8)
# Use PIL to create an image from the new array of pixels
new_image = Image.fromarray(array)
new_image.save('new.png')
EDIT:
A little fun with numpy
to make an image of random pixels:
from PIL import Image
import numpy as np
def random_img(output, width, height):
array = np.random.random_integers(0,255, (height,width,3))
array = np.array(array, dtype=np.uint8)
img = Image.fromarray(array)
img.save(output)
random_img('random.png', 100, 50)
How to read the RGB value of a given pixel in Python?
It's probably best to use the Python Image Library to do this which I'm afraid is a separate download.
The easiest way to do what you want is via the load() method on the Image object which returns a pixel access object which you can manipulate like an 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
Alternatively, look at ImageDraw which gives a much richer API for creating images.
How to get a list of float RGBA pixels values using Pillow?
This is what I was using for RGB .png:
from PIL import Image
import numpy
# http://www.schaik.com/pngsuite/basn2c16.png
im = Image.open('basn2c16.png')
#~ data = numpy.asarray(im)
data = numpy.array(im) # same as .asarray
print("Array dimensions: %s"%(repr(data.shape)))
data = data.astype(float)
print("[20, 30]=%s"%(repr(data[20, 30])))
print(data)
data = numpy.divide(data, 255.0)
print(data)
Nowever, note that it depends on type of .png; for instance, see http://www.schaik.com/pngsuite/pngsuite_bas_png.html for test files, and for basn2c16.png
which is "3x16 bits rgb color", the printouts are:
Array dimensions: (32, 32, 3)
[20, 30]=array([ 8., 90., 156.])
[[[ 255. 255. 0.]
[ 247. 255. 0.]
[ 239. 255. 0.]
...
[[[ 1. 1. 0. ]
[ 0.96862745 1. 0. ]
[ 0.9372549 1. 0. ]
...,
So, even if this is 16-bit, the values seem to span 0-255, as if for 8-bit. In this case, we need to scale the data with numpy.divide
with 255 to get a float range 0.0-1.0 ...
However, if you use an indexed/palleted png basn3p08.png
, you get:
Array dimensions: (32, 32)
[20, 30]=120.0
[[ 165. 165. 165. ..., 254. 254. 254.]
[ 8. 8. 8. ..., 248. 248. 248.]
....
so now the matrix contents do not represent RGB(A) values, but instead an index in a color palette, so dividing with 255 has no meaning.
Finally, if it's an RGBA png like basn6a16.png
, you will get the alpha as well:
Array dimensions: (32, 32, 4)
[20, 30]=array([ 0., 88., 167., 16.])
[[[ 255. 255. 0. 0.]
[ 247. 255. 0. 0.]
...
Again, even if this is 16-bit png, the values seem scaled to 255, so dividing with 255 to obtain floats makes sense.
In other words, its relatively easy to scale the matrix values with numpy
and PIL, however, you should make sure the matrix is in the right format for that...
Related Topics
Why Does Pandas Apply Calculate Twice
Read a File Line by Line from S3 Using Boto
Class Variables Is Shared Across All Instances in Python
Add Zeros to a Float After the Decimal Point in Python
Recursively Iterate Through All Subdirectories Using Pathlib
Python List Comprehension - Want to Avoid Repeated Evaluation
Find Out How Many Times a Regex Matches in a String in Python
Fastest Way to Search a List in Python
How to Return a Subset of a List That Matches a Condition
Value Error Trying to Install Python for Windows Extensions
From ... Import or Import ... as for Modules
Python - Read File from and to Specific Lines of Text
Keep a Subprocess Alive and Keep Giving It Commands? Python
Axes Class - Set Explicitly Size (Width/Height) of Axes in Given Units
Why Is 'Object' an Instance of 'Type' and 'Type' an Instance of 'Object'