Bestimmen ob Bereich im Bild eher Schwarz oder Weiss ist?

sirbender

Top Contributor
Hi,

ich habe ein schwarz-weiss BufferedImage. Wie kann ich bestimmen ob der Bereich x,y,w,h (100,150,10,10) eher weiss oder schwarz ist? Pixel zaehlen? Wie komme ich an die Farben ran?

Geht das auch mit farbigen Bildern? Kann ich irgendwie entscheiden ob das Quadrat im Bild eher 'hell' oder 'dunkel' ist?

Danke,
sb
 
Ich habe soetwas ähnliches wie du willst mal geschrieben.

Wenn ichs richtig im kopf habe, brauchst du nur das Graphics(2D) objekt aus dem Bild und über das [c]getRaster()[/c] kannst du die Bildinformationen in ein Array laden (oder dir den RGB-Wert zurückgeben lassen. Ich habe ein array mit der größe 4 genommen: rot, grün, blau, alpha).

Die Helligkeit ist ganz einfach. Du nimmst den höchsten Wert von den ersten 3 (alpha interessiert nicht) und daraus bekommst du die helligkeit. (Ein Graustufenbild kannst du dann einfach erstellen, indem du den rot,grün und blau wert auf den höchsten Wert setzt, der vorkommt. Beispiel: r:0 g:120: b:150. Dann ist der Blauanteil am höchsten und du setzt dann alles auf 150 (alpha habe ich immer auf 255 gesetzt))

Daraus ein komplettes schwarz ODER weis bild zu machen ist eigentl. auch nicht schwer. Du nimmst dein Graustufenbild und setzt eine Grenze: alles unter 100 z.B. ist 0 alles darüber ist 255. Schon hast du ein schwarz/weis bild.

Damit habe ich überraschend gute Ergebnisse erziehlt.

MFG

Tomate_Salat
 
Zuletzt bearbeitet von einem Moderator:
Simple antwort: ja. mit getRaster() bekommst du die Bildinformationen und kannst diese verändern (die Pixel halt). Wie du jz blurring damit realisierst kann ich dir nicht sagen, weil ich es noch nie versucht habe (vllt gibts dafür aber auch bereits eine Methode? Ka).

Filter Effekte diese Seite habe ich mal überflogen, vllt hilft diese. Sind zwar glaub c++-Beispiele aber vllhilft es trotzdem

MFG

Tomate_Salat
 
Die Helligkeit ist ganz einfach. Du nimmst den höchsten Wert von den ersten 3 (alpha interessiert nicht) und daraus bekommst du die helligkeit. (Ein Graustufenbild kannst du dann einfach erstellen, indem du den rot,grün und blau wert auf den höchsten Wert setzt, der vorkommt. Beispiel: r:0 g:120: b:150. Dann ist der Blauanteil am höchsten und du setzt dann alles auf 150 (alpha habe ich immer auf 255 gesetzt))

Das ist so leider nicht richtig. Ein Pixel (255,0,0) wäre somit als Grauwert heller als (254,254,254), was aber nicht der Fall ist. Die korrekte Umrechnung findet sich hier: YUV-Farbmodell ? Wikipedia.
Der Grauwert Y = 0,299 * R + 0,587 * G + 0,114 * B. Der Grund für diese unterschiedlichen Faktoren liegt darin, dass unser Auge für die Farben unterschiedlich empfindlich ist.

Ralf
 
Danke! Kann ich mit der gleichen Vorgehensweise ueber getRaster() Blurring erreichen?

Ich habe in einer meiner Anwendungen folgendermaßen ein Blurring realisiert (eine gute Anleitung findet sich in dem Buch "Filthy Rich Clients"):

