开发者

How do you compare pixels?

开发者 https://www.devze.com 2023-03-07 10:08 出处:网络
I am using the PIL to take an image with a black background and make a mask out of it. What I want the program to do is iterate through all the pixels in the image and if the pixel is black make it wh

I am using the PIL to take an image with a black background and make a mask out of it. What I want the program to do is iterate through all the pixels in the image and if the pixel is black make it white and if it is any other color make it black, but I am not sure how to appropriately compare pixel values to determine what to do with the pixel.

Here is my code so far which creates an all black image.

import os, sys
import Image

filename = "C:\Users\pdiffley\Dropbox\C++2\Code\Test\BallSpriteImage.bmp"
height   = 50
width    = 50


im = Image.open(filename)
im = im.load()

i = 0
j = 0
while i<height:
    while j<width:
        if im[j,i] == (0,0,0):
            im[j,i] = (255,255,255)
        else:
            im[j,i] = (0,0,0) 
        j = j+1
    i = i+1
mask = Image.new('RGB', (width, height))
newfile = filename.partition('.')
newfile = newfile[0] + "Mask.bmp"

mask.save(newfile)

I believe the problem is in the if statement comparing the im[j,i] to the RGB value (0,0,0) which always evaluates to false. What is th开发者_C百科e correct way to compare the pixel?


The pixel data comparison is correct. But there are two problems with the logic:

  1. When you are finished with a row, you should reset j to 0.
  2. You are modifying the object "im", but writing "mask".

This should work (as long as you have no alpha channel - as andrewdski pointed out):

img = Image.open(filename)
im = img.load()

i = 0
while i<height:
    j = 0
    while j<width:
        if im[j,i] == (0,0,0):
            im[j,i] = (255,255,255)
        else:
            im[j,i] = (0,0,0) 
        j = j+1
    i = i+1
newfile = filename.partition('.')
newfile = newfile[0] + "Mask.png"

img.save(newfile)


Here's how I'd rewrite it, which avoids a pixel index reset problem by using for loops, writes the data to a separate mask image rather than back onto the source, and removes the hardcoded image size. I also added an r prefix to the filename string to handle the backslashes in it.

import os, sys
import Image

BLACK = (0,0,0)
WHITE = (255, 255, 255)

filename = r"C:\Users\pdiffley\Dropbox\C++2\Code\Test\BallSpriteImage.bmp"

img = Image.open(filename)
width, height = img.size
im = img.load()

mask = Image.new('RGB', (width, height))
msk = mask.load()

for y in xrange(height):
    for x in xrange(width):
        if im[x,y] == BLACK:
            msk[x,y] = WHITE
        else:  # not really needed since mask's initial color is black
            msk[x,y] = BLACK

newfilename = filename.partition('.')
newfilename = newfilename[0] + "Mask.bmp"
mask.save(newfilename)


The following function uses the .point method and works on separately on each band of the image:

CVT_TABLE= (255,) + 255 * (0,)

def do_convert(img):
    return img.point(CVT_TABLE * len(img.getbands()))

Working separately on each band means that a picture like this:

How do you compare pixels?


will be converted into this:

How do you compare pixels?

However, you can get almost what you want if you convert the image to mode "L" first:

CVT_TABLE= (255,) + 255 * (0,)

def do_convert(img):
    return img.convert("L").point(CVT_TABLE)

producing the following result:

How do you compare pixels?

The only drawback is that a few darkest colors (e.g. #000001, the darkest blue possible) will probably be converted to black by the mode conversion.

0

精彩评论

暂无评论...
验证码 换一张
取 消