get_rectangle_poseT_get_rectangle_poseGetRectanglePoseGetRectanglePose (Operator)

Name

get_rectangle_poseT_get_rectangle_poseGetRectanglePoseGetRectanglePose — Bestimmen der 3D-Lage (Pose) eines Rechtecks aus seiner perspektivischen Projektion in 2D.

Signatur

get_rectangle_pose(Contour : : CameraParam, Width, Height, WeightingMode, ClippingFactor : Pose, CovPose, Error)

Herror T_get_rectangle_pose(const Hobject Contour, const Htuple CameraParam, const Htuple Width, const Htuple Height, const Htuple WeightingMode, const Htuple ClippingFactor, Htuple* Pose, Htuple* CovPose, Htuple* Error)

void GetRectanglePose(const HObject& Contour, const HTuple& CameraParam, const HTuple& Width, const HTuple& Height, const HTuple& WeightingMode, const HTuple& ClippingFactor, HTuple* Pose, HTuple* CovPose, HTuple* Error)

HPoseArray HXLD::GetRectanglePose(const HCamPar& CameraParam, const HTuple& Width, const HTuple& Height, const HString& WeightingMode, double ClippingFactor, HTuple* CovPose, HTuple* Error) const

HPose HXLD::GetRectanglePose(const HCamPar& CameraParam, double Width, double Height, const HString& WeightingMode, double ClippingFactor, HTuple* CovPose, HTuple* Error) const

HPose HXLD::GetRectanglePose(const HCamPar& CameraParam, double Width, double Height, const char* WeightingMode, double ClippingFactor, HTuple* CovPose, HTuple* Error) const

HPose HXLD::GetRectanglePose(const HCamPar& CameraParam, double Width, double Height, const wchar_t* WeightingMode, double ClippingFactor, HTuple* CovPose, HTuple* Error) const   (Nur Windows)

HPoseArray HCamPar::GetRectanglePose(const HXLD& Contour, const HTuple& Width, const HTuple& Height, const HString& WeightingMode, double ClippingFactor, HTuple* CovPose, HTuple* Error) const

HPose HCamPar::GetRectanglePose(const HXLD& Contour, double Width, double Height, const HString& WeightingMode, double ClippingFactor, HTuple* CovPose, HTuple* Error) const

HPose HCamPar::GetRectanglePose(const HXLD& Contour, double Width, double Height, const char* WeightingMode, double ClippingFactor, HTuple* CovPose, HTuple* Error) const

HPose HCamPar::GetRectanglePose(const HXLD& Contour, double Width, double Height, const wchar_t* WeightingMode, double ClippingFactor, HTuple* CovPose, HTuple* Error) const   (Nur Windows)

static void HOperatorSet.GetRectanglePose(HObject contour, HTuple cameraParam, HTuple width, HTuple height, HTuple weightingMode, HTuple clippingFactor, out HTuple pose, out HTuple covPose, out HTuple error)

HPose[] HXLD.GetRectanglePose(HCamPar cameraParam, HTuple width, HTuple height, string weightingMode, double clippingFactor, out HTuple covPose, out HTuple error)

HPose HXLD.GetRectanglePose(HCamPar cameraParam, double width, double height, string weightingMode, double clippingFactor, out HTuple covPose, out HTuple error)

HPose[] HCamPar.GetRectanglePose(HXLD contour, HTuple width, HTuple height, string weightingMode, double clippingFactor, out HTuple covPose, out HTuple error)

HPose HCamPar.GetRectanglePose(HXLD contour, double width, double height, string weightingMode, double clippingFactor, out HTuple covPose, out HTuple error)

Beschreibung

Ein Rechteck im Raum wird als ein allgemeines Viereck in Bild projiziert. get_rectangle_poseget_rectangle_poseGetRectanglePoseGetRectanglePoseGetRectanglePose bestimmt die 3D-Lage (PosePosePosePosepose) des Rechtecks aus seiner Projektionskontur (ContourContourContourContourcontour).

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 (CameraParamCameraParamCameraParamCameraParamcameraParam) und die Größe des Rechtecks in Meter(WidthWidthWidthWidthwidth, HeightHeightHeightHeightheight) werden für die Bestimmung der Initialpose verwendet. Die PosePosePosePosepose 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 CameraParamCameraParamCameraParamCameraParamcameraParam eine Lochkamera mit Zeilensensor oder eine telezentrische Kamera darstellt (siehe Kalibrierung), wird ein Fehler geliefert.

