get_rectangle_pose
— Bestimmen der 3D-Lage (Pose) eines Rechtecks aus seiner
perspektivischen Projektion in 2D.
get_rectangle_pose(Contour : : CameraParam, Width, Height, WeightingMode, ClippingFactor : Pose, CovPose, Error)
Ein Rechteck im Raum wird als ein allgemeines Viereck in Bild
projiziert. get_rectangle_pose
bestimmt die 3D-Lage
(Pose
) des Rechtecks aus seiner Projektionskontur
(Contour
).
Der Algorithmus arbeitet auf folgende Weise: Erst wird die Kontur in
vier Linien segmentiert und ihre Schnittpunkte werden als Eckpunkte
der Kontur genommen. Die Eckpunkte, die internen Kameraparameter
(CameraParam
) und die Größe des Rechtecks in
Meter(Width
, Height
) werden für die Bestimmung der
Initialpose verwendet. Die Pose
wird zum Schluss durch eine
nichtlineare Optimierung verfeinert, wobei der Abstand von den
Konturpunkten zu der Wiederprojektion des Rechtecks im Bild
minimiert wird.
Der Operator unterstützt nur (projektive) Lochkamera mit
Flächensensor. Falls CameraParam
eine Lochkamera mit
Zeilensensor oder eine telezentrische Kamera darstellt (siehe
Kalibrierung), wird ein Fehler geliefert.
Width
und Height
beschreiben die Größe des
Rechtecks in X- bzw. Y-Richtung in seinem Koordinatensystem. Der
Ursprung dieses Koordinatensystem liegt in dem Mittelpunkt des
Rechtecks. Die Z-Achse zeigt weg von der Kamera.
Die Parameter WeightingMode
und ClippingFactor
können verwendet werden, um die Einwirkung von Ausreißern im
Algorithmus zu vermindern. Wenn WeightingMode
auf 'tukey'
oder 'huber' gesetzt ist, werden die Konturpunkte nach den Verfahren
von Tukey bzw. Huber gewichtet. In diesem Fall wird die
Standardabweichung der Abstände der Konturpunkte zu dem
rückprojizierten Rechteck durch robuste Fehlerstatistik
bestimmt. Der Parameter ClippingFactor
(Skalierungsfaktor
für die Standardabweichung) kontrolliert das Dämpfen von Ausreißern:
Je kleiner der Wert von ClippingFactor
ist, desto mehr
Ausreißer werden erkannt. Siehe fit_line_contour_xld
für
eine Diskussion über die Eigenschaften der verschiedenen
Verfahren. Bitte beachten Sie, dass hier, zum Unterschied von
fit_line_contour_xld
, das Verfahren von Huber empfohlen
wird.
Die gelieferte Pose
hat Code-0 (siehe create_pose
)
und stellt die Position des Mittelpunkts des Rechtecks dar. Die
Positionen der Eckpunkte des Rechtecks kann man wie folgt berechnen:
set_origin_pose (Pose
, Width
/2, -Height
/2, 0, PoseCorner1)
set_origin_pose (Pose
, Width
/2, Height
/2, 0, PoseCorner2)
set_origin_pose (Pose
, -Width
/2, Height
/2, 0, PoseCorner3)
set_origin_pose (Pose
, -Width
/2, -Height
/2, 0, PoseCorner4)
Ein Rechteck ist symmetrisch um seine X-, Y- und Z-Achse und
deswegen kann eine viereckige Kontur ein Rechteck in 4 verschiedenen
Posen darstellen. Die Winkel in Pose
sind normalisiert, so
dass sie in dem Intervall [-90; 90] Grad liegen. Die 3
verbliebenen möglichen Posen können durch eine Kombination von
Umdrehungen, die von den folgenden Formel dargestellt sind,
berechnet werden:
* Achtung: Die folgende Code gilt nur für Pose von Code-0,
* wie von get_rectangle_pose
zurückgeliefert
*
* flip around z-axis
PoseFlippedZ := Pose
PoseFlippedZ[5] := PoseFlippedZ[5]+180
* flip around y-axis
PoseFlippedY := Pose
PoseFlippedY[4] := PoseFlippedY[4]+180
PoseFlippedY[5] := -PoseFlippedY[5]
* flip around x-axis
PoseFlippedX := Pose
PoseFlippedX[3] := PoseFlippedX[3]+180
PoseFlippedX[4] := -PoseFlippedX[4]
PoseFlippedX[5] := -PoseFlippedX[5]
Wenn das Rechteck ein Quadrat ist (Width
==
Height
), dann ist die Anzahl der möglichen Posen 8.
Wenn mehr als eine Kontur in Contour
übergeben wird, dann
muss ein entsprechend großes Tupel von Werten auch in Width
und bzw. Height
übergeben werden. Wird nur ein Wert für
jeweils beide Parameter übergeben, wird dieser Wert für alle
verarbeiteten Konturen verwendet. Für jede Kontur wird eine Pose
bestimmt und alle in Pose
hintereinander gehängt
zurückgeliefert (siehe das Beispiel).
Die Genauigkeit der berechneten Pose
hängt von den
folgenden Faktoren ab:
Um eine genaue Pose berechnen zu können, gibt es drei entsprechende Kriterien:
Erstens sollte das Seitenverhältnis
Width
/Height
die folgenden Beschränkungen
erfüllen:
Hat das Rechteck ein von dieser Regel abweichendes Seitenverhältnis,
dominieren seine längere Seite die Posebestimmung. Dabei entsteht
eine Instabilität bei der Bestimmung des Winkels um die längere
Achse des Rechtecks. Im Extremfall, in dem eine der Dimensionen des
Rechtecks gleich 0 ist, ist das Rechteck ein Liniensegment und seine
Lage kann nicht bestimmt werden.
Zweitens muss jede Konturseite mindestens 20 Pixel lang sein. Falls eine Seite weniger als 5 Pixel lang ist, wird ein Fehler geliefert.
Drittens, je mehr perspektivische Verzerrung bei der Projektion der Kontur auftritt, desto stabiler arbeitet der Algorithmus. Deswegen kann die Pose eines gekippten Rechtecks besser bestimmt werden als die Pose eines parallel zur Bildebene liegenden Rechtecks. Das wird weiter im nächsten Absatz diskutiert. Außerdem gilt die Faustregel, dass das Rechteck so im Raum positioniert sein soll, dass seine Größe in X- und Y-Kamerakoordinate nicht kleiner als 1/10tel seines Abstands von der Kamera in Z-Richtung sein darf.
get_rectangle_pose
liefert zwei Maße für die Genauigkeit der
bestimmten Pose
. Error
ist der durchschnittliche
Pixelabstand zwischen den Konturpunkten und dem rückprojizierten
Rechteck. Falls Error
den Wert von 0.5 überschreitet, hat
der Algorithmus nicht richtig konvergiert. In diesem Fall sollte die
gelieferte Pose
nicht verwendet werden. CovPose
enthält 36 Werte, die die 6×6 Kovarianzmatrix der
6 ersten Posewerte darstellen. Die oben genannte Instabilität des
Winkels um die längere Rechteckachse kann daran erkannt werden, dass
die Absolutwerte der (Ko-)Varianzen der Rotationen um die X-
bzw. Y-Achse größer als 0.05 sind (CovPose
[21],
CovPose
[28], CovPose
[22] und
CovPose
[28]). Erhöhte Werte von allen anderen Kovarianzen
und insbesondere von den Varianzen (die 6 Diagonalwerten von
CovPose
mit Index 0, 7, 14, 21, 28 und 35) deuten ebenfalls
auf eine schlechte Qualität der bestimmten Pose
.
Contour
(input_object) xld(-array) →
object
Zu untersuchende Konturen.
CameraParam
(input_control) campar →
(real / integer / string)
Interne Kameraparameter.
Width
(input_control) number(-array) →
(real)
Breite des Rechtecks in Meter.
Restriktion: Width > 0
Height
(input_control) number(-array) →
(real)
Höhe des Rechtecks im Meter.
Restriktion: Height > 0
WeightingMode
(input_control) string →
(string)
Gewichtungsart für die Optimierungsphase.
Defaultwert: 'nonweighted'
Werteliste: 'huber' , 'nonweighted' , 'tukey'
ClippingFactor
(input_control) number →
(real)
Abschnittsfaktor für das Dämpfen von Ausreißern (normalerweise: 1.0 für 'huber' und 3.0 für 'tukey').
Defaultwert: 2.0
Wertevorschläge: 1.0, 1.5, 2.0, 2.5, 3.0
Restriktion: ClippingFactor > 0
Pose
(output_control) pose(-array) →
(real / integer)
3D-Lage (Pose) des Rechtecks
Parameteranzahl: Pose == 7 * Contour
CovPose
(output_control) number-array →
(real)
Kovarianzen der 6 Posewerte.
Parameteranzahl: CovPose == 36 * Contour
Error
(output_control) number-array →
(real)
Durchschnittsabstand zwischen dem rückprojizierten Rechteck und der Kontur.
Parameteranzahl: Error == Contour
* Process an image with several rectangles of the same size appearing * as light objects. RectWidth := 0.04 RectHeight := 0.025 gen_cam_par_area_scan_division (0.014, 830, 4.58e-006, 4.65e-006, \ 509, 488, 800, 800, CameraParam) read_image (Image, 'barcode/ean13/tea_box_01') * Find light objects in the image. mean_image (Image, ImageMean, 201, 201) dyn_threshold (Image, ImageMean, Region, 5, 'light') * Fill gaps in the objects. fill_up (Region, RegionFillUp) * Extract rectangular contours. connection (RegionFillUp, ConnectedRegions) select_shape (ConnectedRegions, SelectedRegions, ['area','rectangularity'], \ 'and', [50000,0.9], [640000,1]) boundary (SelectedRegions, RegionBorder, 'inner') dilation_circle (RegionBorder, RegionDilation, 3.5) * NOTE: for a real application, this step might require some additional * pre- or postprocessing. reduce_domain (Image, RegionDilation, ImageReduced) edges_sub_pix (ImageReduced, Edges, 'canny', 1, 20, 40) * Get the pose of all contours found. get_rectangle_pose (Edges, CameraParam, RectWidth, RectHeight, 'huber', 2, \ Poses, CovPose, Error) NumPoses := |Poses|/7 for I := 0 to NumPoses-1 by 1 Pose := Poses[I*7:I*7+6] * Use the Pose here. * ... endfor
Sind die Parameterwerte korrekt und konnte die Position des
Rechtecks bestimmt werden, dann liefert get_rectangle_pose
den Wert 2 (H_MSG_TRUE). Falls die übergebene Kontur nicht wie ein Viereck
segmentiert werden kann, liefert get_rectangle_pose
den Wert
H_ERR_FIT_QUADRANGLE. Gegebenenfalls wird eine weiter
Fehlerbehandlung durchgeführt.
get_circle_pose
,
set_origin_pose
,
camera_calibration
G.Schweighofer and A.Pinz: „Robust Pose Estimation from a Planar Target“; Transactions on Pattern Analysis and Machine Intelligence (PAMI), 28(12):2024-2030, 2006
3D Metrology