2016-03-22 5 views
4

Ich arbeite derzeit an einem Anwendungsfall, bei dem ich feststellen muss, ob das hochgeladene Bild Graustufen oder RGB ist. Ich habe einige Möglichkeiten gefunden, dies zu identifizieren, aber ich bin nicht sicher, ob sie zuverlässig sind und gemeinsam verwendet werden können, um zu bestätigen, ob das Bild Graustufen ist oder nicht.Zuverlässiger Weg, um zu überprüfen, ob das Bild Graustufen ist

Teil 1: Lesen Sie Image und erhalten Sie NumberDataElements mit Raster.

Ich beobachtete Wert von elem ist in einigen Fällen "1", aber nicht in allen.

Teil 2: Überprüfen Sie den RGB-Wert jedes Pixels. Wenn der R-, G-, B-Wert der gleiche Pixel ist.

BufferedImage image = ImageIO.read(file); 
     Raster ras = image.getRaster(); 

     //Number of Color elements 
     int elem = ras.getNumDataElements(); 

     int width = image.getWidth(); 
     int height = image.getHeight(); 

     int pixel,red, green, blue; 

     for (int i = 0; i < width; i++) 
      for (int j = 0; j < height; j++) { 
       //scan through each pixel 
       pixel = image.getRGB(i, j); 
       red = (pixel >> 16) & 0xff; 
       green = (pixel >> 8) & 0xff; 
       blue = (pixel) & 0xff; 

       //check if R=G=B 
       if (red != green || green != blue) { 
        flag = true; 
        break; 
       } 


      } 

Hier prüfen i R, G, B sind Werte für alle Dienste gegebenen Pixel und dieses Verhalten ist für alle Pixel konsistent.

Ich verwende diese 2 Ansätze, aber nicht sicher, wie genau sie sind. Mit freundlichen Grüßen ..

+2

'rot! = Grün || grün! = blau || rot! = blau' Es sollten nur zwei Vergleiche notwendig sein. Außerdem rufen Sie zweimal "Pause", die zweite ist redundant. – leonbloy

+0

Obwohl "grau" in RGB R = G = B bedeutet, kann es einige Variationen geben, z. G. Wenn ein Bild ein eingebettetes Farbprofil hat oder von jpeg wiederhergestellt wird. Ich glaube, der zuverlässigere, aber langsamere Weg ist es, Pixel in HSV zu konvertieren und zu überprüfen, ob S (Sättigung) nahe 0 ist. –

+0

@SashaSalauyou wie ich es verstehe, auch wenn das Bild jpeg war und eine Farbentabelle verwendet, wird dieser Code immer noch arbeiten, da das Bild entschlüsselt wurde und getRGB unabhängig vom Quellformat ist. – Elemental

Antwort

1

Below Ansatz ist für mich gearbeitet. Danke Jungs um Hilfe.

BufferedImage image = ImageIO.read(file); 
     Raster ras = image.getRaster(); 

     //Number of Color elements 
     int elem = ras.getNumDataElements(); 

     int width = image.getWidth(); 
     int height = image.getHeight(); 

     int pixel,red, green, blue; 

     for (int i = 0; i < width; i++) 
      for (int j = 0; j < height; j++) { 
       //scan through each pixel 
       pixel = image.getRGB(i, j); 
       red = (pixel >> 16) & 0xff; 
       green = (pixel >> 8) & 0xff; 
       blue = (pixel) & 0xff; 

       //check if R=G=B 
       if (red != green || green != blue) { 
        flag = true; 
        break; 
       } 


      } 
0

Ich denke, Ihre zweite Option ist eine zuverlässige und korrekte Methode, um ein Bild zu beweisen, ist Graustufen. Ihr Code hat einige Probleme: * Sie brechen nicht aus der äußeren Schleife auf die von Ihnen beabsichtigte Weise (schauen Sie sorgfältig auf die zweite Pause - ich denke, es sollte in der äußeren Schleife sein, aber NICHT die innere Schleife). * wie Leonbloy in seinem Kommentar erklärt Ihr Vergleich könnte einfacher sein

Aber wenn Sie diese kleinen Probleme beheben, sollte es zuverlässig funktionieren.

0

Verschieben Sie Ihre if (flag) { break; } Zeile außerhalb der inneren for-Schleife.

Und Sie müssen nur überprüfen, dass (red != green || green != blue). Das Brechen einer dieser beiden Gleichheiten stellt sicher, dass das dritte MUSS gebrochen werden muss, so dass Sie nur zwei Überprüfungen benötigen.

Ich würde auch nur eine isGrayscale-Variable von Boolean auf True setzen und dann auf false setzen, wenn die Gleichheitslogik bricht, anstatt ein Flag auf True zu setzen. Es sollte angenommen werden, dass es Graustufen ist, bis es bricht und falsch wird. Kein Problem mit dem, was Sie hier mit Flagge haben, aber das ist ein wenig sinnvoller und intuitiver.

