Hallo an alle, Ich bin kompletter anfänger im Bereich Bilderkennung. Ich suche gerade nach Algorithmen die, die mir ein Bild nach Rechtecken durchsuchen. Und zwar habe ich ein Foto einer Matrix (siehe Anhang, die Anzahl der felder ist jedoch beliebig), In manchen Feldern kann jedoch etwas drinnen stehen. Ich möchte das Bild analysieren und den Bereich jedes Sub-Rechteck erkennen. Jeder Bereich wird dann weiter analysiert, ob und wenn ja was im Rechteck steht. Könnt ihr mir Tipps geben welche Algorthmen dahinter stehen bzw. Schlagwörter mit denen ich mich in die Materie einlesen kann? Danke im Voraus! Grüße an alle Robert
was weißt du genau über das rechteck nur, dass es 4 seiten hat und jeweils einen rechten winkel?? jenach matrix kann man ja gucken (mit bruteforce, ggbf optimiert) wo man ein rechteck hat- also ob von 0|0 bis 10|10 ein recht eck ist mit ein bisschen gehirn schmalz sollte das recht leicht machbar sein such erst nach linien und probier dann ein bisschen aus so schwer ist das gar nicht! die matrix schätze ich kennt nur 1/0
wie willst du das machen? Mit webcam und PC oder per FPGA? Such mal nach neuronalen Netzen, das ist das, was du suchst.
http://www.kreissl.info/bilderkennung.php http://de.wikipedia.org/wiki/Bilderkennung http://de.wikipedia.org/wiki/OpenCV
Hough! Das ist ein weites Gebiet mein Bruder. Beginne hier: http://www.physik.uni-osnabrueck.de/nonlinop/Hough/LineHough.html
Suchst du vielleicht nach so was? x.png ist das Ausgangsbild, y-png ist das Ergebnis. Funktioniert mit OpenCV.
Hallo, Christian L. schrieb: > wie willst du das machen? Mit webcam und PC oder per FPGA? Die Hardware ist eine Embedded Plattform mit Android als OS. Ich werde derzeit jedoch am PC unter Java entwickeln und dann nach Android Portieren. Michael Haberler schrieb: > sieh Dich mal da um: > > http://opencv.willowgarage.com/wiki/ Danke für den Tipp. Das schaut schonmal sehr gut aus. Es gibt sogar Portierungen nach Android - wobei hier nicht alle Funktionalitäten gegeben sind. Ich denke jedoch es ist machbar. Ich weiß das ist keine triviale Thematik - ich will jedoch auch an der Aufgabe lernen. Zwie Blum schrieb: > Suchst du vielleicht nach so was? x.png ist das Ausgangsbild, y-png ist > das Ergebnis. Funktioniert mit OpenCV. Das schaut schonmal super aus. Kannst du mir sagen wie du das gemacht hast? Danke schonmal für die Tipps! Robert
Im Groben: Gauss auf Bild anwenden, Radius ~ Kasterldurchmesser. Das schaut dann aus wie ein Eierkarton. Lokale Minima/Maxima suchen, das gibt die Mittelpunkte der Kasterl. Daraus das Raster erzeugen.
Robert S. schrieb: > Könnt ihr mir Tipps geben welche Algorthmen dahinter stehen bzw. > Schlagwörter mit denen ich mich in die Materie einlesen kann? Hi ... Also ich hab mal mit der Hough tranformation in Matlab linien detektiert wobei dies natürlich auch mit Rechtecken möglich ist ... ist ein sehr einfach zu realisierender Algorithmus lg Peter
Hallo, Ich habe heute ein bisschen mit OpenCV, bzw auch mit deren Samples gespielt (siehe Anhang). Das Ausgansbild ist wirklich kein ideales - der Algorithmus muss aber damit zurechtkommen. Ich hab hier einfach mal ein Suduko (kommt meinem Bild ganz nahe fotografiert). Ich finde das Ergebnis (das modifizierte Bild jetzt) ist gar nicht mal so schlecht. Wie kann ich das noch besser optimieren um alle Rechtecke zu erkenen? Hier mal mein Code den ich aus einem Sample-Programm modifiziert habe.
1 | //Convert to grayscale image
|
2 | dst = cvCreateImage( cvSize( img->width, img->height ), IPL_DEPTH_8U, 1 ); |
3 | cvCvtColor( img, dst, CV_RGB2GRAY ); |
4 | |
5 | //Normalize Brigthness
|
6 | IplImage *hist = cvCreateImage( cvSize( img->width, img->height ), IPL_DEPTH_8U, 1 ); |
7 | cvEqualizeHist(dst, hist); |
8 | |
9 | //Detect edges
|
10 | IplImage *canny = cvCreateImage( cvSize( img->width, img->height ), IPL_DEPTH_8U, 1 ); |
11 | cvCanny( hist, canny, 0, 250, 5 ); |
12 | |
13 | //only for shwing the result
|
14 | IplImage *color = cvCreateImage( cvSize( img->width, img->height ), IPL_DEPTH_8U, 3 ); |
15 | cvCvtColor( canny, color, CV_GRAY2RGB ); |
16 | |
17 | CvSeq* contours; |
18 | CvSeq* result; |
19 | double s, t; |
20 | // create empty sequence that will contain points -
|
21 | // 4 points per square (the square's vertices)
|
22 | CvSeq* squares = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage ); |
23 | |
24 | cvFindContours( canny, storage, &contours, sizeof(CvContour), |
25 | CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) ); |
26 | |
27 | // test each contour
|
28 | while( contours ) |
29 | {
|
30 | // approximate contour with accuracy proportional
|
31 | // to the contour perimeter
|
32 | result = cvApproxPoly( contours, sizeof(CvContour), storage, |
33 | CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 ); |
34 | // square contours should have 4 vertices after approximation
|
35 | // relatively large area (to filter out noisy contours)
|
36 | // and be convex.
|
37 | // Note: absolute value of an area is used because
|
38 | // area may be positive or negative - in accordance with the
|
39 | // contour orientation
|
40 | if( result->total == 4 && |
41 | fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 1000 && |
42 | cvCheckContourConvexity(result) ) |
43 | {
|
44 | s = 0; |
45 | |
46 | for(int i = 0; i < 5; i++ ) |
47 | {
|
48 | // find minimum angle between joint
|
49 | // edges (maximum of cosine)
|
50 | if( i >= 2 ) |
51 | {
|
52 | t = fabs(angle( |
53 | (CvPoint*)cvGetSeqElem( result, i ), |
54 | (CvPoint*)cvGetSeqElem( result, i-2 ), |
55 | (CvPoint*)cvGetSeqElem( result, i-1 ))); |
56 | s = s > t ? s : t; |
57 | }
|
58 | }
|
59 | |
60 | // if cosines of all angles are small
|
61 | // (all angles are ~90 degree) then write quandrange
|
62 | // vertices to resultant sequence
|
63 | if( s < 0.3 ) |
64 | for(int i = 0; i < 4; i++ ) |
65 | cvSeqPush( squares, |
66 | (CvPoint*)cvGetSeqElem( result, i )); |
67 | }
|
68 | |
69 | // take the next contour
|
70 | contours = contours->h_next; |
71 | }
|
Danke im Voraus Grüße Robert
Mach' mal als erstes den hintergrund weg, geht mit "Local Enhance" oder was artverwandtem. Im Gimp gibt's z.B. "Differenz der Normalverteilungen". Dann Schwellwert auf das Ergebnis.
Nur ein paar Bemerkungen: - Die Hough-Transformation faellt eher unter "brute force". Sollte ein cleverer, recheneffektiver Algorithmus vermeiden. (Auf einem FPGA saehe es anders aus) - Zusammenhaengende Objekte kriegt man mit einem schnellen Fill-Algorithmus indiziert (wenn ueberhaupt noetig, wenn sonst keine Objekte auf dem Bild sind, kann das wegfallen) - Davon erstellt man gleichzeitig per Objekt eine "Boundary Box", also die aeussersten Punkte in einem gerade umfassenden Viereck, oder sogar Achteck. - Ecken lassen sich mit einem Corner-Algorithmus gut auffinden (Evaluierung der Pixel-Umgebung in Kreis-Sektoren). - Die Felder der Matrizen lassen sich mit einem schnellen Bresenham -Algo abscannen/tracen. Damit kennt man dann die Anzahl Felder. - Der Rest ist Geometrie, um die Ansicht der Matrix, die ja perspektivisch schief sein kann, zu normalisieren. Benutze obige Methoden fuer einen 2D-Barcode-Algorithmus und kriege auf einer 480 MHz CPU etwa 3-6 fps unter Linux, die Detektionsrate ist ziemlich gut, schwierig wirds nur, wenn die Lichtverhaeltnisse fliessend sind, dann klappts mit dem Threshold im ersten Pass nicht so gut (er muss sauber zwischen dunkel/Vordergrund und hell/Hintergrund unterscheiden koennen). Weiss nicht, wie weit/gut die diversen freien Toolboxen das unterstuetzen. Mit dem Bresenham-Tracer kann man auch alternative wueste Sachen machen, wenn man in etwa weiss, wonach man sucht..also z.b. um alternierende Pattern in einer gewissen Richtung zu finde, oder man eine Linie zwischen zwei Punkten vermutet. Da gibt es eigentlich nichts schnelleres. Gruesse, - Strubi
Zwie Blum schrieb: > Mach' mal als erstes den hintergrund weg, geht mit "Local Enhance" oder > was artverwandtem. Dazu habe ich anscheinend in OpenCV noch nicht das richtige gefunden. Ich dachte cvEqualizeHist() sorgt für den Effekt - tut es aber nicht. Zwie Blum schrieb: > Im Gimp gibt's z.B. "Differenz der > Normalverteilungen". Dann Schwellwert auf das Ergebnis. Hab bei mir jetzt die englische Version installiert. Dort ist "Difference of Gaussians" bei den Kantenfiltern vorhanden - hast du das gemeint? Für die Kanten hab ich ja jetzt den Canny (weil in OpenCV vorhanden). Etwas anderes passendes habe ich jetzt nicht gefunden. Kennst du was aus OpenCV? Strubi schrieb: > - Zusammenhaengende Objekte kriegt man mit einem schnellen > Fill-Algorithmus indiziert (wenn ueberhaupt noetig, wenn sonst keine > Objekte auf dem Bild sind, kann das wegfallen) > - Davon erstellt man gleichzeitig per Objekt eine "Boundary Box", also > die aeussersten Punkte in einem gerade umfassenden Viereck, oder sogar > Achteck. > - Ecken lassen sich mit einem Corner-Algorithmus gut auffinden > (Evaluierung der Pixel-Umgebung in Kreis-Sektoren). Bei einem "guten" Bild funktioniert der oben gepostete Algorithmus von OpenCV sehr gut. Einzig einen Flächenschwellwert muss ich da auf jeden Fall einbauen, um nicht größere "zusammengebaute" Rechtecke - hier wäre fast FloodFill sogar besser, oder? Strubi schrieb: > - Die Felder der Matrizen lassen sich mit einem schnellen Bresenham > -Algo abscannen/tracen. Damit kennt man dann die Anzahl Felder. Was meinst du damit genau? Ich kenne Bresenham als Algorithmus zum zeichnen (Linie/Kreis). Grüße Robert
Tja, OpenCV ist nett, aber halt auch nur eine Toolbox. Ist nicht immer alles drinnen, was man braucht. Aber es ist alles drinnen, um ein Werkeug zu bauen, das macht was du brauchst - und da liegt die Kunst bei der Bldverarbeitung :-) "Difference of Gaussians" ist genau das Ding. Sehr einfaches Konzept, sehr brauchbar. Was machst du mit den Kanten, wenn du sie hast (Hab' mal das Kantenbild aangehängt)? Probier' mal die Skelettlinie zu finden, die ist interessanter. Hast du Literatur? Gonzales/Woods: "Digital Image Processing", Sonka/Hlavac/Boyle: "Image Processing, Analysis, and Machine Vision" würd' ich die beide als Gutenachtlektüre empfehlen. Jähne, "Digitale Bildverarbeitung" geht auch zur Not.
Robert S. schrieb: > Was meinst du damit genau? Ich kenne Bresenham als Algorithmus zum > zeichnen (Linie/Kreis). Hi Robert, ist auch genau derselbe Algorithmus, nur anstatt dass Du ein Pixel setzt, liest du es. So kannst du entlang eines Vektors Pixel abtasten und z.B. in diesem Fall die Kastenlaenge bestimmen. Das wird natuerlich tricky, wenn du mehr perspektivische Verzerrung erlaubst. Gruesse, - Strubi
Hi, also komplizierte Lösungen über Kanten finden (siehe zahlreiche Versuche mit angehängten Grafiken) sind hier absoluter "overkill". Damit macht man das Bild komplizierter zu interpretieren als es vorher war, weil die Linen nicht mehr gefüllt sind und Unterbrechungen bekommen. Bresenham ist ein guter Ansatz, um eine effektive Lösung auszuarbeiten. Als erstes würde ich aber hier mit der Hough-Transformation anfangen! Die Methode ist in ihrer Basis-Variante unglaublich einfach und dabei hocheffektiv um gerade Linien zu finden. Für Echtzeiterkennung wäre das allein wohl kaum geeignet, obwohl es ja auch optimierte Varianten gibt. Man sollte also erstmal mittels Hough-Transf. die waagrechten und senkrechten Linien finden und daraus dann ein Netz mit parallelen Linien generieren, dass man noch an die Vorlage anpasst, um die Inhalte der einzelnen Boxen exakt zu loklisieren. Wenn das gut klappt, kann man es optimieren, indem man die Hough-Transformation nur auf einen Teil des Netzes anwendet (eine Ecke mit je 2-3 Kästchen in x- und y-Richtung), damit die ersten beiden waagrechten und senkrechten Begrenzungslinien als Vektoren bestimmt und danach per individuellem Bresenham-Scan/Trace die parallen Begrenzungslinien auffindet. Die Hough-Transformation ist halt extrem anspruchslos, was das Ausgangsbild angeht (Kontrast, Lücken, Linenbreite), solange die Linien recht gerade sind. Wichtig wäre nur die evtl. breiten Spots zusammenzufassen bzw. das Zentrum zu bestimmen, um je eine Gerade und keine Schar von Geraden zu erhalten. So könnte man also auch mit einem schlechten Ausgangsbild mit zusätzlichen Inhalten in den Kästchen und beliebigem Hintergrund, sowie perspektivischen Verzerrungen die Umrandungen sicher bestimmen. Nur bei Verzerrungen, die die Linien zu Kurven werden lässt, wird's irgendwann schwierig; ansonsten sollte es "relativ trivial" sein!
Hallo, @razer Ich bin auch interessiert an einer Android OpenCV Portierung. Könntest du mir bitte verraten welche Portierung du verwendest und welches Beispiel du verwendet hast? Danke! mfg Markus
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.