3D-Laserscanner

Ansatz

Nun gibt es mehrere Verfahren, dreidimensionale Objekte zu scannen. Am einfachsten ist meiner Meinung nach ein Scanner nach dem Lichtschnittverfahren, denn alle Hardware, die hierzu nötig ist, sind ein Linienlaser, eine Kamera und dann eine Möglichkeit, das zu scannende Objekt zu drehen.

Der Linienlaser beleuchtet dann das Objekt und "schneidet" die Konturen des Objektes aus, wie im Bild links oben (zugeschnittenes Rohbild eines Schoko-Osterhasen-Scans) zu sehen ist. Rechts ist der Scan komplett. Unten in diesem Bild erkennt man Artefakte, die durch die Reflexion des Lasers am Drehteller entstanden sind. Hat man Bilder einer kompletten Umdrehung, lässt sich aus den Aufnahmen eine Punktwolke rekonstruieren. Der Rest ist ein bisschen Software, wobei zum Glück der Großteil der Arbeit schon getan ist, da die gesamte Bildverarbeitung leicht über die GraphicsMagick Tools abwickelbar ist.

Technische Umsetzung

Laser

Wenn man schon einen Laserpointer besitzt und gerade ein Weinglas zerschmissen hat, kann man den Stiel als Linse vor den Laser kleben. Besser funktioniert aber trotzdem ein Linienlaser, schon weil er sich leichter fokussieren lässt und damit eine bessere Auflösung der Objektdetails ermöglicht. Wenn man eine Kamera mit einem Bayer-Sensor verwendet sollte man einen grünen Laser benutzen, denn diese Sensoren haben 50% grüne Pixel und nur jeweils 25% rote und blaue. Rote und blaue Laser funktionieren aber natürlich auch, ich selbst benutze zum Beispiel einen Laser mit 405nm Wellenlänge.

Kamera

Prinzipiell reicht als Kamera eine einfache Webcam, jedoch gehen je nach Auflösung der Kamera mehr oder weniger Details verloren. Der sinnvollste Kompromiss zwischen Rechenaufwand und Detailauflösung liegt für mich in der Verwendung einer Full HD Videokamera, obwohl ich zu Beginn plante Fotos mit meiner Spiegelreflexkamera zu machen, da ich so die beste mir mögliche Bildqualität erreichen könnte. Aber der Rechenaufwand und die Datenmenge für ein aus einem 1080p60-Video entstandenen 3D-Modell (siehe Bild) lehrten mich eines besseren. Denn das abgebildete 3D-Modell ist 225MB groß und bringt beim Bearbeiten mein voll ausgestattetes Thinkpad W510 ins schwitzen. Ich möchte aber dazu sagen dass ich mich gerade erst einarbeite, sodass ich davon ausgehe, dass ich bisher alle Möglichkeiten zur Vereinfachung des Modells ohne die Details zu verlieren komplett ignoriert habe. Ich habe zwar mit Subsampling experimentiert, aber entweder zu wenig Details oder eine ähnliche Anzahl an Faces wie zuvor erhalten. Auf der anderen Seite habe ich meine Kamera bisher nur im Querformat verwendet also habe ich pro "Scheibe" des Modells maximal 1080 Punkte. Wenn ich die Kamera im Hochformat verwende, ließe sich dieser Wert noch auf maximal 1920 Punkte steigern.

Figur3D

Die Perspektive des Fotos der Figur und die des 3D-Modells sind leicht unterschiedlich, sodass die beiden Bilder nicht 1:1 zueinander passen, aber ich denke eine Ähnlichkeit kann man hier schon erkennen. Der nur sehr niedrig aufgelöste Bereich um den Bart zeigt deutlich die Beschränkungen dieses Verfahrens, denn dieser Bereich wird nicht vom Laser erfasst, wie man an dem einen Quellbild sehen kann. So etwas kann jedoch mit einem zweiten Datensatz an Bildern die von der anderen Seite des Lasers her aufgenommen wurden, ausgleichen. Meine Software unterstützt auch das.

Drehteller

Der Drehteller lässt sich recht einfach entweder aus einer Mikrowelle oder einem Plattenspieler zusammenbauen. Die Mikrowelle bietet den Vorteil, dass eigentlich schon alles fertig ist, denn der Motor, der den Teller dreht, bietet mit normalerweise 2,5 U/min bei unserem 50Hz Stromnetz. Eine wunderbare Basis, wenn das Modell aus einem Video erzeugt werden soll. Bei einem Video mit 30 Bildern pro Sekunde dreht sich das Objekt zwischen jedem Bild um einen halben Grad. Dadurch ergibt sich eine sehr gute Winkelauflösung des Modells. Da ich mit 60fps filme, erreiche ich sogar nur 0,25 Grad pro Sekunde.

