如何仅使用 Python stdlib 检查 jpeg 图像是彩色还是灰度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23660929/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 03:16:35  来源:igfitidea点击:

How to check whether a jpeg image is color or gray scale using only Python stdlib

pythonimage-processingpython-2.6

提问by kadina

I have to write a test case in python to check whether a jpg image is in color or grayscale. Can anyone please let me know if there is any way to do it with out installing extra libraries like opencv?

我必须在python中编写一个测试用例来检查jpg图像是彩色还是灰度。任何人都可以让我知道是否有任何方法可以在不安装像 opencv 这样的额外库的情况下做到这一点?

采纳答案by joaoricardo000

Expanding @gat answer:

扩展@gat 答案:

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

Basically, check every pixel to see if it is grayscale (R == G == B)

基本上,检查每个像素是否是灰度(R == G == B)

回答by gat

As you are probably correct, OpenCV may be an overkill for this task but it should be okay to use Python Image Library (PIL) for this. The following should work for you:

正如您可能是对的,OpenCV 可能对这项任务来说太过分了,但为此使用 Python 图像库 (PIL) 应该没问题。以下应该对您有用:

import Image
im = Image.open("lena.jpg")

EDITAs pointed out by Mark and JRicardo000, you may iterate over each pixel. You could also make use of the im.split() function here.

编辑正如 Mark 和 JRicardo000 所指出的,您可以迭代每个像素。您还可以在此处使用 im.split() 函数。

回答by smci

A performance-enhance for fast results: since many images have black or white border, you'd expect faster termination by sampling a few random i,j-points from im and test them? Or use modulo arithmetic to traverse the image rows. First we sample(-without-replacement) say 100 random i,j-points; in the unlikely event that isn't conclusive, then we scan it linearly.

快速结果的性能增强:由于许多图像具有黑色或白色边框,您希望通过从 im 中采样一些随机 i,j 点并测试它们来更快地终止吗?或者使用模运算来遍历图像行。首先我们采样(-无替换)说 100 个随机 i,j 点;在不太确定的情况下,我们会线性扫描它。

Using a custom iterator iterpixels(im). I don't have PIL installed so I can't test this, here's the outline:

使用自定义迭代器 iterpixels(im)。我没有安装 PIL,所以我无法测试这个,这是大纲:

import Image

def isColor(r,g,b): # use tuple-unpacking to unpack pixel -> r,g,b
    return (r != g != b)

class Image_(Image):
    def __init__(pathname):
        self.im = Image.open(pathname)
        self.w, self.h = self.im.size
    def iterpixels(nrand=100, randseed=None):
        if randseed:
            random.seed(randseed) # For deterministic behavior in test
        # First, generate a few random pixels from entire image
        for randpix in random.choice(im, n_rand)
            yield randpix
        # Now traverse entire image (yes we will unwantedly revisit the nrand points once)
        #for pixel in im.getpixel(...): # you could traverse rows linearly, or modulo (say) (im.height * 2./3) -1
        #    yield pixel

    def is_grey_scale(img_path="lena.jpg"):
        im = Image_.(img_path)
        return (any(isColor(*pixel)) for pixel in im.iterpixels())

(Also my original remark stands, first you check the JPEG header, offset 6: number of components (1 = grayscale, 3 = RGB). If it's 1=grayscale, you know the answer already without needing to inspect individual pixels.)

(我的原话也是如此,首先你检查 JPEG 头,偏移量 6:分量数(1 = 灰度,3 = RGB)。如果它是 1 = 灰度,你已经知道答案,而无需检查单个像素。)

回答by GriMel

Why wouldn't we use ImageStat module?

为什么我们不使用 ImageStat 模块?

from PIL import Image, ImageStat

def is_grayscale(path="image.jpg")

    im = Image.open(path).convert("RGB")
    stat = ImageStat.Stat(im)

    if sum(stat.sum)/3 == stat.sum[0]:
        return True
    else:
        return False

stat.sumgives us a sum of all pixels in list view = [R, G, B] for example [568283302.0, 565746890.0, 559724236.0]. For grayscale image all elements of list are equal.

stat.sum为我们提供了列表视图中所有像素的总和 = [R, G, B] 例如 [568283302.0, 565746890.0, 559724236.0]。对于灰度图像,列表的所有元素都是相等的。

回答by superMind

Can be done as follow:

可以按如下方式进行:

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'

回答by Karl K

For faster processing, it is better to avoid loops on every pixel, using ImageChops, (but also to be sure that the image is truly grayscale, we need to compare colors on every pixel and cannot just use the sum):

为了更快的处理,最好避免在每个像素上循环,使用 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

回答by Alexey Antonenko

There is more pythonic way using numpy functionality and opencv:

使用 numpy 功能和 opencv 有更多 pythonic 方式:

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