[Java]
int filterwidth = ... // Je größer der Wert, desto stärker der Filter.
BufferedImage image = ... // Dein Bild, das Du filtern willst.
// Warum der Filter in zwei einzelne Filter unterteilt wird, lies bitte in dem angegebenen Buch nach. Die Wirkung ist die gleiche wie in einem Durchgang, es geht aber schneller.
image = getGaussianBlurFilter(filterwidth, true).filter(image, null);
image = getGaussianBlurFilter(filterwidth, false).filter(image, null);

public static ConvolveOp getGaussianBlurFilter(int radius, boolean horizontal) {
if (radius < 1) {
throw new IllegalArgumentException("Radius must be >= 1");
}

int size = radius * 2 + 1;
float[] data = new float[size];
float sigma = radius / 3.0f;
float twoSigmaSquare = 2.0f * sigma * sigma;
float sigmaRoot = (float)
Math.sqrt(twoSigmaSquare * Math.PI);
float total = 0.0f;
for (int i = -radius; i <= radius; i++) {
float distance = i * i;
int index = i + radius;
data[index] = (float) Math.exp(-distance / twoSigmaSquare) / sigmaRoot;
total += data[index];
}
for (int i = 0; i < data.length; i++) {
data /= total;
}
Kernel kernel = null;
if (horizontal) {
kernel = new Kernel(size, 1, data);
} else {
kernel = new Kernel(1, size, data);
}
return new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
}
[/Java]

Ralf
 
Das ist so leider nicht richtig. Ein Pixel (255,0,0) wäre somit als Grauwert heller als (254,254,254), was aber nicht der Fall ist. Die korrekte Umrechnung findet sich hier: YUV-Farbmodell ? Wikipedia.
Der Grauwert Y = 0,299 * R + 0,587 * G + 0,114 * B. Der Grund für diese unterschiedlichen Faktoren liegt darin, dass unser Auge für die Farben unterschiedlich empfindlich ist.

Ralf

Für das Umrechnen kann man Color.RGBtoHSB nehmen.
 
Zuletzt bearbeitet:
Das ist so leider nicht richtig. Ein Pixel (255,0,0) wäre somit als Grauwert heller als (254,254,254), was aber nicht der Fall ist. Die korrekte Umrechnung findet sich hier: YUV-Farbmodell ? Wikipedia.
Der Grauwert Y = 0,299 * R + 0,587 * G + 0,114 * B. Der Grund für diese unterschiedlichen Faktoren liegt darin, dass unser Auge für die Farben unterschiedlich empfindlich ist.

Ralf

Für meine Zwecke hat das bis jz super gereicht^^. Werde es mir das aber mal genauer anschauen. Dein Beispiel kann ich nicht nachvollziehen, vllt hab ich aber gerade auch eine falsche Vorstellung von 255,0,0 und 254,254,254.

Wobei ich nicht glaube, dass das bei meinem vorhaben große auswirkungen hat. Da ich in meinem Projekt das ganze zur einfachen Konturerkennung nutze und diese eh im (eigen entwickelten) Editor nachgearbeitet werden müssen

MFG

Tomate_Salat
 
Für meine Zwecke hat das bis jz super gereicht^^. Werde es mir das aber mal genauer anschauen. Dein Beispiel kann ich nicht nachvollziehen, vllt hab ich aber gerade auch eine falsche Vorstellung von 255,0,0 und 254,254,254.

Wobei ich nicht glaube, dass das bei meinem vorhaben große auswirkungen hat. Da ich in meinem Projekt das ganze zur einfachen Konturerkennung nutze und diese eh im (eigen entwickelten) Editor nachgearbeitet werden müssen

Ein Pixel mit der Farbe (255,0,0) ist ein sattes Rot, (254,254,254) hingegen ist fast weiß (ohne Vergleichsmöglichkeit würde man den Unterschied zu weiß nicht merken). Optisch würde jeder sagen, dass der rote Pixel dunkler ist als der fast weiße. Aber nach Deiner Methode würde der erste als heller detektiert werden.

