Locate Ellipse

In diesem Beispiel wird

Erläuterung

Für ein Grundverständnis der Vermessungsfunktionen und deren Parameter sehen Sie sich zuerst das Locate Edge Beispiel an. Die Funktion F_VN_LocateEllipseExp unterscheidet sich von der Funktion F_VN_LocateEdgeExp dadurch, dass sie ein kreisförmiges statt rechteckiges Suchfenster verwendet. In diesem Beispiel ist ein großes, ungenaues Suchfenster parametriert, da sich in diesem Beispiel die Position der kreisförmigen Objekte etwas ändert. So können mit dem gleichen Suchfenster in allen Bildern die Kreise bestimmt werden.

Mit dem Parameter bInvertSearchDirection - der in diesem Beispiel auf TRUE gesetzt wurde - ist definiert worden, dass die Suchrichtung umgekehrt wird, d. h. von außen in Richtung aCenter. Das ist notwendig, da sich in den Beispielbildern innerhalb der gesuchten Ellipse ebenfalls Kanten befinden.

Da in diesem Beispiel die Objekte dunkler sind als der Hintergrund, wurde die Suchrichtung auf TCVN_ED_LIGHT_TO_DARK festgelegt.

Der Parameter nMaxThickness, der definiert, innerhalb von wie vielen Pixeln fMinStrength erreicht werden muss, wurde auf den Wert „7“ gesetzt.

Variablen

hr              : HRESULT;
hrFunc          : HRESULT;

ipImageIn       : ITcVnImage;
ipImageInDisp   : ITcVnDisplayableImage;
ipImageRes      : ITcVnImage;
ipImageResDisp  : ITcVnDisplayableImage;

// result
stEllipse       : TcVnRotatedRectangle;
ipContourPoints : ITcVnContainer;

// input parameters
aCenter         : TcVnPoint2_REAL := [650, 400];
fRadius         : REAL := 300;
fMinRadius      : REAL := 100;
fMinStrength    : REAL := 30;
nSubPixIter     : UDINT := 10;
nSearchLines    : UDINT := 40;
eAlgorithm      : ETcVnEdgeDetectionAlgorithm := TCVN_EDA_INTERPOLATION;

// Watchdog
hrWD            : HRESULT;
tStop           : DINT := 15000;
tRest           : DINT;
nFraction       : UDINT;

// drawing
aColorRed       : TcVnVector4_LREAL := [200, 0, 0];
aColorGreen     : TcVnVector4_LREAL := [0, 175, 0];
sText           : STRING(255);

Code

hrWD := F_VN_StartRelWatchdog(tStop, hr);
   hrFunc := F_VN_LocateEllipseExp(
             ipSrcImage               :=   ipImageIn,
             stEllipse                :=   stEllipse,
             aCenterPoint             :=   aCenter,
             fSearchRadius            :=   fRadius,
             eEdgeDirection           :=   TCVN_ED_LIGHT_TO_DARK,
             fMinStrength             :=   fMinStrength,
             nMaxThickness            :=   7,
             bInvertSearchDirection   :=   TRUE,
             fMinSearchRadius         :=   fMinRadius,
             nSubpixelsIterations     :=   nSubpixIter,
             nSearchLines             :=   nSearchLines,
             fApproxPrecision         :=   0.0001,
             eAlgorithm               :=   eAlgorithm,
             ipContourPoints          :=   ipContourPoints,
             hrPrev                   :=   hr);
hrWD := F_VN_StopWatchdog(hrWD, nFractionProcessed=>nFraction, tRest=>tRest);

