Locate Edge

In diesem Beispiel wird

Erläuterung

Innerhalb eines Suchfensters können Kanten mit der Funktion F_VN_LocateEdge lokalisiert werden. Zur einfacheren Anwendung sind einige Parameter dabei festgesetzt. Alternativ steht mit der hier verwendeten Funktion F_VN_LocateEdgeExp ein voller Zugriff auf alle Parameter zur Verfügung. Dieses Beispiel soll dabei helfen die einzelnen Parameter besser zu verstehen. Probieren Sie daher neben der Standardkonfiguration auch Konfigurationsänderungen aus und betrachten Sie die Auswirkungen auf das Kantenergebnis und auf die Verarbeitungszeit. Eine Auswahl von Konfigurationsänderungen inkl. Beschreibung finden Sie unter Ergebnisse.

Variablen

hr              : HRESULT;
hrFunc          : HRESULT;

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

// result
ipEdgePoints    : ITcVnContainer;

// parameters
aStartPoint     : TcVnPoint2_REAL := [850, 400];
aEndPoint       : TcVnPoint2_REAL := [550, 400];
eDirection      : ETcVnEdgeDirection := TCVN_ED_DARK_TO_LIGHT;
fMinStrength    : REAL := 50;
nSearchLines    : UDINT := 31;
fSearchLineDist : REAL := 1;
nMaxThickness   : UDINT := 7;
nSubpixIter     : UDINT := 10;
eAlgorithm      : ETcVnEdgeDetectionAlgorithm := TCVN_EDA_INTERPOLATION;
fAvgStrength    : REAL;

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

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

Code

hrWD := F_VN_StartRelWatchdog(tStop, hr);
   hrFunc := F_VN_LocateEdgeExp(
                  ipSrcImage             :=   ipImageIn,
                  ipEdgePoints           :=   ipEdgePoints,
                  aStartPoint            :=   aStartPoint,
                  aEndPoint              :=   aEndPoint,
                  eEdgeDirection         :=   eDirection,
                  fMinStrength           :=   fMinStrength,
                  nSearchLines           :=   nSearchLines,
                  fSearchLineDist        :=   fSearchLineDist
                  nMaxThickness          :=   nMaxThickness,
                  nSubpixelsIterations   :=   nSubpixIter,
                  fApproxPrecision       :=   0.0001,
                  eAlgorithm             :=   eAlgorithm,
                  hrPrev                 :=   hr,
                  fAvgStrength           =>   fAvgStrength);
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);
sText := CONCAT('Returncode ', DINT_TO_STRING(hrFunc));
hr := F_VN_PutTextExp(sText, ipImageRes, 25, 150, TCVN_FT_HERSHEY_SIMPLEX, 1.3, aColorGreen, 2, TCVN_LT_8_CONNECTED, FALSE,hr);
hr := F_VN_DrawPoint(REAL_TO_UDINT(aStartPoint[0]), REAL_TO_UDINT(aStartPoint[1]), ipImageRes, TCVN_DS_CIRCLE, aColorRed, hr);
hr := F_VN_DrawPoint(REAL_TO_UDINT(aEndPoint[0]), REAL_TO_UDINT(aEndPoint[1]), ipImageRes, TCVN_DS_X, aColorRed, hr);
hr := F_VN_FitLine(ipEdgePoints, aLine, hr);
hr := F_VN_DrawLine_TcVnVector4_LREAL(aLine, ipImageRes, aColorGreen, 2, hr);
hr := F_VN_DrawPointsExp(ipEdgePoints, ipImageRes, TCVN_DS_PLUS, aColorBlue, 1, 1, TCVN_LT_8_CONNECTED, hr);

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

Ergebnisse

