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

时间:2022-04-24 21:23:37

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?

6 个解决方案

#1


5  

Expanding @gat answer:

扩大@gat回答:

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

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

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

#2


6  

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'

#3


3  

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:

使用自定义迭代器迭代像素(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=灰度,那么您已经知道答案,而不需要检查单个像素。

#4


2  

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):

为了更快的处理,最好避免使用imagechop对每个像素进行循环(但也要确保图像是真正的灰度,我们需要对每个像素的颜色进行比较,不能只使用求和):

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

#5


0  

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")

EDIT As 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()函数。

#6


0  

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.sum gives 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.

sum给出列表视图中所有像素的总和,例如[568283302.0,565746890.0,559724236.0]。对于灰度图像,列表的所有元素都是相等的。

#1


5  

Expanding @gat answer:

扩大@gat回答:

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

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

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

#2


6  

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'

#3


3  

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:

使用自定义迭代器迭代像素(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=灰度,那么您已经知道答案,而不需要检查单个像素。

#4


2  

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):

为了更快的处理,最好避免使用imagechop对每个像素进行循环(但也要确保图像是真正的灰度,我们需要对每个像素的颜色进行比较,不能只使用求和):

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

#5


0  

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")

EDIT As 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()函数。

#6


0  

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.sum gives 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.

sum给出列表视图中所有像素的总和,例如[568283302.0,565746890.0,559724236.0]。对于灰度图像,列表的所有元素都是相等的。