# Mustererkennung realisieren



## jWizard (16. Mrz 2011)

Hallo Zusammen,

ich werde mich bald mit dem Thema Mustererkennung beschäftigen. Ziel der ganzen Arbeit ist ein Bild einzulesen und zwischen Hell und Dunkel (Grauton) zu unterscheiden, sodass zwischen dieser Grenze eine Linie eingezeichnet wird.

Sicherlich werden schon einige von Euch die Erfahrung im Hinblick auf Mustererkennung gemacht haben und daher würde ich mich auf wertvolle Tipps sehr freuen.

Viele Grüße


----------



## theodosis (16. Mrz 2011)

Konvertiere das Bild in einem byte[] array (und wenn du das Bild als 8-bit gespechert hast, dann jede byte ist ein pixel) und dann laufe diesen array durch und mach was du willst. 

Du musst aber selber von vorher entscheiden ab welcher Wert (0-255) eine Grayton Farbe ist dunkel und ab welcher Wert ist Hell.


----------



## Blakh (16. Mrz 2011)

Bin gerade an einer Projektarbeit beteiligt, wo wir Würfelaugen erkennen müssen. Die Bearbeitung sieht so aus:


```
binaerArray = PicMod.zuBinaerbild(urArray, SCHWARZ_SCHWELLWERT);
medianArray = PicMod.medianFiltern(binaerArray, MEDIAN_COUNT);
erosionArray = PicMod.erosionFilter(medianArray, EROSION_COUNT);
dilatationArray = PicMod.dilatationFilter(erosionArray,DILATATION_COUNT);
```

Dass ist eigentlich selbsterklärend. Die Algorithmen musst du dir aber schon selbst erarbeiten. Im Prinzip haben wir das Bild als Array mit den einelnen Pixeln. Dann wird anhand eines Schwellwertes entschieden, welcher Pixel weiß oder schwarz ist. Die anderen drei Methoden dienen der Bildaufbereitung, damit wir einzelnen Augen der Würfel zur geltung kommen. Das wirst du sicher nicht brauchen.


----------



## jWizard (16. Mrz 2011)

Dankeschön für die Infos, werde ich Testen!


----------



## jWizard (16. Mrz 2011)

@theodosis
ich habe versucht deinen Tipp umzusetzen, indem ich das Image-File in einem byte[] konvertiert und im Anschluss diese Daten einem String[] übergeben habe, um diese in einem Text-File (test.txt) abzulegen. 

Was mich wundert ist, dass die Zahlen die ich erhalten habe, immer (unabhängig vom Bild) folgendermaßen beginnen und enden:
-1-40-1- ......-1-39

Mein Ziel ist die RGB-Daten (Grauton ob Schwarz oder Weiß zu entscheiden) zu erhalten. Leider weiß ich nicht was diese Daten aussagen.

Vielen Dank
Gruß


----------



## theodosis (16. Mrz 2011)

Ja, das passiert weil byte ist signed.

Das ist aber kein problem. Für den wirklichen Wert du kannst folgendes nutzen:



```
byte bGrayPixel;
int    iGrayPixel;

bGrayPixel = ....

iGrayPixel = bGrayPixel;
if ( bGrayPixel < 0 )
{
   iGrayPixel = 256 - (-1)*bGrayPixel;
}
```


Es gibt aber ein Thema: 

Wie speicherst du das Bild? Als RGB? Dann für jede Pixel du hast 3 bytes. Und die Sache wird komplizierter (ohne Grund). Oder als 8-bit grayscaled ? 

Und: Wie konvertierst du das Bild zu byte[] array? Weill wenn du immer die gleiche Reihenfolge von bytes nimmst dann du konvertierst die Datei ohne die speziellen Klassen für diese  Arbeit zu nutzen und das ist nicht richtig.


----------



## musiKk (16. Mrz 2011)

jWizard hat gesagt.:


> Ziel der ganzen Arbeit ist ein Bild einzulesen und zwischen Hell und Dunkel (Grauton) zu unterscheiden, sodass zwischen dieser Grenze eine Linie eingezeichnet wird.



Das ganze läuft unter dem Oberbegriff Bildsegmentierung. Im Speziellen suchst Du hier Kantenerkennung. Das Thema kann beliebig komplex werden. Es kommt darauf an, in welchem Kontext die Aufgabe läuft (aka wie "professionell" das aufgezogen werden soll). Vielleicht reicht schon ein entsprechender Algorithmus aus der Wikipedia. Wenn das nicht reicht, muss eben Literatur ran.

ImageJ ist evtl. auch einen Blick wert. Das bedarf natürlich auch wieder Einarbeitungszeit, nimmt aber einige Dinge ab.


----------



## muckelzwerg (16. Mrz 2011)

Der allgemeine Klassiker für solche Erkennung wäre z.B. Kombination von Sobelfilter und Hough Transformation.
Die sind beide relativ leicht zu implementieren, für den Anfänger aber oft schon eine gewisse Herausforderung.
Die Probleme verstecken sich da im Detail. Wenn Du zum Beispiel das Bild binarisierst, dann bekommst Du zu harte Kanten und musst erst wieder andere Filter (z.B. Medianfilter, Gaussfilter ...) verwenden.
Je nach dem, was man denn für konkrete Bilder hat und was man GENAU sucht, kann man die Verfahren anpassen, oder auch ganz andere Verfahren verwenden.

Du kannst ja nochmal beschreiben, worum es denn genau geht.


----------



## Dow Jones (16. Mrz 2011)

Hallo jWizard!

Da du ja auch nach Erfahrungen gefragt hattest: Ich persönlichen kann dir SUSAN für die Kantenerkennung/Bildsegmentierung/Feature Detection empfehlen. Liefert meiner Ansicht nach sehr gute Ergebnisse - und man muß nicht mal viel Mathe können um den Algorithmus zu verstehen  . Einziger Wermutstropfen - ich meine mich daran erinnern zu können das das Verfahren patentiert ist. Aber lesenswert ist es trotzdem.

Ansonsten solltest du auch mal bei Universitäten vorbeigoogeln, die Fachbereiche Informatik/Elektrotechnik/Mathematik haben manchmal Vorlesungen zum Thema Mustererkennung. Und oft kann man dort auch das Skript dazu herunterladen.

Und ja, mich würde ebenfalls interessieren was du damit vorhast (reine Neugierde...). Wirklich Mustererkennung? Bisher klang es eher nach einfacher Kantenerkennung.


----------



## jWizard (17. Mrz 2011)

..


----------



## muckelzwerg (17. Mrz 2011)

Wenn Du nicht mit Kamerabildern arbeitest oder Dir die Performanz sowieso egal ist, dann ist "getRGB()" in Ordnung.
Ansonsten 

```
int[] a = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
```


----------