Möchte man einen Plattenspieler verwenden, hat man den Vorteil, dass der Plattenteller häufig eine Auflage aus schwarzem Gummi hat, die so gut wie nicht reflektiert und somit ein besseres Ergebnis liefert. Bei der Mikrowelle müsste man das Glas entsprechend schwärzen oder eine ähnliche Auflage bauen. Bei dem Plattenspieler kann man aber in der Regel einfacher einen Schrittmotor an Stelle des Getriebemotors einbauen und damit das bessere Gerät schaffen, wenn man einzelne Fotos und kein Video machen möchte. Die universellste Lösung dürfte ein Plattenspieler mit Schrittmotor sein, bei dem man per Schalter zwischen den beiden Modi wählen kann, am besten gleich noch mit der Integration eines Fernauslösers für die Kamera(s) im Foto-Modus. Vielleicht verbessere ich meinen Scanner noch dahin gehend, denn bisher habe ich einen Plattenspieler mit einem Mikrowellenmotor. Allerdings werde ich für jegliche Verbesserungen erst einen vernünftigen Grund brauchen, so etwas wie einen 3D-Drucker oder so...

So sieht mein 3D-Scanner aktuell aus. Die Kamerahalterung wird aber demnächst durch einen kleinen Kugelkopf ersetzt. Außerdem werde ich dem Gerät noch eine zusammenlegbare Haube aus schwarzem Kunststoff spendieren, damit ich unabhängig vom Tageslicht Gegenstände scannen kann.

Software

Meine Software besteht aus zwei Teilen: einem Shell Script das alle nötigen Parameter im Terminal abfragt und dann mit Hilfe von GraphicsMagick die Quellbilder dekomprimiert, zuschneidet, und in .ppm Dateien speichert. Dann wird das Programm 3ds2 gestartet, dass je nach Farbe des Lasers und eines Schwellwerts die Punktwolke berechnet.

Die fertige Punktwolke liegt dann im .obj Format vor und kann zur Betrachtung und weiteren Bearbeitung in eine Vielzahl von Programmen zur Betrachtung und weiteren Bearbeitung geladen werden. Hier bietet sich zum Beispiel MeshLab an. Dabei sei auch auf diesen interessanten Blog-Artikel verwiesen. Leider habe ich noch keine zufriedenstellenden Ergebnisse mit dem Subsampling erzielt.

Das Shell Script und das Programm müssen sich im selben Ordner befinden. Überhaupt befindet sich die Software im Hinblick auf Benutzerfreundlichkeit und Überprüfung der Eingaben noch in einem sehr frühen Stadium, eine Hilfe gibt es schon gar nicht. Wenn das jemanden akut stört darf derjenige mir gerne eine verbesserte Version mailen.

Download

Shell Script: 3D-Scanner.sh
Programm zur Berechnung des 3D-Modells: 3ds2 V0.61
Quelltext von 3ds2: 3ds2.c V0.61

Bedienung der Software

Als Erstes sollten die Quellbilder gemacht und entsprechend vorbereitet werden. Im Idealfall sollte das vom Objekt reflektierte Laserlicht das Einzige sein was auf den Bildern zu sehen ist. Wenn das nicht möglich ist, kann man versuchen das durch einen höheren Schwellwert auszugleichen. Im Zuge dessen sei darauf hingewiesen dass das Programm nur die Farbkomponente auswertet die der Laserfarbe entspricht (also entweder Rot, Grün oder Blau). Dadurch werden alle Pixel im Bild die in dieser Farbkomponente einen höheren Wert als den Schwellwert haben in die Punktwolke exportiert. So würde ein gelbes (also 255,255,0) Pixel sowohl bei der Auswertung von Grün als auch von Rot in die Punktwolke exportiert werden. Etwas weißes (also 255,255,255) erfüllt immer das Vergleichskriterium. Darauf ist bei der Aufnahme der Quellbilder zu achten. Es muss aber nicht zwangsläufig alles dunkel sein, wie das eine Rohbild des Figur-Scans zeigt.

Des Weiteren kann es bei glänzenden oder sehr bunten Gegenständen dazu kommen, dass der Laserstrahl vollständig reflektiert wird und daher keine brauchbare Punktwolke entsteht.

