简体   繁体   English

如何测试图像为灰度?

[英]How can I test an image to be grayscale?

In the Aforge .net/ Accord .net library, the following test is performed to determine whether an image is grayscale: Aforge .net / Accord .net库中, 执行以下测试以确定图像是否为灰度:

public static bool IsGrayscale (Bitmap image)
{
    bool ret = false;

    // check pixel format
    if (image.PixelFormat == PixelFormat.Format8bppIndexed)
    {
        ret = true;
        // check palette
        ColorPalette cp = image.Palette;
        Color c;
        // init palette
        for ( int i = 0; i < 256; i++ )
        {
            c = cp.Entries[i];
            if ((c.R != i) || (c.G != i) || (c.B != i))
            {
                ret = false;
                break;
            }
        }
    }
    return ret;
}

Isn't it fallacious? 这不是谬误吗?

As far as the definition goes, a Grayscale image can be of any color depth except 1-bit pp. For instance, the following is a 32-bit grayscale image: 定义而言,灰度图像可以是除1位pp之外的任何颜色深度。例如,以下是32位灰度图像:

在此输入图像描述
在此输入图像描述

So, my question is, what is the proper way to test a Grayscale image? 所以,我的问题是,测试灰度图像的正确方法是什么?

Looks like I got my answer in this link . 看起来我在这个链接中得到了答案。

If the image is a Gray Scale image then 如果图像是灰度图像那么

 if(R=G=B) //Grayscale 

For more accurate results you can introduce some thresholds values. 要获得更准确的结果,您可以引入一些阈值。 ie

 if((abs(RG)< Threshold))// Threshold-> can be greater than zero. eg 0.006 //Grayscale 

By this way you can get pretty good results. 通过这种方式,您可以获得相当不错的结果。

But, I suspect, this procedure would be as slow as hell. 但是,我怀疑, 这个程序会像地狱一样慢。

So, anyone with a better idea is welcome to answer. 因此,欢迎任何有更好主意的人回答。

That code is checking for standard 8-bit grayscale where the pixel values correspond to their brightness. 该代码检查标准的8位灰度,其中像素值对应于它们的亮度。 This is more or less a standard for grayscale, but it will indeed not match optimised palettes or anything like that. 这或多或少是灰度的标准,但它确实不匹配优化的调色板或类似的东西。

I'm not sure why you would exclude 1bpp though. 我不知道为什么你会排除1bpp。 It's an indexed format like any other, and in fact has a colour palette just like 8bpp, meaning it is not even limited to pure black and white. 它是一种与任何其他格式一样的索引格式,实际上有一个像8bpp一样的调色板,这意味着它甚至不仅限于纯黑色和白色。 This is a 1bpp grayscale version of that parrot with two gray values in its palette: 这是该鹦鹉的1bpp灰​​度版本,其调色板中有两个灰度值:

1bpp灰​​鹦鹉

The simplest way to check indexed images is indeed to go over the palette and do the R=G=B test, but technically, even then, you could argue that the image is grayscale as long as any non-gray colours on the palette are not actually used on the image. 检查索引图像的最简单方法确实是通过调色板并进行R = G = B测试,但从技术上讲,即使这样,你也可以认为只要调色板上的任何非灰色颜色都是灰度图像没有实际使用的图像。

A sure-fire way is probably just to make LockBits convert the image to 32bppARGB, and then check the R, G and B on that. 一种可靠的方法可能只是让LockBits将图像转换为32bppARGB,然后检查R,G和B. But even there you'll have to make choices... do 100% transparent pixels that don't match R=G=B make the image "not grayscale" ? 但即使在那里你也必须做出选择...... 100%透明像素与R = G = B不匹配使图像“不灰度”

Anyway, here would be the method I'd use: 无论如何,这将是我使用的方法:

public static Boolean IsGrayscale(Bitmap cur)
{
    // Indexed format, and no non-gray colours in the images palette: immediate pass.
    if ((cur.PixelFormat & PixelFormat.Indexed) == PixelFormat.Indexed
        && cur.Palette.Entries.All(c => c.R == c.G && c.R == c.B))
        return true;
    // Quick indexed check failed; actually check image data.
    // Get bytes out of the image, converted to 32bpp ARGB 
    BitmapData curBitmapData = cur.LockBits(new Rectangle(0, 0, cur.Width, cur.Height),
        ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    Int32 stride = curBitmapData.Stride;
    Byte[] data = new Byte[stride * cur.Height];
    Marshal.Copy(curBitmapData.Scan0, data, 0, data.Length);
    cur.UnlockBits(curBitmapData);
    // Go over all bytes per block of four.
    Int32 curRowOffs = 0;
    for (Int32 y = 0; y < cur.Height; y++)
    {
        // Set offset to start of current row
        Int32 curOffs = curRowOffs;
        for (Int32 x = 0; x < cur.Width; x++)
        {
            Byte b = data[curOffs];
            Byte g = data[curOffs + 1];
            Byte r = data[curOffs + 2];
            Byte a = data[curOffs + 3];
            // Increase offset to next colour
            curOffs += 4;
            if (a == 0)
                continue;
            if (r != g || r != b)
                return false;
        }
        // Increase row offset
        curRowOffs += stride;
    }
    return true;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM