10
votes

Détecter des images en niveaux de gris avec .NET

Je numérise des documents aux images JPG. Le scanner doit numériser toutes les pages sous forme de couleur ou de toutes les pages en noir et blanc. Étant donné que beaucoup de mes pages sont de couleur, je dois numériser toutes les pages comme couleur. Une fois la numérisation terminée, je voudrais examiner les images avec .net et essayer de détecter les images noires et blanches afin que je puisse convertir ces images en niveaux de gris et é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.


5 commentaires

Vérification du type d'image ne va pas le couper car il sera défini pour 24 ou 32 bits (puisque vous numérisez en couleur). Vous devrez probablement vérifier chaque pixel; Si r == g == B dans tous les pixels, c'est une image en niveaux de gris, sinon c'est probablement la couleur.


Une pensée: même si le scanner en théorie fournit r == g == b, est-il possible que lors de la compression JPEG, il peut y avoir des pixels où ce n'est presque pas vrai? Considérez, JPEG est un algorithme de compression à perte. Peut-être que JPEG prend des libertés avec des couleurs de pixels à proximité. Mais j'avoue, je ne suis pas un expert JPEG. Mais je voudrais savoir comment cela a fonctionné avant de compter sur R == g == B.


Oui, je détesterais compter exactement sur R == g == b parce que même si JPG ne fait pas de rabattre (et je parie que cela fait), votre scanner et votre original devraient être parfaits aussi, ce qui me frappe comme improbable dans de nombreux cas.


Assez juste. N'avait pas considéré que des variations de pixels (qui sont bien entendu survenir lors de la numérisation). Problème intéressant.


@Dave: J'aurais dû le faire plus tôt mais ... ce matin a collé dans ma réponse, un extrait de code qui retournera réellement le delta de pixel le plus élevé de pixel RVB d'une image. Comment vous interprétez le delta est à vous de décider. Vous pouvez tester 0 (échelle gris vraie et complète) ou légèrement supérieure à zéro pour permettre des informations de couleur.


6 Réponses :


6
votes

Un simple algorithme à tester pour la couleur: Marchez l'image Pixel par pixel dans une boucle imbriquée pour une boucle (largeur et hauteur) et testez pour voir si les valeurs RVB du pixel sont égales. S'ils ne sont pas alors l'image a des informations de couleur. Si vous faites tout le chemin à travers tous les pixels sans rencontrer cette condition, vous avez une image à l'échelle grise.

révision avec un algorithme plus complexe:

dans le Premier Rev de ce message J'ai proposé un algorithme simple qui suppose que les pixels sont à l'échelle de gris si les valeurs RVB de chaque pixel sont égales. Donc, les RGBS de 0,0,0 ou 128 128 128 128 128 ou 230 230 230 seront tous testés comme gris tandis que 123,90,78 ne le feraient pas. Simple.

Voici un extrait de code qui teste une variance de gris. Les deux méthodes constituent une petite sous-section de processus plus complexe, mais devraient fournir suffisamment de code brut pour aider à la question initiale. xxx


8 commentaires

Certains scanners introduiront une légère couleur dans des images autrement noires et blanches. Vous devez autoriser un petit seuil pour que les couleurs ne soient pas assez égales.


Une image avec des valeurs RVB de 128 128 128 de toutes les pixels ne serait-elle pas considérée comme une image rectangulaire grise (une couleur)?


@crischu: Eh bien, je pense que c'était juste un exemple de montrer comment toutes les valeurs seraient égales.


Je ne pense pas que tu puisses. Numérisation de couleur et l'utilisation de la compression pertinente produira très sûrement des artefacts en termes de couleurs. Même les documents B & W ne seront pas parfaitement en niveaux de gris.


Juste pour permettre la variation attendue de la numérisation, je suggérerais d'améliorer cela un peu. Faire quelque chose comme: Colordiff = (rouge - bleu) ^ 2 + (rouge - vert) ^ 2. Si Colordiff


@Beska je sais que c'était juste un exemple. Toujours ma déclaration a toujours sa valeur car elle n'a pas d'importance si l'exemple de valeurs est de 128, 3 ou 42, la photo qui remplit ce chèque est une image d'une seule couleur et non une image en niveaux de gris.


@Kigurai: C'est donc ce clair ou non le seul moyen? Il ne peut pas être tous les deux. Je visitais d'abord la simplicité de vanille. "Algorithme simple à tester la couleur" Ce matin, j'ai suivi avec un exemple plus complexe qui permettra un gris légèrement "off".


À la deuxième pensée, j'ai peut-être mangé des choses dans ma tête et j'ai fait un jugement un peu trop rapide. Supprimer mon commentaire précédent et le bowvote.



14
votes

Si vous ne trouvez pas une bibliothèque pour cela, vous pouvez essayer de saisir un grand nombre (ou tous) des pixels pour une image et voir si leurs valeurs R, G et B sont dans un certain seuil (que vous avez pourrait définir de manière empirique ou avoir un réglage) les uns des autres. S'ils le sont, l'image est en niveaux de gris.

Je ferais certainement le seuil pour un test un peu plus grand que 0, bien que ... donc je ne testerais pas r = g, par exemple, mais (ABS (R-G) précision grisalcale.


3 commentaires

Je n'utiliserais pas une bibliothèque pour faire quelque chose d'aussi simple que de détecter si r = g = b


Ou vérifier un delta contre un seuil, ce qui serait la meilleure approche.


@Ed: N'est-ce pas à peu près ce que j'ai dit?



0
votes

Au fur et à mesure que JPEG dispose de la prise en charge des métadonnées, vous devez d'abord vérifier si votre logiciel de scanner placez quelques données spéciales sur des images enregistrées et si vous pouvez compter sur ces informations.


2 commentaires

Cela n'a pas de sens pour moi. Le logiciel Scanner, s'il écrit des métadonnées dans le fichier, vous écrirez que l'image est une image couleur si elle est numérisée sous forme de couleur (qu'elle est), même si l'image ne contient que le contenu en niveaux de gris.


C'était une idée et j'ai souligné pour valider ces données hypothétiques, beska. Quoi qu'il en soit, Ty pour votre commentaire.



0
votes

Le Réponse I Publié dans la section Python pourrait être utile. Images que vous trouvez par exemple Sur le Web qu'un humain considérerait que la grisalyse ne dispose souvent pas de valeurs de R, G, B identiques. Vous avez besoin d'un certain calcul de la variance et d'une sorte de processus d'échantillonnage, vous n'avez donc pas à vérifier un million de pixels. La solution Paul a donné est basée sur la différence Max afin qu'un seul artefact de pixels rouges à partir d'un scanner puisse transformer une image en niveaux de gris en non grisalcale. La solution que j'ai postée a reçu 99,1% de précision et 92,5% de rappel sur 13 000 images.


0 commentaires

1
votes

un plus rapide versión. Testez avec un seuil de 8. Travaillez bien pour mon

Utilisation: P>

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


1 commentaires

Essayez-vous de répondre ou de poser une question? S'il vous plaît soyez clair!



0
votes

Je pense que cette approche devrait exiger le moindre code, il a été testé sur les JPEG. 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");
 }


0 commentaires