Als nächstes muss der Ausschnitt der Bilder bestimmt werden, den das Programm analysieren soll. Der Rand des Ausschnitts muss durch die Drehachse des Objektes gehen, damit die Proportionen des 3D-Modells auch mit denen des Originals übereinstimmen. Der Beschnitt wird dann vom Shell Script in der Form <Breite>x<Höhe>+<Versatz in x Richtung>+<Versatz in y Richtung> abgefragt und die Quellbilder entsprechend bearbeitet. Das nächste Bild stellt das nochmal anschaulicher dar.

Arbeitet man mit einem Video als Quelle, lässt sich das alles am bequemsten in einem Abwasch erledigen indem man das Video in eine Videobearbeitungssoftware wie zum Beispiel Avidemux lädt. Damit legt man den Videoausschnitt mit dem Crop-Filter passend fest. Dann die Marker A und B so setzen, das genau eine Umdrehung des Objektes zwischen ihnen liegt. Nun speichert man dieses editierte Video in eine neue Datei ab und lädt diese neue Datei wiederum in Avidemux. Jetzt unter Datei -> Speichern -> Auswahl als JPEG Bilder speichern... die nummerierten Einzelbilder in einen Ordner ablegen.

Sind die Quellen einzelne Fotos, muss nur der Ausschnitt ermittelt werden. Das geht zum Beispiel mit GIMP und dem rechteckige Auswahl Werkzeug. In der Werkzeugkasten findet man dann alle Angaben die man braucht.

Das Shell-Script

Die Standardangaben können im Shell Script dem eigenen Setup angepasst werden, sodass die Abfragen nur noch mit Enter bestätigt werden müssen. Wenn eine Kamera fest montiert wird und sich somit der zu verarbeitende Ausschnitt nicht mehr ändert, kann diese Angabe fest im Shell Script eingetragen werden und die Abfrage danach im Gegenzug auskommentiert werden.

Zuerst fragt das Skript nach dem Datentyp der Quellbilder, oder genauer gesagt, ob es sich um JPEGs oder PPM Dateien handelt. Eigentlich ist diese Frage auch nicht ganz korrekt, denn die Bilder müssen keine JPEGs sein, es sind alle Formate möglich, die von GraphicsMagick unterstützt werden (und das sind so ziemlich alle). Sollten die Quellbilder schon vom Typ PPM sein und keinen Beschnitt mehr benötigen, so müssen die Dateien nicht weiter vorbereitet werden und können gleich ausgewertet werden. Diese Option ist nützlich, um unnützen Rechenaufwand zu vermeiden.
J (Standard) für JPEGs, P für PPM.

Als nächstes will das Skript wissen, ob eine oder zwei Kameras Daten bereitstellen.
0 (Standard) für eine Kamera, für mehrere Kameras 1.

Dann werden Quell- und Zielordner und wenn mehrere Kameras verwendet werden auch die Anfänge der jeweiligen Dateinamen der Bilder abgefragt. Wenn zum Beispiel die Bilder DCIM0000.jpg, DCIM0001.jpg, DCIM0002.jpg und so weiter heißen, dann sollte man bei der Frage nach dem Dateinamen "DCIM*" (natürlich ohne Anführungszeichen) eingeben. Der Standard für Bilder der rechten Kamera ist "framer*" und für Bilder der linken Kamera entsprechend "framel*".

Die Auflösung in Grad pro Bild meint um wie viel Grad sich das Objekt zwischen zwei Bildern weiter dreht. Das hängt vom jeweiligen Drehteller ab, siehe dazu den Abschnitt über den Drehteller.

Der Winkel zwischen Kamera und Laser muss nicht genau bekannt sein, diese Angabe wird nur dazu genutzt, um die Proportionen des Modells zu erhalten.
Wenn die Kameras nicht parallel zur Drehachse liegen, entsteht auch eine Verzerrung (Stichwort "Stürzende Linien"), die aber noch nicht korrigiert wird.

Ich denke, der Rest dürfte selbsterklärend sein. Im Zweifel Enter drücken, dann werden Standardwerte benutzt. Ob es funktioniert, sieht man dann ja.

Kommandozeilenargumente von 3ds2

Hier noch eine Übersicht über alle Kommandozeilenargumente die 3ds2 versteht. Das könnte nützlich sein, wenn man nicht mit dem Shell Script arbeiten, sondern sein eigenes Interface bauen möchte.