在 Aforge .net / Accord .net库中,执行the following test以确定图像是否为灰度:
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;
}
这不是谬误吗?
就definition而言,灰度图像可以具有除1位pp之外的任何颜色深度。例如,以下是32位灰度图像:
所以,我的问题是,测试灰度图像的正确方法是什么?
答案 0 :(得分:2)
好像我在this link中得到了答案。
如果图像是灰度图像,则
if(R=G=B) //Grayscale
为获得更准确的结果,您可以引入一些阈值。即
if((abs(R-G)< Threshold))// Threshold-> can be greater than zero. eg 0.006 //Grayscale
通过这种方式,您可以获得很好的结果。
但是,我怀疑此过程会像地狱一样慢。
因此,欢迎有更好主意的人回答。
答案 1 :(得分:1)
该代码正在检查标准8位灰度,其中像素值与其亮度相对应。这或多或少是灰度的标准,但是它确实不能匹配优化的调色板或类似的东西。
我不确定您为什么会排除1bpp。它是一种索引格式,与其他格式一样,实际上具有与8bpp一样的调色板,这意味着它甚至不限于纯黑白。这是该鹦鹉的1bpp灰度版本,在其调色板中带有两个灰度值:
检查索引图像的最简单方法实际上是检查调色板并进行R = G = B测试,但是从技术上讲,即使这样,您也可以认为只要是非灰色颜色,图像都是灰度的。调色板实际上并未在图像上使用。
确定有效的方法可能只是使LockBits将图像转换为32bppARGB,然后在其上检查R,G和B。但即使在那儿,您也必须做出选择... do 100% transparent pixels that don't match R=G=B make the image "not grayscale"?
无论如何,这就是我要使用的方法:
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;
}