24-Bit-Farbdiagramm und 8-Bit-Graustufendiagramm
Lassen Sie uns zunächst ein 24-Bit-Farbbild vorstellen. In einem 24-Bit-Farbbild wird jedes Pixel durch drei Bytes dargestellt, die normalerweise als RGB ausgedrückt werden. Im Allgemeinen werden viele 24-Bit-Farbbilder als 32-Bit-Bilder gespeichert, und die überschüssigen Bytes pro Pixel werden als alpha Wert gespeichert und zeigen spezielle Einflussinformationen [1].
Wenn im RGB -Modell r = g = b ist, stellt die Farbe eine Graustufenfarbe dar, wobei der Wert von r = g = b als Graustufenwert bezeichnet wird. Daher erfordert jedes Pixel des Graustufenbildes nur ein Byte, um den Graustufenwert (auch als Intensitätswert und Helligkeitswert bekannt) zu speichern, und der Graustufenbereich beträgt 0-255 [2]. Dies gibt Ihnen ein Graustufenbild des Bildes.
Verschiedene Methoden der Graustufen
1. Komponentenmethode: Verwenden Sie eine der drei RGB -Komponenten als Graustufenwert der Graustufenkarte.
2. Die meiste Wertemethode: Verwenden Sie den maximalen oder minimalen Wert der drei RGB -Komponenten als Graustufenwert der Graustufenkarte.
3. mittlere Methode: Verwenden Sie den Durchschnittswert der drei RGB -Komponenten als Graustufenwert des Graustufendiagramms.
4. Gewichtungsmethode: Aufgrund der unterschiedlichen Farbempfindlichkeit der menschlichen Augen kann gewichteter Durchschnitt von RGB-Dreikomponenten ein vernünftigeres Graustufenbild erhalten. Die allgemeine Situation ist wie folgt: y = 0,30R + 0,59 g + 0,11b.
[Anmerkung] Die Gewichtungsmethode nimmt tatsächlich den Helligkeitswert eines Bildes als Berechnung des Graustufenwerts auf und verwendet das YUV -Modell. In [3] werden Sie feststellen, dass der Autor y = 0,21 * R + 0,71 * g + 0,07 * B verwendet, um den Graustufenwert zu berechnen (offensichtlich ist die Summe der drei Gewichte nicht gleich 1, was der Fehler des Autors sein kann?). Tatsächlich sollte dieser Unterschied darauf zusammenhängen, ob Gamma -Korrektur verwendet wird [1].
Eine Methode zur Implementierung von Graustufen in Java
Wenn Sie nach "Java implementiert Grayscale" suchen, sind die meisten von ihnen eine Methode (Code):
public void GrayImage () löscht IOException {Datei file = new File (System.getProperty ("user.dir")+"/test.jpg"); Bufferedimage image = imageio.read (Datei); int width = image.getWidth (); int height = image.getheight (); Bufferedimage grayimage = new bufferedImage (width, Höhe, bufferedimage.type_byte_gray); für (int i = 0; i <width; i ++) {für (int j = 0; j <Höhe; j ++) {int rgb = image.getRGB (i, j); GrayImage.SetRGB (I, J, RGB); }} Datei newfile = new Datei (System.getProperty ("user.dir")+"/method.jpg"); Imageio.Write (Grayimage, "JPG", Newfile); }Das ursprüngliche Bild von test.jpg lautet:
Das unter der obige Methode erhaltene Graustufendiagramm:
Wenn wir dieses Graustufenbild sehen, scheint es machbar zu sein. Wenn wir jedoch opencv verwenden, um Graustufen zu erreichen oder PIL (Python) zu verwenden, werden Sie feststellen, dass die Effekte stark variieren:
img = cv2.imread ('test.jpg', cv2.imread_color) Gray = cv2.cvtcolor (IMG, CV2.Color_Bgr2Gray) cv2.imwrite ('PythonMethod.jpg', Gray) Es ist deutlich zu erkennen, dass das unter opencv (dasselbe gilt für PIL) erhaltene Graustufe viel besser ist als die Methode, die nach der obigen Java -Methode erhalten wurde, und viele Details sind zu sehen. Dies zeigt, dass diese beliebte Methode im Internet schon immer ein Problem hatte, aber sie wurde ignoriert.
Wie man Graustufen in openCV erreicht
Wenn Sie Bücher oder Codes im Zusammenhang mit opencv gelesen haben, können Sie wahrscheinlich wissen, dass opencv -Graustufen die Gewichtungsmethode verwendet. Der Grund ist ungefähr, weil wir nicht wissen, warum opencv -Graustufenbilder so gut sind. Gibt es noch andere Verarbeitungsdetails, die wir ignorieren?
Unsere Vermutung zu überprüfen ist sehr einfach. Überprüfen Sie einfach die Änderungen vor und nachdem der Pixelwert ausgegraut ist. Sie können es wie folgt testen:
img = cv2.imread('test.jpg',cv2.IMREAD_COLOR)h, w = img.shape[:2]gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) for j in range(w): for i in range(h): print str(i) + " : " + str(j) + " " + str(gray[i][j])print IMG [H-1] [W-1] [0: 3]Es fällt uns schwer, so viele Pixel unten zu beurteilen, aber wir müssen nur auf den letzten Pixelpunkt achten, und wir können Hinweise finden: Der RGB -Wert des letzten Pixelpunkts im Originalbild beträgt 44, 67, 89 und der Wert nach der Graustätte 71. Es passt nur zu dem von der Gewichtsmethode berechneten Grauskaltewert. Wenn Sie die Pixelwerte des Bildes überprüfen, das zuvor in Java ausgrau gemacht wurde, werden Sie feststellen, dass nicht nur die Pixelwerte diese Formel nicht erfüllen, sondern sogar weit voneinander entfernt sind.
Zu diesem Zeitpunkt vermuten wir, dass OpenCV (einschließlich PIL) eine Graustufen -Implementierung unter Verwendung der Gewichtungsmethode ist.
Java implementiert gewichtete Methode Graustufen
Wenn diese beliebte Methode im Internet nicht funktioniert, wie sollten wir Java verwenden, um Graustufen zu erreichen? Tatsächlich hat [3] Graustufen erfolgreich (mehrere Methoden) erreicht (ausländische Freunde sind immer noch sehr leistungsfähig in der Technologie), und nur der erforderliche Code wird hier extrahiert:
private static int colortorgb (int alpha, int rot, int grün, int blau) {int newpixel = 0; Newpixel += Alpha; newpixel = newpixel << 8; Newpixel += rot; newpixel = newpixel << 8; Newpixel += grün; newpixel = newpixel << 8; Newpixel += blau; Newpixel zurückgeben; } public static void main (String [] args) löst ioException aus {bufferedImage bufferedimage = imageio.read (neue Datei (System.getProperty ("user.dir" + "/test.jpg")); bufferedImage Grayimage = new bufferedimage.getWidthtWidthtwidtht- (). (int i = 0; i <bufferedImage.getWidth (); i ++) {für (int j = 0; (0,3 * R + 0,59 * G + 0,11 * B); "/ok.jpg"); Der obige Code druckt die Pixelwerte im grauen Maßstab aus. Wenn Sie sie mit dem obigen Python -Code vergleichen, werden Sie feststellen, dass die Pixelwerte vollständig entsprechend sind. Die colorToRGB -Methode behandelt das Farbdiagramm genau 4 Bytes, von denen einer der alpha -Parameter ist (wie bereits erwähnt). Die folgende Abbildung ist das Graustufenbild dieses Code:
Für andere Methoden kann dies auch nacheinander erhalten werden.
Zusammenfassen
Der Grund für diesen Artikel besteht darin, Java zu verwenden, um mehrere Graustufenoperationen zu implementieren und OpenCV zu verwenden, um das Recht oder Unrecht der Konvertierung zu überprüfen. In den tatsächlichen Tests wurden jedoch einige Probleme gefunden (es gibt Unterschiede in den konvertierten Bildern und die Erzeugung von Graustufenbildern auf der Grundlage der Graustufenwerte nach der Konvertierung), und einige Gedanken und Überprüfungen wurden dazu vorgenommen. Es ist hier zu beachten, dass einige Artikel im Internet mehr oder weniger weiter nachdenken (und viele von ihnen werden sogar kopiert, insbesondere inländische Artikel), und für diese praktischen Themen ist praktische Implementierung und Überprüfung eine sehr wichtige Methode. Ich hoffe, der Inhalt dieses Artikels wird für alle hilfreich sein. Wenn Sie Fragen haben, überlassen Sie bitte eine Nachricht, um zu diskutieren.