Domanda

Io la scansione di documenti in immagini JPG. Lo scanner deve eseguire la scansione di tutte le pagine come il colore o tutte le pagine come in bianco e nero. Dal momento che molti dei mie pagine sono a colori, devo scansione di tutte le pagine come il colore. Dopo la scansione, vorrei esaminare le immagini con .Net e provare a rilevare quale le immagini sono in bianco e nero in modo che posso convertire quelle immagini in scala di grigi e risparmiare sullo storage.

Qualcuno sa come rilevare un'immagine in scala di grigi con .Net?

Per favore fatemi sapere.

È stato utile?

Soluzione

Un semplice algoritmo di prova per colore: brucia l'immagine pixel per pixel in una annidato ciclo for (larghezza e altezza) e test per verificare se i valori RGB del pixel sono uguali. Se non lo sono, allora l'immagine ha informazioni di colore. Se fate tutto il percorso attraverso tutti i pixel senza incontrare questa condizione, allora si dispone di un'immagine in scala di grigi.

Revisione con un algoritmo più complesso:

Nel primo giro di questo post ho proposto un semplice algoritmo che presuppone che i pixel sono scala di grigi se RGB di ciascun pixel sono valori sono uguali. Così RGBs di 0,0,0 o 128.128.128 o 230.230.230 sarebbero tutti test come grigio, mentre 123,90,78 no. Semplice.

Ecco un frammento di codice che testa per una varianza dal grigio. I due metodi sono una piccola sottosezione di un processo più complesso, ma dovrebbe fornire il codice grezzo sufficiente per aiutare con la domanda iniziale.

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

Altri suggerimenti

Se non riesci a trovare una libreria per questo, si potrebbe provare afferrare un gran numero (o tutti) dei pixel per l'immagine e vedere se le loro R, G, B e valori sono all'interno di una certa soglia (che si potrebbe impostare empiricamente, oppure avere come impostazione) l'uno dall'altro. Se lo sono, l'immagine è in scala di grigi.

avrei sicuramente fare la soglia per un test un po 'più grande di 0, anche se ... in modo da non provare r = g, per esempio, ma (abs (r-g) a meno che le vostre tecniche di immagine e di scansione originali danno appunto in scala di grigi.

Un veloce di versione. Prova con una soglia di ben 8. Il lavoro per il mio

Usa:

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

Hai un uno più veloce?

Come JPEG hanno il supporto per i metadati, si deve prima controllare se il vostro posto software dello scanner alcuni dati particolari su immagini salvate e se si può fare affidamento su tali informazioni.

La risposta ho postato nella sezione pitone potrebbe essere utile. Immagini che si trovano per esempio sul web che un essere umano considererebbe scala di grigi spesso non hanno valori identici R, G, B. Avete bisogno di qualche calcolo della varianza e una sorta di processo di campionamento in modo da non controlla un milione di pixel. La soluzione Paul ha dato si basa sulla differenza massima in modo da un singolo manufatto pixel rosso da uno scanner potrebbe trasformare un'immagine in scala di grigi in non-scala di grigi. La soluzione che ho postato ottenuto il 99,1% e il 92,5% di precisione richiamo sulle 13.000 immagini.

Credo che questo approccio dovrebbe richiedere il codice almeno, è stato testato su file JPEG. bimage sotto è un array di byte.

 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");
 }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top