Python PIL 检测图片是否完全为黑色或白色

29
使用Python Imaging Library(PIL),如何检测一张图片是否所有像素都是黑色或白色?
~更新~
条件:不要迭代每个像素!

4
你目前为止尝试过什么?检测一张图片是否只使用了一种颜色并不太难。 - Martijn Pieters
只需迭代每个像素并检查其值。您是否阅读了手册 - David Cain
@David 我不想这么做。是的,我不是那么新手的人。 - Jimmy Kane
@MartijnPieters 我正在尝试使用直方图,但目前还没有成功。 - Jimmy Kane
4
你的问题缺乏细节,因此我们只能假设最基本的情况。如果你告诉我们你尝试过什么以及为何不起作用,那会帮助我们更好地理解你已经知道了什么,以及你想要实现什么目标。 - Martijn Pieters
这个问题涉及到PIL,所以我请求提供该库的方法和一般性建议,以便检测它是黑色还是白色。 - Jimmy Kane
4个回答

37
if not img.getbbox():

...将测试图像是否完全为黑色。(如果图像中没有非黑色像素,则 Image.getbbox() 返回假值 None,否则返回点的元组,是真值。)要测试图像是否完全为白色,请先反转它:

if not ImageChops.invert(img).getbbox():

你还可以使用img.getextrema()。这将告诉你图像中最高和最低的值。为了更方便地处理这个值,你应该先将图像转换为灰度模式(否则极值可能是一个RGB或RGBA元组,也可能是一个单独的灰度值,或者是一个索引,你需要处理所有这些情况)。

extrema = img.convert("L").getextrema()
if extrema == (0, 0):
    # all black
elif extrema == (1, 1):
    # all white

后一种方法可能会更快,但在大多数应用程序中你不会注意到(两种方法都相当快)。

上述技术的一行版本,可以测试黑色或白色:

if sum(img.convert("L").getextrema()) in (0, 2):
    # either all black or all white

那正是我所询问的!感谢您的时间。 - Jimmy Kane
你确定吗?对于这张白色图片http://wordpress.com/i/blank.jpg,我得到了极值等于(255, 255)。 - ducu
还有其他不同格式的白色图像。我正在使用Pillow,可能是原因。 - ducu
2
是的,一年半前Pillow曾经引起了我的关注。如果他们决定将图像值表示为字节而不是范围在0.0到1.0之间的浮点数,我也不会感到惊讶。但是,这些技术都可以轻松地适应使用的任何值。 - kindall

15

扩展Kindall:

如果您查看名为img的图像,则为:

extrema = img.convert("L").getextrema()

它给出了图像中值的范围。因此,全黑的图像将是(0,0),而全白的图像将是(255,255)。因此,您可以查看:

if extrema[0] == extrema[1]:
    return("This image is one solid color, so I won't use it")
else:
    # do something with the image img
    pass

在我创建缩略图并希望确保正确读取一些数据时,这对我非常有用。

谢谢。非常好的方法。 - Jimmy Kane

11
from PIL import Image
img = Image.open("test.png")
clrs = img.getcolors()

clrs 包含 [("出现次数", "颜色"), ...]

通过检查 len(clrs) == 1,您可以验证图像是否仅包含一种颜色,并通过查看 clrs 中第一个元组的第二个元素来推断颜色。

如果图像包含多种颜色,则可以考虑到出现次数来处理几乎完全单色的图像,如果99%的像素共享相同的颜色。


2

我尝试了 Kindall 的解决方案 ImageChops.invert(img).getbbox(),但没有成功,我的测试图像失败了。

我注意到一个问题,白色应该是255我发现白色图像的数值极值是(0,0)..这是为什么呢?请参见下面的更新。

我改变了 Kindall 的第二个解决方案(getextrema),它可以正确运行,而且不需要图像转换。我编写了一个函数,并验证了它对灰度和RGB图像都起作用:

def is_monochromatic_image(img):
    extr = img.getextrema()
    a = 0
    for i in extr:
        if isinstance(i, tuple):
            a += abs(i[0] - i[1])
        else:
            a = abs(extr[0] - extr[1])
            break
    return a == 0
img参数是一个PIL图像对象。你可以进行小的修改来检查图像是否为黑白,但是你需要决定“白色”是0还是255,也许你有最终答案,我没有。:-) 希望有用。
更新:我认为,带有零内部的白色图像可能是具有透明度的PNG或其他图像格式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接