如何仅用Python标准库检查JPEG图像是彩色还是灰度

42 投票
12 回答
93363 浏览
提问于 2025-04-18 06:34

我需要用Python写一个测试案例,来检查一个jpg图片是彩色的还是黑白的。有没有人能告诉我有没有办法在不安装额外库(比如OpenCV)的情况下做到这一点?

12 个回答

6

在处理灰度图像时,某个像素的所有通道值都是相同的(如果只有一个通道,那就没问题了)。

所以,基本上你可以列出所有像素的三个通道值,来检查每个像素的三个通道是否都相等。

Image.getcolors() 这个函数会返回一个无序的 (数量, 像素) 值的列表。

im = Image.open('path_to_image.whatever')
color_count = im.getcolors()

如果 len(color_count) 超过 256(默认的最大值),那么这个函数会返回 None,这意味着你的像素列表中有超过 256 种颜色选项,因此这是一张彩色图像(灰度图像最多只能有 256 种颜色,从 (0,0,0)(255,255,255))。

所以之后你只需要:

if color_count: 
    # your image is grayscale
else:
    # your images is colored

请注意,这个方法只在使用 getcolors() 的默认参数值时有效。

文档链接: https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.getcolors

19

为了提高处理速度,最好避免对每个像素进行循环操作。可以使用ImageChops这个工具。不过,为了确保图像确实是灰度的,我们需要检查每个像素的颜色,而不能仅仅依靠颜色的总和来判断。

from PIL import Image,ImageChops

def is_greyscale(im):
    """
    Check if image is monochrome (1 channel or 3 identical channels)
    """
    if im.mode not in ("L", "RGB"):
        raise ValueError("Unsuported image mode")

    if im.mode == "RGB":
        rgb = im.split()
        if ImageChops.difference(rgb[0],rgb[1]).getextrema()[1]!=0: 
            return False
        if ImageChops.difference(rgb[0],rgb[2]).getextrema()[1]!=0: 
            return False
    return True
22

这里有一种更符合Python风格的方法,使用了numpy的功能和opencv库:

import cv2
def isgray(imgpath):
    img = cv2.imread(imgpath)
    if len(img.shape) < 3: return True
    if img.shape[2]  == 1: return True
    b,g,r = img[:,:,0], img[:,:,1], img[:,:,2]
    if (b==g).all() and (b==r).all(): return True
    return False
31

可以这样做:

from scipy.misc import imread, imsave, imresize
image = imread(f_name)
if(len(image.shape)<3):
      print 'gray'
elif len(image.shape)==3:
      print 'Color(RGB)'
else:
      print 'others'
26

你可以检查每一个像素,看看它是否是灰度的(也就是红色、绿色和蓝色的值相等)。

from PIL import Image

def is_grey_scale(img_path):
    img = Image.open(img_path).convert('RGB')
    w, h = img.size
    for i in range(w):
        for j in range(h):
            r, g, b = img.getpixel((i,j))
            if r != g != b: 
                return False
    return True

撰写回答