| Operatoren |
fuse_object_model_3d — Fusionieren von 3D-Objektmodellen.
fuse_object_model_3d( : : ObjectModel3D, BoundingBox, Resolution, SurfaceTolerance, MinThickness, Smoothing, NormalDirection, GenParamName, GenParamValue : ObjectModel3DFusion)
fuse_object_model_3d fusioniert mehrere Punktwolken, welche die Oberfläche eines Objekts repräsentieren, zu einer wasserdichten Oberfläche ObjectModel3DFusion. Der Operator vereinfacht die Nachverarbeitung von Punktwolken, welche bereits im selben Koordinatensystem erfasst sind. Insbesondere können folgende Prozesse oft einfach und mit hoher Qualität abgewickelt werden: Vereinigung, Unterdrückung von Ausreißern, Kompromiss aus Glättung und Kantenerhaltung, äquidistantes Subsampling, Löcher füllen, Vermaschung der resultierenden Oberfläche. Der Operator fuse_object_model_3d hat allerdings eine relativ lange Rechenzeit.
Sollen Punktwolken fusioniert werden, welche über Stereo-Rekonstruktion aufgenommen wurden, sollte stattdessen reconstruct_surface_stereo verwendet werden.
Aufnahme der Punktwolken; diese in ein einheitliches Koordinatensystem bringen, z.B. mittels register_object_model_3d_pair und register_object_model_3d_global.
Berechnen der Dreiecke oder Punktnormalen für die Punktwolken mittels triangulate_object_model_3d oder surface_normals_object_model_3d, sofern diese nicht bereits vorhanden sind. Die Triangulierung ist geeigneter, falls die Oberflächen viele Ausreißer oder zu schließende Löcher haben. Ansonsten, im Falle von glatten Oberflächen, kann man mit Punktnormalen arbeiten.
Inspizieren der Normalen des Eingabe-Modells mittels visualize_object_model_3d mit der Option GenParamName 'disp_normals' oder dev_inspect_ctrl. Die Punkt- oder Dreiecksnormalen müssen konsistent entweder nach innen oder außen gerichtet sein. Der Parameter NormalDirection muss dann entsprechend auf 'inwards' oder 'outwards' gesetzt werden.
Festlegen des umschließenden Quaders über den Parameter BoundingBox. Für eine erste Näherung des umschließenden Quaders BoundingBox kann get_object_model_3d_params verwendet werden, mit GenParamName gesetzt auf 'bounding_box1'.
Die Werte für die initialen Parameter kann man wie folgt abschätzen: Einen groben Wert für Resolution (z.B. 1/100 der Raumdiagonalen des umschließenden Quaders BoundingBox), SurfaceTolerance etwas größer (z.B. 5*Resolution), MinThickness als minimale Dicke des Objekts (sollte die Eingabe-Punktwolke das Objekt nur von einer Seite aus darstellen, wird empfohlen, den Wert sehr hoch zu setzen, damit das Objekt erst durch den umschließenden Quader BoundingBox abgeschnitten wird) und Smoothing mit Wert 1.0.
Ausführen des Operators fuse_object_model_3d und nachjustieren der Parameterwerte zur Verbesserung des Ergebnisses bezüglich Qualität und Rechenzeit, siehe auch unten. Zur Vermeidung langer Rechenzeiten ist eine Auflösung Resolution empfohlen, die gerade noch ausreichend ist, um Objektdetails erkennen zu können, während die anderen Parameter eingestellt werden. Zur Optimierung sollten auch die zusätzlichen Parameter von GenParamName in Erwägung gezogen werden.
In dem HDevelop-Beispiel fuse_object_model_3d_workflow wird gezeigt, wie die hier aufgelisteten Parameter für eine bestimmte Anwendung optimiert werden können.
Die Eingabe-Punktwolken ObjectModel3D müssen in einem gemeinsamen Koordinatensystem sein und stellen die initiale Oberfläche dar. Des Weiteren müssen diese Punktwolken Dreiecke oder Punktnormalen beinhalten. Sollten beide Attribute vorhanden sein, werden, aufgrund der Geschwindigkeitsvorteile, als Standardeinstellung Punktnormalen verwendet. Wenn die Verwendung von Dreiecken gewünscht ist, müssen die Dreiecke und Punkte mittels copy_object_model_3d in ein neues Objektmodell überführt werden. Mit Oberflächen, die viele Ausreißer oder zu füllende Löcher beinhalten, empfehlen wir, die Triangulierung zu verwenden, während glatte Oberflächen mittels Punktnormalen verarbeitet werden können. Die Punkt- oder Dreiecksnormalen müssen entweder konsistent ins Innere oder Äußere des Objekts gerichtet sein.
NormalDirection gibt an, ob die Punkt- oder Dreiecksnormalen nach innen ('inwards'), oder außen ('outwards') gerichtet sind. Wird nur ein einzelner Wert angegeben, so wird dieser für alle Eingabe-Modelle verwendet. Ansonsten muss die Anzahl Eingabewerte der Anzahl an Eingabe-Modellen entsprechen.
Der umschließende Quader BoundingBox definiert den berücksichtigten Bereich, sowohl die Eingabepunkte als auch die Ausgabepunkte betreffend. Punkte außerhalb des umschließenden Quaders werden verworfen, ebenso auch Dreiecke mit zumindest einem Punkt außerhalb des umschließenden Quaders. Der umschließende Quader BoundingBox wird durch das Tupel [x1,y1,z1,x2,y2,z2] festgelegt, welches die beiden gegenüberliegenden Ecken P1=[x1,y1,z1] und P2=[x2,y2,z2] des Quaders angibt (mit Kanten parallel zu den Koordinatenachsen). Damit der umschließende Quader festgelegt werden kann, muss P1 in der unteren vorderen Ecke und P2 in der oberen hinteren Ecke des Quaders sein, d.h. x1<x2, y1<y2 und z1<z2. Der umschließende Quader wird in der gleichen Einheit gesetzt, die in ObjectModel3D verwendet wird. Der Operator versucht, eine geschlossene Oberfläche zu kreieren. Falls die Eingabe-Punktwolke das Objekt nur von einer Seite repräsentiert, will man üblicherweise den umschließenden Quader als Begrenzung des unbekannten Teils. Dafür setzt man MinThickness z.B. auf einen Wert größer oder gleich der Länge der Diagonale des umschließenden Quaders (welche über get_object_model_3d_params mit dem Parameter 'diameter_axis_aligned_bounding_box' erhalten werden kann). Wird ein Objekt durch eine Seite des umschließenden Quaders abgeschnitten, hat das Objekt an dieser spezifischen Ebene der Oberfläche keine Punkte, d.h. es ist hohl. Um einen eventuellen unbekannten Teil des Objekts an der richtigen Stelle zu begrenzen, muss die Eingabe-Punktwolke möglicherweise rotiert werden, da die Kanten des umschließenden Quaders immer parallel zu den Koordinatenachsen sind. Eine solche Rotation ist z. B. möglich über die Operatoren affine_trans_object_model_3d oder rigid_trans_object_model_3d.
Die Auflösung Resolution definiert die Distanz benachbarter Stützstellen in Richtung der Koordinatenachsen bei der Diskretisierung des umschließenden Quaders, BoundingBox. Resolution wird in der gleichen Einheit gesetzt, die in ObjectModel3D verwendet wird. Ein zu kleiner Wert, d.h. eine zu hohe Auflösung, wird die Rechenzeit unnötig erhöhen während ein zu großer Wert zu hohem Detailverlust bei der Rekonstruktion führen kann. Wir empfehlen mit einer groben Auflösung zu beginnen. Bei Änderung der Auflösung Resolution muss Smoothing eventuell adaptiert werden. Zudem muss zur Vermeidung von Diskretisierungseffekten Resolution stets kleiner sein als SurfaceTolerance.
SurfaceTolerance legt fest, wie viel Rauschen der Eingabe-Punktwolke von der Innen- und Außenseite her zur Oberfläche vereint wird. Die Ausnahme ist gegeben durch SurfaceTolerance größer als 'distance_in_front', dann bestimmt 'distance_in_front' die Dicke der Oberfläche zur Außenseite. SurfaceTolerance wird in der gleichen Einheit gesetzt, die in ObjectModel3D verwendet wird. SurfaceTolerance gibt die Dicke der Oberfläche an, während MinThickness die Dicke des gefüllten Objekts nach innen bestimmt. Daher muss SurfaceTolerance kleiner sein als MinThickness. Punkte, die laut NormalDirection (sowie GenParamName='angle_threshold') auf der Innenseite der Objektoberfläche liegen, werden somit als sicher innerhalb eines Objekts betrachtet, wenn ihre Distanz zur initialen Oberfläche größer ist als SurfaceTolerance, aber kleiner als MinThickness. Um Diskretisierungseffekte zu vermeiden, muss SurfaceTolerance stets etwas größer als Resolution sein.
MinThickness legt die Dicke des Objekts auf der initialen Oberfläche in Normalenrichtung fest. Sie wird in der gleichen Einheit gesetzt, die in ObjectModel3D verwendet wird. Punkte, die laut NormalDirection (sowie GenParamName='angle_threshold') auf der Innenseite der Objektoberfläche liegen, werden somit nur als innerhalb des Objekts betrachtet, falls ihre Distanz zur initialen Oberfläche den Wert MinThickness nicht überschreitet. Dies kann zu Hohlräumen im Objekt führen. MinThickness muss stets größer als SurfaceTolerance sein. Der Operator versucht, eine geschlossene Oberfläche zu erstellen. Für Punktwolken, welche das Objekt von verschiedenen Seiten repräsentieren, wird MinThickness am besten als die Dicke des schmalsten Bereichs festgelegt. Sollte die Eingabe-Punktwolke das Objekt nur von einer Seite repräsentieren, will man üblicherweise den umschließenden Quader als Begrenzung des unbekannten Teils. Damit die Ausdehnung des Objekts nicht bereits durch die gesetzte Dicke begrenzt wird, muss MinThickness groß genug gesetzt werden. Aufgrund der fehlenden Beobachtung der Objektrückseite wird die Rekonstruktion dieses Teils wahrscheinlich falsch sein. Falls verschiedene Objekte nur von einer Seite betrachtet werden, sollte MinThickness kleiner sein, damit die rekonstruierten Objekte schmal genug bleiben, um nicht zu einer Oberfläche zusammengefasst zu werden. Zu kleine Werte können Löcher oder Doppelwände in den vereinigten Punktwolken ergeben. Hingegen können zu große Werte zu einer deformierten Punktwolke oder gar zum Aufblasen der Punktwolke Richtung Oberfläche führen (wird die Oberfläche über den umschließenden Quader hinaus aufgeblasen, so wird sie an der entsprechenden Ebene abgeschnitten und es werden wie oben beschrieben keine Punkte für diese Ebene zurückgegeben).
| (1) | (2) |
Smoothing bestimmt, wie eine kleine Gesamtabweichung der Distanzfunktion gegenüber der Datentreue gewichtet wird. Damit kann also die 'Unruhe' der rekonstruierten Oberfläche durch den Glättungsparameter Smoothing gesteuert werden. Ein geeigneter Wert für Smoothing, um eine passende und visuell ansprechende Oberfläche zu erhalten, muss durch Ausprobieren gefunden werden. Ein zu kleiner Wert führt dazu, dass viele Ausreißer miteinbezogen werden, selbst wenn die Oberfläche dadurch große Sprünge aufweist. Zu große Werte hingegen führen zu Verlust an Wiedergabentreue gegenüber den Eingabe-Punktwolken (wie der Algorithmus die Distanz zu den Eingabe-Punktwolken sieht, hängt stark von SurfaceTolerance und MinThickness ab). Smoothing muss eventuell adaptiert werden, wenn Resolution geändert wird.
Mit GenParamName und GenParamValue können die folgenden zusätzlichen Parameternamen und -werte eingestellt werden:
Punkte, die gemäß NormalDirection (sowie GenParamName='angle_threshold') auf der Außenseite der Objektoberfläche liegen, werden nur dann als Teil des Objekts betrachtet, wenn ihre Distanz zur initialen Oberfläche nicht größer ist als 'distance_in_front'. Dies ist das Pendant für die Außenseite zu MinThickness der Innenseite, mit der Ausnahme, dass 'distance_in_front' auch kleiner als SurfaceTolerance sein darf. Falls 'distance_in_front' kleiner ist als SurfaceTolerance, bestimmt dies die Oberflächendicke des Objekts zur Außenseite hin. Dieser Parameter ist nützlich, falls Löcher in der Oberfläche entlang eines Sprunges gefüllt werden sollen (z.B. entlang der Blickrichtung des Sensors). In diesem Fall kann 'distance_in_front' auf einen kleinen Wert gesetzt werden, um falsche Initialisierungen zu vermeiden. 'distance_in_front' wird in der gleichen Einheit gesetzt, die in ObjectModel3D verwendet wird. Sie sollte stets etwas größer als Resolution sein, um Diskretisierungseffekte zu vermeiden. Der Defaultwert für 'distance_in_front' ist ein Wert größer als die Raumdiagonale des umschließenden Quaders, wodurch alle Punkte außerhalb des Objekts berücksichtigt werden.
Werteliste: 0.001, 0.1, 1, 10
Defaultwert: größer als die Raumdiagonale des umschließenden Quaders
Restriktion: 'distance_in_front' > 0
legt den Winkel des Kegels um die Oberflächennormalen fest und wird in [rad] gesetzt. Bei der Bestimmung der Distanzinformation für die Datentreue werden nur jene Punkte berücksichtigt, die innerhalb eines solchen Kegels, mit Spitze auf dem nächsten Oberflächenpunkt, liegen. Wenn Distanzen zu Dreiecken bestimmt werden, kann 'angle_threshold' auf 0.0 gesetzt werden, wodurch ausschließlich die Volumen über den Dreiecksflächen (also gerade Prismen) berücksichtigt werden. Werden Punktnormale verwendet und damit Distanzen zu Normalen bestimmt, muss 'angle_threshold' auf einen größeren Wert gesetzt werden.
Falls Ausreißer das Resultat stören, kann ein Reduzieren des Wertes 'angle_threshold' helfen. Falls Löcher entlang eines Sprunges in der Oberfläche gefüllt werden sollen (z.B. entlang der Blickrichtung des Sensors), kann ein Vergrößern des Wertes für 'angle_threshold' helfen.
Werteliste: 'rad(0.0)', 'rad(10.0)', 'rad(30.0)'
Defaultwert: 'rad(10.0)'
Restriktion: 'angle_threshold' >= 0
bestimmt, ob die Ausgabepunkte mit dem Algorithmus 'marching tetrahedra' trianguliert werden sollen, Dazu muss 'point_meshing' auf 'isosurface' gesetzt werden. Wird eine Vermaschung der Isofläche aktiviert, sind auch bei gleicher Resolution mehr Stützpunkte in ObjectModel3DFusion.
Wertevorschläge: 'none', 'isosurface'
Defaultwerte: 'isosurface'
Der Algorithmus produziert eine wasserdichte, geschlossene Oberfläche (welche eventuell am umschließenden Quader BoundingBox abgeschnitten ist). Ziel ist es, eine möglichst glatte und trotzdem formtreue Oberfläche zu erhalten. Dazu wird der umschließende Quader gesampelt und jedem Sample-Punkt ein Distanzwert zu einer sogenannten Isofläche (bestehend aus Punkten mit Distanzwert 0) zugewiesen. Die endgültigen Distanzwerte (und somit die Isofläche) erhält man durch Minimierung einer Fehlerfunktion, basierend sowohl auf der Datentreue zur Eingabe-Punktwolke als auch der totalen Variation ('Sprunghaftigkeit') der Distanzfunktion. Dadurch erreicht man eine Fusion der Eingabe-Punktwolken (siehe das Paper unter Referenzen).
Die Berechnung der Isofläche kann durch die Parameter des Operators beeinflusst werden. Die Auflösung, d.h. die Distanz zwischen den Stützstellen des umschließenden Quaders (in Richtung der Koordinatenachsen), kann durch den Parameter Resolution bestimmt werden.
Datentreue zu den Eingabe-Punktwolken wird erfasst als die vorzeichenbehafteten Distanzen der Abtastpunkte, d.h. Stützstellen des umschließende Quaders, zu ihren nächsten Nachbarn (Punkte oder Dreiecke) der Eingabe-Punktwolke. Ob ein Abtastpunkt als innerhalb oder außerhalb des Objektes liegend betrachtet wird (Vorzeichen der Distanz), wird bestimmt durch die Normale des nächsten Nachbarn auf der initialen Oberfläche und der gesetzten Richtung NormalDirection. Um zu bestimmen, ob ein Abtastpunkt in Bezug auf die Eingabe-Punktwolke sicher innerhalb oder außerhalb eines Objektes liegt, wird die Distanz zum nächsten Nachbarn auf der initialen Oberfläche bestimmt. Ein Abtastpunkt der Innenseite wird als sicher im Objekt liegend betrachtet, wenn die Distanz größer als SurfaceTolerance, aber kleiner als MinThickness ist, während ein Abtastpunkt der Außenseite als außerhalb gilt, wenn die Distanz größer 'distance_in_front' ist.
Datentreue zu den Eingabe-Punktwolken wird nur berücksichtigt für Abtastpunkte, die maximal MinThickness innerhalb oder GenParamName 'distance_in_front' außerhalb der initialen Oberfläche liegen.
Des Weiteren wird die Datentreue für einen gegebenen Abtastpunkt nicht gepflegt, falls er nicht innerhalb eines Kegels mit Winkel GenParamName 'angle_threshold' liegt. Also dann nicht, wenn die Verbindungslinie des Abtastpunktes zu seinem nächsten Nachbarn auf der initialen Oberfläche und die Oberflächennormale des nächsten Nachbarn einen Winkel größer als GenParamName 'angle_threshold' bilden. Während die Distanz zu nächsten Nachbarsdreiecken oft überzeugendere Resultate liefert, können die Distanzen zu den nächsten Punkten viel schneller berechnet werden.
Die anschließende Optimierung der Distanzwerte ist die selbe wie in reconstruct_surface_stereo mit Method='surface_fusion'.
Der Parameter Smoothing reguliert die 'Sprunghaftigkeit' der Distanzfunktion durch Gewichten der beiden Terme in der Fehlerfunktion: Datentreue zur Eingabe-Punktwolke einerseits, Gesamtabweichung der Distanzfunktion andererseits. Der geeignete Wert für Smoothing, um eine passende und visuell ansprechende Oberfläche zu erhalten, muss durch Ausprobieren gefunden werden.
Die 3D Punkte des in ObjectModel3DFusion zurückgegebenen Objektmodells stammen aus der Isofläche, auf der die Distanzfunktion Null ist. Die Normalen werden aus dem Gradienten der Distanzfunktion berechnet. Die dadurch erhaltene Punktwolke kann auch vermascht werden mittels Algorithmus 'marching tetrahedra' durch Setzen des Parameters GenParamName 'point_meshing' auf GenParamValue 'isosurface'.
Es wird empfohlen, sich an den oben stehenden Ablauf zu halten. Wenn die Rekonstruktionsergebnisse nicht zufriedenstellend sind, können die folgenden Verbesserungsmaßnahmen versucht werden:
Die Eingabe-Punktwolken sollten die gesamte Objektoberfläche repräsentieren. Falls Punktnormalen benutzt werden, sollten die Punkte auf der ganzen Oberfläche dicht liegen und nicht nur entlang der Objektkanten. Insbesondere mit CAD-Daten sollte die Triangulierung verwendet werden.
Das Verwenden von Dreiecken statt Punktnormalen führt typischerweise zu besseren Ergebnissen. Sollten beide Attribute vorhanden sein, werden, aufgrund der Geschwindigkeitsvorteile, als Standardeinstellung Punktnormalen verwendet. Bei Bevorzugung von Dreiecken verwenden Sie bitte copy_object_model_3d, damit nur Informationen zu Punkten und Dreiecken vorhanden sind.
Falls Ausreißer des Eingabe-Modells die ausgegebene Oberfläche selbst für große Werte von Smoothing stören, kann man versuchen, GenParamName 'angle_threshold' zu reduzieren. Falls gewünscht, können Ausreißer des Eingabe-Modells auch entfernt werden, z.B. mittels connection_object_model_3d. In kleinerem Ausmaß kann auch das Modifizieren von GenParamName 'distance_in_front' helfen, gewisse Ausreißer zu minimieren.
Falls Löcher selbst für große Werte von Smoothing nicht gefüllt werden (z.B. ein Sprung der Oberfläche in Blickrichtung des Sensors), kann man versuchen, GenParamName 'distance_in_front' zu reduzieren. Vergrößern von GenParamName 'angle_threshold' kann dem Algorithmus helfen, die Löcher zu schließen. Beachten Sie, dass triangulate_object_model_3d beim Triangulieren Löcher von Sensordaten, welche eine 2D Zuordnung enthalten, füllen kann.
Ist die Rückgabe leer, kann man versuchen, Smoothing zu reduzieren. Sollte die Rückgabe selbst für sehr kleine Werte von Smoothing leer bleiben, empfehlen wir zu überprüfen, ob ob MinThickness zu groß ist und ob die NormalDirection richtig gesetzt ist.
Um die Rechenzeit zu verkürzen, empfehlen wir folgende Punkte zu beachten:
Der umschließende Quader sollte möglichst eng um die zu fusionierenden Punktwolken liegen. Ansonsten wird die Rechenzeit erheblich erhöht, ohne irgendeinen Vorteil zu generieren.
Ein höherer Wert für die Auflösung Resolution beschleunigt die Fusion merklich.
Das Verwenden von Punktnormalen anstelle von Dreiecken beschleunigt die Ausführung. Sollten beide Attribute vorhanden sein, werden als Standardeinstellung Punktnormalen verwendet.
Die Eingabe-Punktwolken können ausgedünnt werden ,entweder mittels sample_object_model_3d (falls Punktnormalen verwendet werden) oder mittels simplify_object_model_3d mit 'true' für den Parameter GenParamName 'avoid_triangle_flips' (bei Verwendung von Dreiecken).
Unnötig große Werte für MinThickness und GenParamName 'distance_in_front' können die Vorbereitung und die Distanzberechnung verlangsamen.
Wenn ein 3D-Objektmodell überschrieben werden soll oder nicht länger benötigt wird, muss der Speicher durch Aufrufen des Operators clear_object_model_3d freigegeben werden.
Handle eines 3D-Objektmodells.
Zwei gegenüberliegende Ecken des umschließenden Quaders.
Verwendete Auflösung innerhalb des umschließenden Quaders.
Defaultwert: 1.0
Wertevorschläge: 1.0, 1.1, 1.5, 10.0, 100.0
Distanz des erwarteten Rauschens zur Oberfläche.
Defaultwert: 1.0
Wertevorschläge: 1.0, 1.1, 1.5, 10.0, 100.0
Minimale Dicke des Objekts in Richtung Normale zur Oberfläche.
Defaultwert: 1.0
Wertevorschläge: 1.0, 1.1, 1.5, 10.0, 100.0
Gewichtungsfaktor zur Datentreue.
Defaultwert: 1.0
Wertevorschläge: 1.0, 1.1, 1.5, 10.0, 100.0
Richtung der Normalen im Eingabe-Modell.
Defaultwert: 'inwards'
Werteliste: 'inwards', 'outwards'
Name des generischen Parameters.
Defaultwert: []
Werteliste: 'angle_threshold', 'distance_in_front', 'point_meshing'
Wert des generischen Parameters.
Defaultwert: []
Wertevorschläge: 'isosurface', 'none', 0.0, 0.1, 0.175, 0.524
Handle des fusionierten 3D-Objektmodelles.
fuse_object_model_3d liefert den Wert 2 (H_MSG_TRUE) wenn alle Parameter korrekt sind. Andernfalls wird eine Fehlerbehandlung durchgeführt.
read_object_model_3d, register_object_model_3d_pair, register_object_model_3d_global, surface_normals_object_model_3d, triangulate_object_model_3d, simplify_object_model_3d, get_object_model_3d_params
write_object_model_3d, create_surface_model
C. Zach, T. Pock, and H. Bischof: „A globally optimal algorithm for robust TV-L1 range image integration.“ Proceedings of IEEE International Conference on Computer Vision (ICCV 2007).
3D Metrology
| Operatoren |