Wenn Sie wirklich clever werden möchten, könnten Sie ein Delta der Varianz zulassen, um Bilder zu ermöglichen, die AUSREICHEND Graustufen für den Zweck sind, d.h. ihre Abweichung von der Gleichheit ist niedriger als eine gesetzte Schranke. Aber das funktioniert wie es ist :)

0

Überprüfung R = G = B wird Ihnen sagen, ob ein Bild Graustufen ist, das ist sicher. Aber ich wäre sehr vorsichtig mit diesem Ansatz. Du weißt nicht wo die Bilder herkommen. Sie könnten mit verlustreicher Komprimierung oder einem anderen seltsamen Format gespeichert werden. Ich weiß nicht, ob Formate wie JPG tatsächlich Graustufenpixel verschiebt, aber das hängt möglicherweise auch vom Komprimierungsalgorithmus ab (und somit vom Programm, das zum Speichern des Bildes verwendet wurde). Wie auch immer, ich würde vorschlagen, dass Sie Bilder selbst in Graustufen umwandeln, nur um sicher zu gehen. Zumindest für solche Bilder, die den R = G = B Test nicht bestehen.

Für Ihren Algorithmus empfehle ich Ihnen dringend, eine neue Funktion zum Überprüfen von R = G = B zu erstellen. Auf diese Weise können Sie, wenn Sie ein Pixel gefunden haben, das den Test nicht bestanden hat, sofort false zurückgeben.

public static boolean isGreyscale(BufferedImage image) 
{ 
    int pixel,red, green, blue; 
    for (int i = 0; i < width; i++) 
    { 
     for (int j = 0; j < height; j++) 
     { 
      pixel = image.getRGB(i, j); 
      red = (pixel >> 16) & 0xff; 
      green = (pixel >> 8) & 0xff; 
      blue = (pixel) & 0xff; 
      if (red != green || green != blue) return false; 
     } 
    } 
    return true; 
} 

PS: Ich habe gerade die Kompression Colorshift Sache überprüft. Ich kann Farbverschiebungen mit pohotohop und jpg Format nicht durchführen.Es ist aber möglich, ein Graustufenbild als gif so zu speichern, dass es nicht mehr graustufen ist.

0

Die Frage ist: Soll das Bild selbst Graustufen oder die Codierung sein?

Ihre zweite Lösung sagt Ihnen, ob das Bild Graustufen ist oder nicht, unabhängig von der Codierung (d. H., Es gibt True auch das Bild möglicherweise Farben haben könnte, aber nur nicht). Es ist jedoch nicht perfekt, man könnte sich eine Situation vorstellen, in der das Bild in einem anderen Farbraum als RGB Graustufen ist und ein Rundungsfehler den Test zum Scheitern bringt. Oder eine verlustreiche Codierung. Sie sollten einen Fehlerbereich hinzufügen und jedes Bild, das nahe genug ist, in die richtige Graustufe konvertieren.

Ihre erste Lösung ist ein unvollständiger Versuch herauszufinden, ob die Codierung Graustufen ist. Ein Bild mit einer Farbpalette der Größe 255 würde auch elem=1 ergeben, und ein Graustufenbild kann elem=2 haben, wenn es einen Alpha-Kanal hat.

Um zu überprüfen, ob Ihre Codierung Graustufen ist, schlage ich den folgenden Test:

int type = image.getColorModel().getColorSpace().getType(); 
boolean grayscale = (type==ColorSpace.TYPE_GRAY || type==ColorSpace.CS_GRAY); 

Um dies zu tun, werden Sie die Klassen und Farbmodell Color von java.awt.image und java.awt.color importieren müssen.

Sie können auch untersuchen, ob image.getType() den Wert BufferedImage.TYPE_BYTE_GRAY oder BufferedImage.TYPE_USHORT_GRAY hat.

0

Dies ist eine sehr einfache Art und Weise:

  1. Testen Sie den Bildtyp
  2. Testen Sie die Bild Anzahl der Kanäle
  3. Testen Sie die Pixelwerte.

Hier ist der Code

boolean isGrayScale(BufferedImage image) 
    { 
    // Test the type 
    if (image.getType() == BufferedImage.TYPE_BYTE_GRAY) return true ; 
    if (image.getType() == BufferedImage.TYPE_USHORT_GRAY) return true ; 
    // Test the number of channels/bands 
    if (image.getRaster().getNumBands() == 1) return true ; // Single channel => gray scale 

    // Multi-channels image; then you have to test the color for each pixel. 
    for (int y=0 ; y < image.getHeight() ; y++) 
    for (int x=0 ; x < image.getWidth() ; x++) 
     for (int c=1 ; c < image.getRaster().getNumBands() ; c++) 
      if (image.getRaster().getSample(x, y, c-1) != image.getRaster().getSample(x, y, c)) return false ; 

    return true ; 
    } 
Verwandte Themen