如何比较像素?

3 投票
3 回答
15325 浏览
提问于 2025-04-16 18:08

我正在使用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)进行比较,但这个比较总是返回假。我想知道正确的比较像素的方法是什么。

3 个回答

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

这是我重新写的代码,它通过使用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)
4

像素数据的比较是正确的。但是逻辑上有两个问题:

  1. 当你处理完一行时,应该把 j 重置为 0。
  2. 你在修改对象 "im",但却在写 "mask"。

只要你没有使用 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)

撰写回答