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:
- When you are finished with a row, you should reset j to 0.
- 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:
will be converted into this:
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:
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.
精彩评论