10

我正在将文档扫描为 JPG 图像。扫描仪必须将所有页面扫描为彩色或所有页面扫描为黑白。由于我的许多页面都是彩色的,因此我必须将所有页面都扫描为彩色。扫描完成后,我想用 .Net 检查图像并尝试检测哪些图像是黑白的,这样我就可以将这些图像转换为灰度并节省存储空间。

有人知道如何用.Net 检测灰度图像吗?

请告诉我。

4

6 回答 6

14

如果您找不到为此的库,您可以尝试抓取图像的大量(或全部)像素,并查看它们的 r、g 和 b 值是否在某个阈值内(您可以根据经验设置,或作为一种设置)彼此。如果是,则图像是灰度的。

我肯定会让测试的阈值比 0 大一点,但是......所以我不会测试 r=g,例如,但是 (abs(rg) < e) 其中 e 是你的阈值。这样你就可以降低你的假彩色阳性......因为我怀疑你会得到一个不错的数字,除非你的原始图像和扫描技术提供精确的灰度。

于 2009-12-09T22:37:37.527 回答
6

测试颜色的简单算法:在嵌套的 for 循环(宽度和高度)中逐像素遍历图像,并测试像素的 RGB 值是否相等。如果不是,则图像具有颜色信息。如果你一直通过所有像素而不遇到这种情况,那么你就有一个灰度图像。

使用更复杂的算法进行修订:

在这篇文章的第一个版本中,我提出了一个简单的算法,如果每个像素的 RGB 值相等,则假设像素是灰度的。因此 0,0,0 或 128,128,128 或 230,230,230 的 RGB 都将测试为灰色,而 123,90,78 则不会。简单的。

这是一个测试灰色差异的代码片段。这两种方法是更复杂过程的一小部分,但应该提供足够的原始代码来帮助解决原始问题。

/// <summary>
/// This function accepts a bitmap and then performs a delta
/// comparison on all the pixels to find the highest delta
/// color in the image. This calculation only works for images
/// which have a field of similar color and some grayscale or
/// near-grayscale outlines. The result ought to be that the
/// calculated color is a sample of the "field". From this we
/// can infer which color in the image actualy represents a
/// contiguous field in which we're interested.
/// See the documentation of GetRgbDelta for more information.
/// </summary>
/// <param name="bmp">A bitmap for sampling</param>
/// <returns>The highest delta color</returns>
public static Color CalculateColorKey(Bitmap bmp)
{
    Color keyColor = Color.Empty;
    int highestRgbDelta = 0;

    for (int x = 0; x < bmp.Width; x++)
    {
        for (int y = 0; y < bmp.Height; y++)
        {
            if (GetRgbDelta(bmp.GetPixel(x, y)) <= highestRgbDelta) continue;

            highestRgbDelta = GetRgbDelta(bmp.GetPixel(x, y));
            keyColor = bmp.GetPixel(x, y);
        }
    }

    return keyColor;
}

/// <summary>
/// Utility method that encapsulates the RGB Delta calculation:
/// delta = abs(R-G) + abs(G-B) + abs(B-R) 
/// So, between the color RGB(50,100,50) and RGB(128,128,128)
/// The first would be the higher delta with a value of 100 as compared
/// to the secong color which, being grayscale, would have a delta of 0
/// </summary>
/// <param name="color">The color for which to calculate the delta</param>
/// <returns>An integer in the range 0 to 510 indicating the difference
/// in the RGB values that comprise the color</returns>
private static int GetRgbDelta(Color color)
{
    return
        Math.Abs(color.R - color.G) +
        Math.Abs(color.G - color.B) +
        Math.Abs(color.B - color.R);
}
于 2009-12-09T22:36:43.187 回答
1

更快的版本。以 8 的阈值进行测试。适合我的

采用:

bool grayScale;
Bitmap bmp = new Bitmap(strPath + "\\temp.png");
grayScale = TestGrayScale(bmp, 8);
if (grayScale)
   MessageBox.Show("Grayscale image");


/// <summary>Test a image is in grayscale</summary>
/// <param name="bmp">The bmp to test</param>
/// <param name="threshold">The threshold for maximun color difference</param>
/// <returns>True if is grayscale. False if is color image</returns>
public bool TestGrayScale(Bitmap bmp, int threshold)
{
    Color pixelColor = Color.Empty;
    int rgbDelta;

    for (int x = 0; x < bmp.Width; x++)
    {
        for (int y = 0; y < bmp.Height; y++)
        {
            pixelColor = bmp.GetPixel(x, y);
            rgbDelta = Math.Abs(pixelColor.R - pixelColor.G) + Math.Abs(pixelColor.G - pixelColor.B) + Math.Abs(pixelColor.B - pixelColor.R);
            if (rgbDelta > threshold) return false;
        }
    }
    return true;
}

你有更快的吗?

于 2014-11-18T20:45:59.643 回答
0

由于 JPEG 支持元数据,您应该首先检查您的扫描仪软件是否在保存的图像上放置了一些特殊数据,以及您是否可以依赖这些信息。

于 2009-12-09T22:47:35.210 回答
0

我在 python 部分发布的答案可能会有所帮助。您在网络上发现的人们认为灰度的图像通常没有相同的 R、G、B 值。您需要对方差进行一些计算和某种采样过程,这样您就不必检查一百万个像素。Paul 给出的解决方案是基于最大差异,因此来自扫描仪的单个红色像素伪影可以将灰度图像变成非灰度图像。我发布的解决方案在 13,000 张图像上获得了 99.1% 的准确率和 92.5% 的召回率。

于 2014-04-13T03:26:17.483 回答
0

我认为这种方法应该需要最少的代码,它已经在 jpeg 上进行了测试。下面的 bImage 是一个字节数组。

 MemoryStream ms = new MemoryStream(bImage);
 System.Drawing.Image returnImage = System.Drawing.Image.FromStream(ms);
 if (returnImage.Palette.Flags == 2)
 {
      System.Diagnostics.Debug.WriteLine("Image is greyscale");
 }
于 2015-07-01T17:16:24.310 回答