// Draw result for visualization
hr := F_VN_ConvertColorSpace(ipImageIn, ipImageRes, TCVN_CST_GRAY_TO_RGB, hr);
sText := CONCAT(CONCAT('Processed ', UDINT_TO_STRING(nFraction)), '%');
hr := F_VN_PutTextExp(sText, ipImageRes, 25, 50, TCVN_FT_HERSHEY_SIMPLEX, 1.3, aColorGreen, 2, TCVN_LT_8_CONNECTED, FALSE, hr);
sText := CONCAT(CONCAT('Time ', DINT_TO_STRING(tStop - tRest)), 'us');
hr := F_VN_PutTextExp(sText, ipImageRes, 25, 100, TCVN_FT_HERSHEY_SIMPLEX, 1.3, aColorGreen, 2, TCVN_LT_8_CONNECTED, FALSE,hr);
hr := F_VN_DrawCircle(REAL_TO_UDINT(aCenter[0]), REAL_TO_UDINT(aCenter[1]), REAL_TO_UDINT(fMinRadius), ipImageRes, aColorRed, 2, hr);
hr := F_VN_DrawCircle(REAL_TO_UDINT(aCenter[0]), REAL_TO_UDINT(aCenter[1]), REAL_TO_UDINT(fRadius), ipImageRes, aColorRed, 2, hr);
hr := F_VN_DrawPoints(ipContourPoints, ipImageRes, TCVN_DS_X, aColorGreen, hr);
hr := F_VN_DrawPoint(REAL_TO_UDINT(stEllipse.aCenter[0]), REAL_TO_UDINT(stEllipse.aCenter[1]), ipImageRes, TCVN_DS_PLUS, aColorGreen, hr);
hr := F_VN_DrawEllipse(stEllipse, ipImageRes, aColorGreen, 1, hr);

// Display source and result image
hr := F_VN_TransformIntoDisplayableImage(ipImageIn, ipImageInDisp, S_OK);
hr := F_VN_TransformIntoDisplayableImage(ipImageRes, ipImageResDisp, S_OK);

Ergebnisse

Die Funktion liefert die TcVnRotatedRectangle-Struktur stEllipse zurück, die die gefundene Ellipse anhand ihres Mittelpunkts aCenter, ihrer Höhe und Breite stSize.fHeight bzw. stSize.fWidth und ihres Winkels fAngle definiert.
Optional kann zusätzlich ein Kantenpunkt pro Suchlinie ipContourPoints zurückgegeben werden, aus denen die Ellipse approximiert wurde.

Zur Visualisierung wird zunächst der Suchbereich durch 2 rote Kreise um den vorgegebenen Mittelpunkt ins Bild eingezeichnet. Die gefundene Ellipse wird als grüne Linie eingezeichnet und der zugehörige Mittelpunkt als grünes „+“. Die einzelnen Messpunkte aus ipContourPoints werden als grüne x eingezeichnet. Zudem stehen oben links der Bearbeitungsanteil und die benötigte Rechenzeit. Für die vorgegebenen Parameter sieht das Ergebnis für das Eingangsbild LocateEllipse_T.bmp folgendermaßen aus:

Locate Ellipse 1:

Erhöht man nun die Anzahl der Suchlinien von 40 auf 180, wird die benötigte Rechenzeit wie erwartet linear dazu erhöht:

Locate Ellipse 2:

Da die Rechenzeit in der Praxis je nach Eingangsbild etwas schwankt, ist es oftmals sinnvoll, die benötigte Rechenzeit von außen mittels Watchdog zu begrenzen. Setzt man z. B. die Anzahl der Suchlinien auf 120 und den Watchdog timeout tStop auf 2000 (abhängig von der verwendeten CPU), so wird die Funktion bei etwa 85% Bearbeitungsanteil abgebrochen und die bis dahin verfügbaren Teilergebnisse zurückgeliefert:

Locate Ellipse 3:

Da der Algorithmus nur an dezidierten Stellen unterbrochen werden und die Teilergebnisse zurückgegeben werden können, bricht die Funktion nicht exakt nach 2000µs ab, sondern benötigt etwas länger, was es bei der Wahl der Abbruchzeit zu berücksichtigen gilt. Die maximal zusätzlich benötigte Zeit ist generell abhängig von dem Algorithmus und der Parametrierung.
Obwohl aufgrund des Abbruchs die Ergebnisse einiger Suchlinien fehlen (4 größere Lücken zwischen den grünen x), konnte die Ellipse trotzdem korrekt approximiert werden, d. h. die Teilergebnisse können sinnvoll weiterverwendet werden, so als wäre die Funktion zu 100% abgearbeitet worden.

In begrenztem Maße ist dies ebenfalls möglich, wenn die Position eines Objekts zum Teil außerhalb des definierten Suchbereichs liegt, z. B. weil ein vorheriger Positionierungsschritt fehlerhaft war. Setzt man z. B. fMinRadius auf 180, so liegt bei einigen Beispielbildern ein Teil der Außenkontur außerhalb des vorgegebenen Bereichs. Trotzdem sind noch genügend Suchpunkte vorhanden, um daraus eine Ellipse zu approximieren. In der Praxis sollte man sich allerdings nicht darauf verlassen und den Suchbereich groß genug wählen:

Locate Ellipse 4:

Ähnliche Beispiele