Autor Beitrag
Namenlosnameless
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 259
Erhaltene Danke: 6

Windows XP Home Edition, Windos Vista
C#
BeitragVerfasst: Do 26.03.15 00:24 
Hallo Liebe Entwickler-Ecke!

Gleich vorweg das wird jetzt viel Text :wink:

Ich bastle seit einigen Jahren mit Lego-Mindstorms herum. Diesmal habe ich mir ein recht ambitioniertes Projekt vorgenommen. Einen Roboter-Arm der zeichnen kann.
In etwa so: (KLICK) habe ich mir das vorgestellt. Das Lego-Teil ist gebaut und die Inverse-Kinematik ist bereits implementiert (also ich gebe dem Arm eine Positionsangabe und er bewegt den Stift an den Punkt den ich angegeben habe! Dabei kann ich aber auch eine Sammlung von Punkten übergeben und die Software interpoliert linear dazwischen um den Robo-Arm möglichst präzise zu bewegen!)

Was mir derzeit Kopfzerbrechen bereitet ist das Einlesen und Aufbereiten von Bildern , so wie es in dem Video gemacht wird.

Hiermal ein Überblick was ich bereits implementieren konnte!

Dabei habe ich derzeit eine Kantenerkennung mit dem Canny-Algorithmus mehr oder weniger Implementiert.
  • Konvertieren in Graustufenbild
  • Weichzeichnen mit Gauss'schem Kernel
  • Ableitung des Bildes in X und Y Richtung
  • Kantenerkennung
  • Winkelerkennung
  • NonMaximumSupression-Algorithmus
  • Hysterese


Am Ende der Kantendedektion habe ich 2 Arrays vorliegen. Einer speichert einen Boolean-Wert ob ein Pixel eine Kante ist oder nicht. Der andere einen Integer-Wert für die Richtung

Für das Nachfolgende würde ich eure Hilfe benötigen: (Ich hab mir natürlich zu jedem Thema Gedanken gemacht, die ich auch dazuschreiben werde!)

Problem 1: Zusammenhängende Kanten finden und als Linien abspeichern

Um einen möglichst guten Zeichenfluss für den Roboter zu gewährleisten ist es essentiell dass er ohne Absetzen möglichst lange Linien ziehen kann.
Meine Idee: Es müsste Theoretisch möglich sein ein beliebiges Pixel das als Kante erkannt wurde entlang des Winkels der gewonnen wurde zu vervolgen und immer zu Prüfen ob das folgende Pixel auch eine Kante ist. Somit könnte man zumindest ein paar Stücke von Kanten erkennen und zusammenfassen. Jedoch wird diese Methode bei Gabelungen scheitern weil die Richtungsangabe des Pixels eindeutig ist und somit garkeine Möglichkeit besteht herauszufinden ob sich gerade 2 Kanten schneiden. Damit kann es passieren dass das kürzere Stück verwendet wird obwohl die andere Seite der Gabelung eine viel längere zusammenhängende Kante ergeben hätte. Nimmt man das Problem mit der Gabelung aus, müsste man mit einer geeigneten Rekursion die längsten Kanten finden können. Sobald der eine Rekursionsbaum durchlaufen ist speichert man die Linie ab und geht zum nächsten Pixel dass noch nirgendwo zugeordnet wurde. usw.... Zum Schluss müssen alle Linien nochmal untersucht werden und Bereiche gleicher Richtung mit 2 Positionsangaben anstatt n-vieler angegeben werden.
Also z.B. Gefundene Kante hat die Punkte: [0,0];[1,0];[2,0];[3,0];[3,1];[3,2];[3;3] dann könnte man das ja auch so schreiben: [0,0];[0,3];[3,3] ohne das Information verloren geht.

Frage: gibts da vielleicht schon einen Algorithmus der diese Aufgabe effizient löst? Oder hat jemand eine andere bessere Idee wie man das Problem angehen könnte?

Problem 2: Flächen erkennen

Nur die Umrisse zu zeichnen wäre ja langweilig :wink:
Leider bin ich noch nicht dahinter gekommen wie man zusammenhängende Flächen in einem Bild erkennt.
Meine Idee: Eine Herangehensweise könnte sein, Bereiche mit ungefähr gleichen Grauwerten zu untersuchen. Da habe ich aber leider garkeinen Plan wie das funktionieren könnte, oder ob meine Idee da überhaupt zum Ziel führen kann!
Frage:Gibts einen Algorithmus der das kann (Schlagwort würde genügen -- Meine Google-Suchen waren wohl sehr ineffizient), oder wie kann man sowas machen?

