I want to create a program that loads the RGB values of each pixel in a image and saves them in some kind of list/dictionary/tuple and then when I type in a value it tells me how much pixels in the image have that value. So far I have read through the whole PIL documentation trying to find a method that could fit my needs and I have tried several other approaches with for example the .getpixel() or the .load() fun开发者_运维问答ction, but it is very difficult to save and evaluate that information for each pixel.
First, you will want to convert the image to the "RGB" mode, so that you always get (R, G, B) tuples for pixels, even for grayscale/monochrome images.
image = image.convert("RGB")
Then, iterate over getdata()
to build your histogram.
colors = {}
for color in image.getdata():
colors[color] = colors.get(color, 0) + 1
Then, you can use get() to retreive the number of pixels of a given color
print colors.get((255, 255, 255), 0) # No. of white pixels
New in version 1.1.5 of PIL is the method getcolors()
which should do exactly what you're looking for. The documentation from the PIL web documentation follows:
getcolors
im.getcolors() => a list of (count, color) tuples or None
im.getcolors(maxcolors) => a list of (count, color) tuples or None
(New in 1.1.5) Returns an unsorted list of (count, color) tuples, where the count is the number of times the corresponding color occurs in the image.
If the maxcolors value is exceeded, the method stops counting and returns None. The default maxcolors value is 256. To make sure you get all colors in an image, you can pass in size[0]*size[1] (but make sure you have lots of memory before you do that on huge images).
.load()
is the way to go. It works really efficiently and allows to get many pixels quickly.
width,height=image.size
px=image.load()
col={}
for y in range(height):
for x in range(width):
c=px[x,y]
col[c]=col.get(c,0)+1
# `col` will look like this: {(r,g,b):n,...}
I think that .getpixel()
is exactly what you need — if you are going to be doing lots of lookups and you need speed, then loop over each image once, creating a dictionary of coordinates at which each color is found. Make it look like this:
{
(128,128,4): [(1,1), (1,2)],
(128,130,6): [(1,3)],
...
}
Of course, if it is really just the counts you need (you are building a histogram, then?), then just store an integer at each dictionary entry instead of the whole list of points.
If only the .histogram()
method broke its results out by specific color — but it looks like it returns each channel separately, without regard for the combinations in which the various color components appear together.
精彩评论