Pregunta

Estoy escanear documentos a imágenes JPG. El escáner debe escanear todas las páginas como el color o todas las páginas como en blanco y negro. Dado que muchos de mis páginas son de color, hay que escanear todas las páginas como el color. Después de la exploración es completa, me gustaría examinar las imágenes con .Net y tratar de detectar lo que las imágenes son en blanco y negro para que pueda convertir esas imágenes a escala de grises y ahorrar en almacenamiento.

¿Alguien sabe cómo detectar una imagen en escala de grises con .Net?

Por favor, hágamelo saber.

¿Fue útil?

Solución

Un simple algoritmo para poner a prueba para el color: Camina el píxel de la imagen por pixel en una anidada para el bucle (anchura y altura) y la prueba para ver si los valores RGB del píxel son iguales. Si no es así, entonces la imagen tiene información de color. Si usted lo hace todo el camino a través de todos los píxeles sin encontrarse con esta condición, entonces usted tiene una imagen de escala de grises.

Revisión con un algoritmo más complejo:

En el primer rev de este post me propuso un algoritmo simple que asume que los píxeles son escala de grises si RGB de cada píxel son valores son iguales. Así RGBs de 0,0,0 o 128128128 o 230230230 haría toda la prueba tan gris, mientras que 123,90,78 no lo haría. Simple.

He aquí un fragmento de código que las pruebas de una variación de color gris. Los dos métodos son una pequeña subsección de un proceso más complejo, pero debe proveer suficiente código crudo para ayudar con la pregunta original.

/// <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);
}

Otros consejos

Si no puede encontrar una biblioteca para esto, usted podría intentar agarrar un gran número (o todos) de los píxeles de una imagen y ver si sus R, G y B son los valores dentro de un cierto umbral (que se podría establecer empíricamente, o tienen como escenario) el uno del otro. Si lo están, la imagen es en escala de grises.

sin duda haría el umbral para una prueba un poco más grande que 0, aunque ... así que no pondría a prueba r = g, por ejemplo, pero (abs (r-g) precisamente en escala de grises.

Una versión más rápida. Prueba con un umbral de bienestar 8. Trabajar para mi

Uso:

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;
}

¿Tiene un ser más rápido?

Como JPEG tiene soporte para metadatos, primero debe comprobar si su lugar software del escáner algunos datos especiales sobre las imágenes guardadas y si se puede confiar en esa información.

he publicado en la sección pitón podría ser útil. Las imágenes que encuentran, por ejemplo, en la web que un ser humano consideraría escala de grises a menudo no tienen los valores R, G, B idénticas. Usted necesitará un poco de cálculo de la varianza y algún tipo de proceso de muestreo por lo que no tiene que comprobar un millón de píxeles. La solución Pablo dio se basa en la diferencia máximo para un solo artefacto píxel rojo de un escáner podría convertir una imagen en escala de grises en la no-escala de grises. La solución que he publicado consiguió% de precisión 99,1 y 92,5% revocatorio de 13.000 imágenes.

Creo que este enfoque debería requerir el código por lo menos, se ha probado en archivos JPEG. bimage a continuación es una matriz de bytes.

 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");
 }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top