Problem 3: Vektorisieren
natürlich müssen die gefundenen Kanten und Flächen noch irgendwie für den Roboter "begreifbar" gemacht werden.

Meine Ideen: Für Kanten ist das ganze ja recht trivial, vorausgesetzt man konnte sie vorher als Linien abspeichern (Siehe Problem 1). Nicht mehr trivial wirds jedoch wenn man jetzt versucht die Flächen umzuwandeln. Aber ich denke da habe ich schon einen ganz guten Lösungansatz: Man nimmt einen Punkt aus der Fläche und sucht sich das näherste Pixel dass als Kante erkannt wurde, ließt die Richtung dieses Pixels aus undverwendet sie um das nächste Pixel aus der Fläche zu finden. Sobald die Kante "fertig" ist (wie auch immer man "fertig" letztendlich definiert) speichert man die so gewonnene Linie als Kante ab, so als ob man sie durch den Canny-Algorithmus gewonnen hätte. Und wiederholt den vorgang bis alle Pixel irgendwie verbaut wurden. Ich denke die in dem YouTube-Video gezeigte Software macht ähnliches. Zumindest verlaufen die Linien der Fläche verdächtig ähnlich wie die der Kanten.
Fraglich ist für mich nur wie man eine sinnvolle Ausstiegsbedingung formuliert, mit der man eine Linie als abgeschlossen betrachten kann und mit der nächsten anfängt.

Frage: Auch hier wären sachdienliche Hinweise zur Herangehensweise sehr nützlich!

Jeder der auch nur eine Idee hat wie man ein Teilproblem bewältigt seis jetzt Arbeitsweise des Algorithmus, Implementierung in C# oder einfach nur Verbresserungsvorschläge ist herzlich eingeladen mir seine Gedanken mitzuteilen.

Dennoch muss ich auch ein bisschen an euer Verständnis appellieren. Ich hab mir Programmieren usw. im Laufe der letzten 6 Jahre zwar recht solide aber dennoch "nur" selbst begebracht, es kann also sein dass ich bei dem einen oder anderen Fachterminus aussteige :p

mfg Namenlosnameless

_________________
1:<<Life sucks!!>> 2:<< Well okay>> 1: <<Just Yours>> 2:<<Ohmph>>
FinnO
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: Do 26.03.15 10:29 
Moin,

zu deinem Problem 1:

Zusammenhängende Kanten zu erkennen ist - wie meiner Meinung nach alle Probleme in der Bildverarbeitung - keine einfache Sache.
Wenn du dich auf Primitive besinnst, also zum Beispiel gerade Linien und Kreise (und Performance für dich keine Rolle spielt) dann könntest du dir die Hough Transformation mal anschauen. Damit lassen sich gewisse Features aus Bildern extrahieren.

Problem 2:

Hier würde ich die Verwendung von einem Region-Growing-Algorithmus empfehlen. Dazu wählst du im Prinzip einen Punkt aus und dehnst von dort eine Fläche aus, bis ein Abbruchkriterium (z.B. ein zu hoher Farbgradient o.ä.) erfüllt ist.

Zu Problem 3 fällt mir jetzt keine generische Lösung ein. Was du dir definitiv aber anschauen solltest ist OpenCV, damit sparst du dir sicherlich die Implementierung einer Vielzahl von Algorithmen. Die Macher des YouTube Videos nutzen meiner Einschätzung nach auch nur eine Reihe von Filtern, die Entsprechende Pixelausgaben generiert.

Gruß
Finn
Namenlosnameless Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 259
Erhaltene Danke: 6

Windows XP Home Edition, Windos Vista
C#
BeitragVerfasst: Do 26.03.15 12:34 
Hallo FinnO

zu 1) Ich will wirklich nur gerade Kanten erkennen... Also jeweils jene Kantenrichtung die über den Gradientenwinkel durch die Abkritung in X bzw. Y erhalten werden.

hough-Transformation muss ich mir anschauen!

Zu 2) Schaue ich mir auch gleich an!