WidthWidthWidthWidthwidth und HeightHeightHeightHeightheight 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 WeightingModeWeightingModeWeightingModeWeightingModeweightingMode und ClippingFactorClippingFactorClippingFactorClippingFactorclippingFactor können verwendet werden, um die Einwirkung von Ausreißern im Algorithmus zu vermindern. Wenn WeightingModeWeightingModeWeightingModeWeightingModeweightingMode 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 ClippingFactorClippingFactorClippingFactorClippingFactorclippingFactor (Skalierungsfaktor für die Standardabweichung) kontrolliert das Dämpfen von Ausreißern: Je kleiner der Wert von ClippingFactorClippingFactorClippingFactorClippingFactorclippingFactor ist, desto mehr Ausreißer werden erkannt. Siehe fit_line_contour_xldfit_line_contour_xldFitLineContourXldFitLineContourXldFitLineContourXld für eine Diskussion über die Eigenschaften der verschiedenen Verfahren. Bitte beachten Sie, dass hier, zum Unterschied von fit_line_contour_xldfit_line_contour_xldFitLineContourXldFitLineContourXldFitLineContourXld, das Verfahren von Huber empfohlen wird.

Ausgabe

Die gelieferte PosePosePosePosepose hat Code-0 (siehe create_posecreate_poseCreatePoseCreatePoseCreatePose) und stellt die Position des Mittelpunkts des Rechtecks dar. Die Positionen der Eckpunkte des Rechtecks kann man wie folgt berechnen: set_origin_pose (PosePosePosePosepose, WidthWidthWidthWidthwidth/2, -HeightHeightHeightHeightheight/2, 0, PoseCorner1) set_origin_pose (PosePosePosePosepose, WidthWidthWidthWidthwidth/2, HeightHeightHeightHeightheight/2, 0, PoseCorner2) set_origin_pose (PosePosePosePosepose, -WidthWidthWidthWidthwidth/2, HeightHeightHeightHeightheight/2, 0, PoseCorner3) set_origin_pose (PosePosePosePosepose, -WidthWidthWidthWidthwidth/2, -HeightHeightHeightHeightheight/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 PosePosePosePosepose 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_poseget_rectangle_poseGetRectanglePoseGetRectanglePoseGetRectanglePose zurückgeliefert * * flip around z-axis PoseFlippedZ := PosePosePosePosepose PoseFlippedZ[5] := PoseFlippedZ[5]+180 * flip around y-axis PoseFlippedY := PosePosePosePosepose PoseFlippedY[4] := PoseFlippedY[4]+180 PoseFlippedY[5] := -PoseFlippedY[5] * flip around x-axis PoseFlippedX := PosePosePosePosepose PoseFlippedX[3] := PoseFlippedX[3]+180 PoseFlippedX[4] := -PoseFlippedX[4] PoseFlippedX[5] := -PoseFlippedX[5] Wenn das Rechteck ein Quadrat ist (WidthWidthWidthWidthwidth == HeightHeightHeightHeightheight), dann ist die Anzahl der möglichen Posen 8.

Wenn mehr als eine Kontur in ContourContourContourContourcontour übergeben wird, dann muss ein entsprechend großes Tupel von Werten auch in WidthWidthWidthWidthwidth und bzw. HeightHeightHeightHeightheight ü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 PosePosePosePosepose hintereinander gehängt zurückgeliefert (siehe das Beispiel).

Genauigkeit der Pose

Die Genauigkeit der berechneten PosePosePosePosepose 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 WidthWidthWidthWidthwidth/HeightHeightHeightHeightheight 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_poseget_rectangle_poseGetRectanglePoseGetRectanglePoseGetRectanglePose liefert zwei Maße für die Genauigkeit der bestimmten PosePosePosePosepose. ErrorErrorErrorErrorerror ist der durchschnittliche Pixelabstand zwischen den Konturpunkten und dem rückprojizierten Rechteck. Falls ErrorErrorErrorErrorerror den Wert von 0.5 überschreitet, hat der Algorithmus nicht richtig konvergiert. In diesem Fall sollte die gelieferte PosePosePosePosepose nicht verwendet werden. CovPoseCovPoseCovPoseCovPosecovPose 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 (CovPoseCovPoseCovPoseCovPosecovPose[21], CovPoseCovPoseCovPoseCovPosecovPose[28], CovPoseCovPoseCovPoseCovPosecovPose[22] und CovPoseCovPoseCovPoseCovPosecovPose[28]). Erhöhte Werte von allen anderen Kovarianzen und insbesondere von den Varianzen (die 6 Diagonalwerten von CovPoseCovPoseCovPoseCovPosecovPose mit Index 0, 7, 14, 21, 28 und 35) deuten ebenfalls auf eine schlechte Qualität der bestimmten PosePosePosePosepose.

Ausführungsinformationen

Parameter

ContourContourContourContourcontour (input_object)  xld(-array) objectHXLDHXLDHobject

Zu untersuchende Konturen.

CameraParamCameraParamCameraParamCameraParamcameraParam (input_control)  campar HCamPar, HTupleHTupleHtuple (real / integer / string) (double / int / long / string) (double / Hlong / HString) (double / Hlong / char*)

Interne Kameraparameter.

WidthWidthWidthWidthwidth (input_control)  number(-array) HTupleHTupleHtuple (real) (double) (double) (double)

Breite des Rechtecks in Meter.

Restriktion: Width > 0

HeightHeightHeightHeightheight (input_control)  number(-array) HTupleHTupleHtuple (real) (double) (double) (double)

Höhe des Rechtecks im Meter.

Restriktion: Height > 0

WeightingModeWeightingModeWeightingModeWeightingModeweightingMode (input_control)  string HTupleHTupleHtuple (string) (string) (HString) (char*)

Gewichtungsart für die Optimierungsphase.

Defaultwert: 'nonweighted' "nonweighted" "nonweighted" "nonweighted" "nonweighted"

Werteliste: 'huber'"huber""huber""huber""huber", 'nonweighted'"nonweighted""nonweighted""nonweighted""nonweighted", 'tukey'"tukey""tukey""tukey""tukey"

ClippingFactorClippingFactorClippingFactorClippingFactorclippingFactor (input_control)  number HTupleHTupleHtuple (real) (double) (double) (double)

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

PosePosePosePosepose (output_control)  pose(-array) HPose, HTupleHTupleHtuple (real / integer) (double / int / long) (double / Hlong) (double / Hlong)

3D-Lage (Pose) des Rechtecks

Parameteranzahl: Pose == 7 * Contour

CovPoseCovPoseCovPoseCovPosecovPose (output_control)  number-array HTupleHTupleHtuple (real) (double) (double) (double)

Kovarianzen der 6 Posewerte.

Parameteranzahl: CovPose == 36 * Contour

ErrorErrorErrorErrorerror (output_control)  number-array HTupleHTupleHtuple (real) (double) (double) (double)

Durchschnittsabstand zwischen dem rückprojizierten Rechteck und der Kontur.

Parameteranzahl: Error == Contour

Beispiel (HDevelop)

* 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

Ergebnis

Sind die Parameterwerte korrekt und konnte die Position des Rechtecks bestimmt werden, dann liefert get_rectangle_poseget_rectangle_poseGetRectanglePoseGetRectanglePoseGetRectanglePose den Wert 2 (H_MSG_TRUE). Falls die übergebene Kontur nicht wie ein Viereck segmentiert werden kann, liefert get_rectangle_poseget_rectangle_poseGetRectanglePoseGetRectanglePoseGetRectanglePose den Wert H_ERR_FIT_QUADRANGLE. Gegebenenfalls wird eine weiter Fehlerbehandlung durchgeführt.

Vorgänger

edges_sub_pixedges_sub_pixEdgesSubPixEdgesSubPixEdgesSubPix

Siehe auch

get_circle_poseget_circle_poseGetCirclePoseGetCirclePoseGetCirclePose, set_origin_poseset_origin_poseSetOriginPoseSetOriginPoseSetOriginPose, camera_calibrationcamera_calibrationCameraCalibrationCameraCalibrationCameraCalibration

Literatur

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

Modul

3D Metrology