Zum Tragen kommt der Unterschied in der Umrechnung dann, wenn die Pixel des Bildes sehr große Variationen in den Farbkanälen haben, d. h. bei einem Teil der Pixel ist der eine, bei einem anderen Teil ein anderer Farbkanal dominant.

Ralf
 
Konturerkennung? Du meinst in Vektoren umwandeln also tracen? Ist das Programm erhaeltlich?

Für meine Zwecke hat das bis jz super gereicht^^. Werde es mir das aber mal genauer anschauen. Dein Beispiel kann ich nicht nachvollziehen, vllt hab ich aber gerade auch eine falsche Vorstellung von 255,0,0 und 254,254,254.

Wobei ich nicht glaube, dass das bei meinem vorhaben große auswirkungen hat. Da ich in meinem Projekt das ganze zur einfachen Konturerkennung nutze und diese eh im (eigen entwickelten) Editor nachgearbeitet werden müssen

MFG

Tomate_Salat
 
Ich wuerde gerne folgenden Code fuer mein Blur verwenden:

001 float ninth = 1.0f / 9.0f;
002 float[] blurKernel = {
003 ninth, ninth, ninth,
004 ninth, ninth, ninth,
005 ninth, ninth, ninth
006 };
007 BufferedImageOp blur = new ConvolveOp(new Kernel(3, 3, blurKernel));

Das Problem ist nur...wie verstaerke ich den Blur-Effekt? Muss ich das Blur mehrmals anwenden bzw. den Kernel vergroessern?
 
Das Problem ist nur...wie verstaerke ich den Blur-Effekt? Muss ich das Blur mehrmals anwenden bzw. den Kernel vergroessern?

Du vergrößerst den Kernel. Dabei aber beachten, dass die Summe der Einträge 1 ergibt.
Es gibt allerdings den Nachteil, dass der Rand, der nicht mit bearbeitet wird, größer wird. Also eventuell das zu filternde Bild in ein größeres Bild einbetten, filtern und dann wieder ausschneiden.
Du kannst natürlich auch den Blur mehrfach anwenden. Schau einfach, was für Dich das Beste Ergebnis gibt.

Dein Kernel ist übrigens separierbar, d. h. Du kannst ihn in zwei 1x3-Kernel aufteilen. Siehe dazu mein Beispiel. Dies spart Rechenoperationen und ist sinnvoll, wenn die Filterung schnell erfolgen soll.

Ralf
 
Konturerkennung? Du meinst in Vektoren umwandeln also tracen? Ist das Programm erhaeltlich?

Nein. In ein Polygon um genau zu sein und der Prototyp (Editor) ist noch in Entwicklung. Er wird als Modeleditor später verfügbar sein. Ich will irgendwann mal mit Spieleentwicklung anfangen und dafür wird der Editor dann später gebraucht werden. Dieser soll auch für andere Spiele die ich mal vorhabe zu entwickeln (zuminest habe ichs mal vor 😀) genutzt werden.

MFG

Tomate_Salat
 
Ich wuerde gerne folgenden Code fuer mein Blur verwenden:

001 float ninth = 1.0f / 9.0f;
002 float[] blurKernel = {
003 ninth, ninth, ninth,
004 ninth, ninth, ninth,
005 ninth, ninth, ninth
006 };
007 BufferedImageOp blur = new ConvolveOp(new Kernel(3, 3, blurKernel));

Das Problem ist nur...wie verstaerke ich den Blur-Effekt? Muss ich das Blur mehrmals anwenden bzw. den Kernel vergroessern?

Den Kernel vergrößern. Für ein gutes Ergebnis mit einem größeren Kernel solltest du allerdings in der Mitte größere und am Rand kleinere Werte verwenden (Summe sollte 1 sein, sonst verändert sich die durchschnittliche Helligkeit). Üblicherweise verwendet man dafür ein Gauß-Verteilung. Schau mal hier:
Java Programming [Archive] - filters mean 5x5 and gaussian 5x5
 

Zurück
Oben