Zur Visualisierung werden die gefundenen Kantenpunkte in blau und eine Ausgleichsgerade in grün in das Ausgabebild gezeichnet. Zudem werden der Startpunkt (roter Kreis) und der Endpunkt (rotes X) eingezeichnet. Oben links werden der Bearbeitungsanteil, die benötigte Ausführungszeit und der Rückgabewert der Funktion angezeigt.
Für die vorgegebenen Parameter sieht das Ergebnis folgendermaßen aus:

Locate Edge 1:

Wird nun die Anzahl der Suchlinien mit dem Parameter nSearchLines von 31 auf 61 erhöht, verdoppelt sich auch die benötigte Rechenzeit. Die Ausgleichsgerade wird im Gegenzug aber auch genauer:

Locate Edge 2:

Soll anstelle der Außenkante des Bauteils die Kante der Fräsung auf dem Bauteil gefunden werden, muss der Parameter eDirection auf TCVN_ED_LIGHT_TO_DARK geändert werden. Dadurch wird der äußere Kantenübergang von dunkel nach hell ignoriert und stattdessen die nachfolgende Kante mit dem Übergang hell nach dunkel gefunden:

Locate Edge 3:

Ausführungszeit reduzieren

Hierbei fällt auf, dass die Ausführungszeit trotz ansonsten identischer Parameter höher ist als beim Lokalisieren der äußeren Kante. Das liegt daran, dass die gefundene Kante weiter vom Startpunkt entfernt liegt.

Im Umkehrschluss heißt das auch, dass die Ausführungszeit bei einem festen Suchfenster je nach Position des Bauteils im Bild etwas schwankt, was sich auch gut bei den drei Beispielbildern beobachten lässt.

Ein noch größeres Schwanken kann bei den beiden Approximierungsalgorithmen auftreten, da diese unterschiedlich viele Iterationen benötigen, um die Modellparameter mittels der umliegenden Pixelintensitäten zu approximieren.

Generell werden weniger Iterationen benötigt, wenn die Suchlinien des Suchfensters möglichst orthogonal auf die Kante treffen. Falls die Position und Orientierung der Objekte im Bild keinen oder nur geringen Schwankungen unterliegen, richten Sie das Suchfenster entsprechend aus, um kürzere Ausführungszeiten zu erreichen. Zudem lässt sich die maximal benötigte Zeit reduzieren, indem die maximale Anzahl an Iterationen verringert wird, was aber ggf. auch ungenauere Ergebnisse liefert.

Watchdog nutzen

Zudem kann die Zeit auch mit einem Watchdog von außen begrenzt werden, der die Ausführung der Funktion bei Bedarf abbricht und die vorhandenen Teilergebnisse zurückliefert. Wird zum Beispiel der Algorithmus auf TCVN_EDA_APPROX_ERF geändert und die maximale Anzahl Iterationen auf 60 festgelegt, benötigt die Ausführung für das Bild LocateEdge2.bmp (Außenkante orthogonal zu den Suchlinien) ziemlich genau 4ms (abhängig von der verbauten CPU), wohingegen die anderen beiden Bilder 4.3 bzw. 4.4 ms benötigen. Setzt man nun den Parameter tStop auf 4000, wird die Ausführung der Funktion nach 4ms zum nächst möglichen Zeitpunkt gestoppt und die bis dahin vorhandenen Teilergebnisse zurückgeliefert. Daher wird die Funktion auf dem Bild LocateEdge2.bmp weiterhin zu 100% bearbeitet, wohingegen bei den anderen beiden Bildern (hier LocateEdge3.bmp) vorzeitig abgebrochen wird:

Locate Edge 4:

Da nur an bestimmten Punkten im Algorithmus abgebrochen werden kann und die Teilergebnisse (bisher gefundene Kantenpunkte auf den Suchlinien) zurückgeliefert werden, wird die Funktion nicht nach exakt 4000µs beendet, 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.

Trotz des Abbruchs reichen die Teilergebnisse aus, um das gewünschte Ergebnis zu erzielen, da lediglich die Resultate von ein oder zwei Suchlinien fehlen.

Ähnliche Beispiele