Selbstgeschriebene Funktionen

In diesem Beispiel wird erklärt, worauf beim Schreiben von eigenen Funktionen für Vision-Applikationen zu achten ist. Dabei geht es im Wesentlichen um:

Selbstgeschriebene Funktionen 1:

Auch andere Strukturen

Diese Funktionsimplementierung ist an die Struktur der TwinCAT Vision API-Funktionen angelehnt. Es sind auch andere Strukturen denkbar, achten Sie jedoch auf die hier erklärten Punkte.

Selbstgeschriebene Funktionen 2:

Auch Methoden

In diesem Beispiel wird eine Funktion beschrieben. Es ist jedoch in gleichem Maße für Methoden gültig.

Dazu wird beispielhaft eine selbst geschriebene Funktion zum Zählen und Malen von Objekten betrachtet:

FUNCTION F_CountAndDrawObjects : HRESULT

Deklarationsteil

Die Attribute der Funktion sind wie folgt im VAR_INPUT-Teil deklariert. Das Ursprungsbild wird direkt als ITcVnImage übergeben. Da in einer Funktion oder Methode keine Variablenwerte gespeichert werden, muss in diesem Fall nichts weiter beachtet werden. Hingegen wird das Ergebnisbild als REFERENCE TO ITcVnDisplayableImage übergeben, da es in der Funktion erstellt wird und nach außen zur weiteren Verarbeitung zurückgegeben werden soll. Hier wird aufgrund der Reference also keine Kopie des Interface Pointers erstellt.

VAR_INPUT
    ipSrcImage          :   ITcVnImage;
    ipDestImage         :   REFERENCE TO ITcVnImage;
    aColor              :   TcVnVector4_LREAL;
    nNumberOfObjects    :   REFERENCE TO ULINT;
    hrPrev              :   HRESULT;
END_VAR

Zudem werden einige Hilfsvariablen im VAR deklariert, die intern von der Funktion benötigt werden.

VAR
    hr                  :   HRESULT;
    ipContours          :   ITcVnContainer;
    stParams            :   TcVnParamsBlobDetection;
END_VAR

Eingangsprüfungen

Am Anfang der Funktion werden einige Eingangsprüfungen durchgeführt, um sicherzustellen, dass die Funktion ordnungsgemäß ausgeführt werden kann.

Zunächst wird mittels FAILED(hrPrev) überprüft, ob in der bisherigen Verarbeitungskette ein Fehler aufgetreten ist. Wenn dies der Fall ist, wird derselbe Fehler zurückgegeben und die Funktion direkt beendet.

IF FAILED(hrPrev) THEN
    F_CountAndDrawObjects := hrPrev;
    RETURN;
END_IF

Ebenfalls wird überprüft, ob alle Interface Pointer, die als VAR_INPUT an die Funktion übergeben werden, valide sind. Anderenfalls kann die Funktion nämlich nichts damit anfangen und gibt als Return Code INVALIDPARM zurück.

IF ipSrcImage = 0 THEN
    F_CountAndDrawObjects := Tc2_System.E_HRESULTAdsErr.INVALIDPARM;
    RETURN;
END_IF

Sofern alle Eingangsprüfungen erfolgreich waren, müssen z. B. bei Funktionsblöcken noch die Referenzzähler aller als VAR_INPUT übergebenen Interface Pointer inkrementiert werden. Denn durch das Übergeben des Interface Pointers wird eine Kopie erstellt, die nach dem Ausführen des Bausteins erhalten bleiben und daher im Referenzzähler abgebildet werden müssen. Die Methode TcAddRef kann direkt ohne vorherige <> 0 Prüfung ausgeführt werden, da dies schon während der Eingangsprüfungen geschehen ist. Wie schon im Deklarationsteil beschrieben, ist das Erhöhen des Referenzzählers bei Funktionen und Metthoden nicht notwendig, da die Variablenwerte wie in diesem Fall die Pointer-Adresse nach der Ausführung nicht erhalten bleiben.

Hauptverarbeitung

Im Hauptteil der Funktion steht der tatsächliche Bildverarbeitungsablauf. Dieser ist hier nur beispielhaft und wird nicht weiter betrachtet. Der Aufruf von F_VN_ConvertColorSpace verdeutlicht, dass Interface Pointer, die zum Zwecke der Ergebnisrückgabe als REFERENCE TO übergeben werden, direkt von TwinCAT Vision API-Funktionen beschrieben werden können.

hr := F_VN_ConvertColorSpace(ipSrcImage, ipDestImage, TCVN_CST_GRAY_TO_RGB, hr);
stParams.bFilterByArea := TRUE;
stParams.fMinArea := 10_000;
stParams.fMaxArea := 100_000;
hr := F_VN_DetectBlobs(ipSrcImage, ipContours, stParams, hr);
hr := F_VN_GetNumberOfElements(ipContours, nNumberOfObjects, hr);
hr := F_VN_DrawContours(ipContours, -1, ipDestImage, aColor, 5, hr);

Durch diesen Bildverarbeitungsablauf werden Objekte im Ergebnisbild gemalt und ihre Anzahl als ULINT zurückgegeben:

Ursprungsbild

Ergebnisbild

Selbstgeschriebene Funktionen 3:

Selbstgeschriebene Funktionen 4:

Anzahl gefundener Objekte: 4

 

Aufräumen und Rückgabe

Nach dem eigentlichen Bildverarbeitungsablauf müssen die Interface Pointer, die innerhalb der Funktion deklariert sind, wieder freigegeben werden. Dies ist der Fall, weil alle in der Funktion deklarierten Variablen (also auch die Interface Pointer) nach Beenden der Funktion gelöscht werden. Wenn im Hintergrund nun noch Daten vorhanden wären, die noch nicht freigegeben sind, entständen Speicher-Lecks.

FW_SafeRelease(ADR(ipContours));

Schließlich wird das HRESULT als Rückgabewert der Funktion zugewiesen, um eventuelle Fehler nach außen zu melden. Damit es nicht verfälscht wird, sollten die Rückgabewerte der FW_SafeRelease Funktionen nicht dem HRESULT zugewiesen werden.

F_CountAndDrawObjects := hr;