10 Stimmen

Erkennung von Graustufenbildern mit .Net

Ich scanne Dokumente in JPG-Bilder. Der Scanner muss alle Seiten in Farbe oder alle Seiten in Schwarz-Weiß scannen. Da viele meiner Seiten farbig sind, muss ich alle Seiten in Farbe scannen. Nach dem Scannen möchte ich die Bilder mit .Net untersuchen und versuchen zu erkennen, welche Bilder schwarz-weiß sind, damit ich diese Bilder in Graustufen umwandeln und Speicherplatz sparen kann.

Weiß jemand, wie man ein Graustufenbild mit .Net erkennt?

Bitte lassen Sie es mich wissen.

1 Stimmen

Die Überprüfung des Bildtyps wird nicht ausreichen, da dieser auf 24 oder 32 Bit eingestellt ist (da Sie in Farbe scannen). Wahrscheinlich müssen Sie jedes einzelne Pixel überprüfen. Wenn R == G == B in allen Pixeln ist, handelt es sich um ein Graustufenbild, andernfalls ist es wahrscheinlich ein Farbbild.

1 Stimmen

Ein Gedanke: Auch wenn der Scanner theoretisch R == G == B liefert, ist es möglich, dass es bei der JPEG-Kompression einige Pixel gibt, bei denen dies nur fast der Fall ist? Bedenken Sie, dass JPEG ein verlustbehafteter Komprimierungsalgorithmus ist. Vielleicht nimmt sich JPEG einige Freiheiten bei den Farben der nahegelegenen Pixel. Aber ich gestehe, ich bin kein JPEG-Experte. Aber ich würde wissen wollen, wie es funktioniert, bevor ich mich auf R == G == B verlasse.

0 Stimmen

Ja, ich würde mich nur ungern auf genau r==g==b verlassen, denn selbst wenn jpg keine Verfälschungen vornimmt (und ich wette, das tut es), müssten Ihr Scanner und Ihr Original ebenfalls perfekt sein, was ich in vielen Fällen für unwahrscheinlich halte.

14voto

Beska Punkte 12341

Wenn Sie keine entsprechende Bibliothek finden, können Sie versuchen, eine große Anzahl (oder alle) der Pixel eines Bildes zu erfassen und zu sehen, ob ihre r-, g- und b-Werte innerhalb eines bestimmten Schwellenwerts liegen (den Sie empirisch oder als Einstellung festlegen können). Wenn dies der Fall ist, ist das Bild ein Graustufenbild.

Ich würde auf jeden Fall den Schwellenwert für einen Test etwas größer als 0 machen, obwohl ... so würde ich nicht testen r = g, zum Beispiel, aber (abs(r-g) < e), wo e ist Ihre Schwelle. Auf diese Weise können Sie die Zahl der falsch-positiven Farben gering halten... denn ich vermute, dass Sie ansonsten eine anständige Zahl erhalten, es sei denn, Ihr Originalbild und die Scan-Techniken geben genau Graustufen.

0 Stimmen

Ich würde keine Bibliothek verwenden, um etwas so Einfaches wie die Feststellung, ob R=G=B ist oder nicht, zu tun.

0 Stimmen

Oder ein Delta gegen einen Schwellenwert prüfen, was der bessere Ansatz wäre.

0 Stimmen

@Ed: Ist das nicht ziemlich genau das, was ich gesagt habe?

6voto

Paul Sasik Punkte 76202

Ein einfacher Algorithmus zur Prüfung auf Farbe: Gehen Sie das Bild Pixel für Pixel in einer verschachtelten for-Schleife durch (Breite und Höhe) und prüfen Sie, ob die RGB-Werte der Pixel gleich sind. Wenn dies nicht der Fall ist, hat das Bild Farbinformationen. Wenn Sie alle Pixel durchlaufen, ohne auf diese Bedingung zu stoßen, dann haben Sie ein Graustufenbild.

Überarbeitung mit einem komplexeren Algorithmus:

In der ersten Version dieses Beitrags habe ich einen einfachen Algorithmus vorgeschlagen, der davon ausgeht, dass Pixel Graustufen sind, wenn die RGB-Werte der einzelnen Pixel gleich sind. So RGBs von 0,0,0 oder 128,128,128 oder 230,230,230 würden alle als grau testen, während 123,90,78 nicht. Einfach.

Hier ist ein Codeschnipsel, der auf eine Abweichung von Grau testet. Die beiden Methoden sind ein kleiner Teil eines komplexeren Prozesses, sollten aber genug Rohcode liefern, um bei der ursprünglichen Frage zu helfen.

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

0 Stimmen

Einige Scanner bringen ein wenig Farbe in ansonsten schwarz-weiße Bilder. Sie sollten eine kleine Schwelle zulassen, damit die Farben nicht ganz gleichmäßig sind.

0 Stimmen

Würde ein Bild mit RGB-Werten von 128,128,128 bei ALLEN Pixeln nicht einfach als ein (einfarbig-)graues rechteckiges Bild betrachtet werden?

0 Stimmen

@crischu: Nun, ich denke, das war nur ein Beispiel dafür, wie alle Werte gleich sein können.

1voto

Eine schnellere Version. Test mit einem Schwellenwert von 8. arbeiten gut für meine

Verwendung:

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

Haben Sie ein schnelleres Modell?

0 Stimmen

Versuchen Sie zu antworten oder eine Frage zu stellen. Bitte seien Sie deutlich!

0voto

Rubens Farias Punkte 55555

Da JPEG Metadaten unterstützt, sollten Sie zunächst prüfen, ob Ihre Scannersoftware spezielle Daten auf den gespeicherten Bildern ablegt und ob Sie sich auf diese Informationen verlassen können.

0 Stimmen

Das ergibt für mich keinen Sinn. Wenn die Scannersoftware Metadaten in die Datei schreibt, wird sie schreiben, dass das Bild ein Farbbild ist, wenn es als Farbe gescannt wird (was es ist), auch wenn das Bild nur Graustufen enthält.

0 Stimmen

Es war eine Idee, und ich wies darauf hin, um diese hypothetischen Daten zu validieren, beska. Wie auch immer, ty für Ihren Kommentar.

0voto

Noah Whitman Punkte 191

El Antwort, die ich in der Python-Sektion gepostet habe könnte hilfreich sein. Bilder, die man z. B. im Internet findet und die ein Mensch als Graustufen ansehen würde, haben oft nicht die gleichen R-, G- und B-Werte. Man braucht eine Berechnung der Varianz und eine Art Stichprobenverfahren, damit man nicht eine Million Pixel überprüfen muss. Die von Paul angegebene Lösung basiert auf der maximalen Differenz, so dass ein einziges rotes Pixel eines Scanners ein Graustufenbild in ein Nicht-Graustufenbild verwandeln kann. Die von mir gepostete Lösung erreichte bei 13.000 Bildern eine Genauigkeit von 99,1 % und eine Wiedererkennung von 92,5 %.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X