Zu 3) ich denke nicht dass da einfach nur Pixel ausgegeben werden... Dazu mal der Roboter nachher viel zu viele durchgängige Linien in der Flächenerkennung. Also da werden definitiv Linien als Sammlung von Vektoren übergeben!

Jedenfalls rießen großes Danke!

_________________
1:<<Life sucks!!>> 2:<< Well okay>> 1: <<Just Yours>> 2:<<Ohmph>>
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1321
Erhaltene Danke: 117

Win 10
RIO, CE, Lazarus
BeitragVerfasst: Do 26.03.15 15:48 
Hi, setz einfach erstmal Problem Nummer Zwei um. Also die Erkennung der Flächen. Ist das erledigt hast Du automatisch die Kanten, denn die bleiben ja als Trennung zwischen den Flächen übrig.
Ich habe da früher mal ne ganze portion Hirnschmalz rein investiert und war mit Region-growing / Watershed Transformation ganz zufrieden.
Die Kanten sind zum Schluss nur noch einen Pixel breit. So dass man dann recht einfach via ablaufen der Kanten Richtungsvektoren bilden könnte.
Interessanter finde ich, zu entscheiden welche Flächen dann gezeichnet werden und diese Fläche in Linien aufzuteilen. Beim 3D Druck wird ja auch mit einem bestimmten Verfahren ein Layer gleichmäßig gezeichnet um es zu füllen. Aber in dem Video wirkt das viel natürlicher, nicht einfach nur zig zag.

Mich würde mal Interessieren wie die Entscheidung getroffen wurde in welcher Reihenfolge die Linien vom der Roboter gezeichnet werden sollen.

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
Namenlosnameless Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 259
Erhaltene Danke: 6

Windows XP Home Edition, Windos Vista
C#
BeitragVerfasst: Do 26.03.15 16:41 
Hallo Sinspin!

Guter Ansatz mit dem Problem Nr. 2

Zufällig beschäftige ich mich seit einiger Zeit recht intensiv mit 3D-Druckern und seit Weihnachten steht so ein Teil auch bei mir rum...
Was die diversen Slicer-Programme machen ist ein sogenanntes Infill wo über die ganze Fläche einfach ein Gewebe (z.B. Linien, Honigwaben, Rechtecke etc...) mit einer bestimmten Dichte gelegt und einfach gedruckt. Die Fläche wird außen mit einem durchgängigem Streifen abgegrenzt somit ist es eigentlich egal wie das Infill aussieht... Das funktioniert leider im 2D-Fall nicht.

Wie bereits erwähnt erweckt der Verlauf für die Linien der Flächen auf mich den Eindruck dass sie immer entlang von Kanten gezogen werden.

_________________
1:<<Life sucks!!>> 2:<< Well okay>> 1: <<Just Yours>> 2:<<Ohmph>>
Namenlosnameless Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 259
Erhaltene Danke: 6

Windows XP Home Edition, Windos Vista
C#
BeitragVerfasst: Do 26.03.15 16:54 
Habe mir jetzt nochmal das Video ganz genau angeschaut... Was da unter "Flächen-Detektion" läuft sind im Endeffekt einfach 2 Schwellwerte Pixel die Grauwerte zwischen den Werten haben werden einfach zu einer Fläche gezählt. Letztendlich gibt es dann nur eine Fläche!

Dieser Roboter ist 2007 auf einer Lego-Convention vorgestellt worden und hat dort den ganzen Tag Fotos von Menschen gezeichnet die vor einem Greenscreen gestanden sind. Durch den Chromakey kann sicher gestellt werden, dass es nur eine einzige zusammenhängende Fläche gibt.

Die Linien verlaufen exakt entlang der mit Canny-EdgeDetection gefundenen Kanten, also schätze ich dass ich doch auf der richtigen Spur bin.
Gezeichnet werden dann zuerst Außenkanten dann die Flächenlinien. Jedoch muss dabei noch ein Zwischenschritt erfolgen, da der Roboter deutlich weniger Linien zeichnet als das Programm ausrechnet. Vermutlich kann man da per Zufall einen gewissen Prozentsatz eleminieren?!

mfg Namenlosnameless

_________________
1:<<Life sucks!!>> 2:<< Well okay>> 1: <<Just Yours>> 2:<<Ohmph>>