我正在使用PIL拍摄黑色背景的图像并从中制作一个遮罩。我希望程序做的是遍历图像中的所有像素,如果像素是黑色使其变为白色,如果是任何其他颜色使其变黑,但我不确定如何正确比较像素值以确定什么与像素有关。
到目前为止,这是我的代码,它会创建一个全黑的图像。
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)
我认为问题出在if语句中,将im [j,i]与RGB值(0,0,0)进行比较,后者总是计算为false。比较像素的正确方法是什么?
答案 0 :(得分:4)
像素数据比较是正确的。但是逻辑存在两个问题:
这应该有用(只要你没有alpha通道 - 正如andrewdski指出的那样):
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)
答案 1 :(得分:1)
以下函数使用.point
方法,并在图像的每个波段上单独处理:
CVT_TABLE= (255,) + 255 * (0,)
def do_convert(img):
return img.point(CVT_TABLE * len(img.getbands()))
在每个乐队上单独工作意味着这样的图片:
将转换成这个:
但是,如果首先将图像转换为模式“L”,则几乎可以获得所需的内容:
CVT_TABLE= (255,) + 255 * (0,)
def do_convert(img):
return img.convert("L").point(CVT_TABLE)
产生以下结果:
唯一的缺点是,一些最暗的颜色(例如#000001
,可能是最暗的蓝色)可能会通过模式转换转换为黑色。
答案 2 :(得分:1)
这是我如何重写它,它通过使用for
循环避免像素索引重置问题,将数据写入单独的掩码图像而不是返回到源,并删除硬编码图像大小。我还在文件名字符串中添加了r
前缀来处理其中的反斜杠。
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)