Question

Je suis numérisation de documents aux images JPG. Le scanner doit scanner toutes les pages que la couleur ou toutes les pages en noir et blanc. Comme bon nombre de mes pages sont en couleur, je dois scanner toutes les pages que la couleur. Après la numérisation est terminée, je voudrais examiner les images avec .Net et essayer de détecter ce que les images sont en noir et blanc pour que je puisse convertir les images en niveaux de gris et d'économiser sur le stockage.

Quelqu'un sait-il comment détecter une image en niveaux de gris avec .Net?

S'il vous plaît laissez-moi savoir.

Était-ce utile?

La solution

Un algorithme simple pour tester la couleur: Walk the image pixel par pixel dans une boucle imbriquée pour (largeur et hauteur) et un test pour voir si les valeurs RVB du pixel sont égaux. Si elles ne sont pas alors l'image a l'information couleur. Si vous faites tout le chemin à travers tous les pixels sans rencontrer cette condition, alors vous avez une image en échelle de gris.

Révision avec un algorithme plus complexe:

Dans le premier tour de ce poste i a proposé un algorithme simple qui suppose que les pixels sont échelle des gris si le RGB de chaque pixel sont des valeurs sont égales. Ainsi RGBs de 0,0,0 ou 128128128 ou 230230230 serait tout test gris tout 123,90,78 ne serait pas. Simple.

Voici un extrait de code qui teste pour une variance de gris. Les deux méthodes sont un petit paragraphe d'un processus plus complexe, mais doit fournir suffisamment de code brut pour aider à la question initiale.

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

Autres conseils

Si vous ne trouvez pas une bibliothèque pour cela, vous pouvez essayer de saisir un grand nombre (ou la totalité) des pixels pour une image et voir si leurs r, g, et les valeurs b sont dans un certain seuil (que vous pourrait fixer de manière empirique, ou avoir comme paramètre) les uns des autres. Si elles sont, l'image est en niveaux de gris.

Je certainement le seuil requis pour un test un peu plus grand que 0, mais ... je ne voudrais pas tester r = g, par exemple, mais (abs (r-g) avec précision Niveaux de gris.

Une version plus rapide. Test avec un seuil de 8 puits de travail pour mon

Utilisation:

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

Avez-vous une plus rapide?

JPEG ont un soutien pour les métadonnées, vous devez d'abord vérifier si votre lieu de logiciel du scanner des données spéciales sur les images enregistrées et si vous pouvez compter sur cette information.

La réponse J'ai posté dans la section python pourrait être utile. Les images que vous trouvez par exemple sur le web que l'homme considérerait souvent en niveaux de gris n'ont pas des valeurs identiques R, G, B. Vous avez besoin de calcul de la variance et une sorte de processus d'échantillonnage de sorte que vous ne devez pas vérifier un million de pixels. La solution Paul a donné est basé sur la différence maximum si un seul artefact de pixel rouge à partir d'un scanner pourrait transformer une image en niveaux de gris en niveaux de gris non. La solution que j'ai posté obtenu 99,1% de précision et de 92,5% sur le rappel de 13.000 images.

Je pense que cette approche devrait exiger le moindre code, il a été testé sur jpegs. bimage ci-dessous est un tableau d'octets.

 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");
 }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top