Self-written functions

This sample explains what needs to be observed when writing your own functions for Vision applications. It essentially concerns:

Self-written functions 1:

Other structures too

This function implementation is based on the structure of the TwinCAT Vision API functions. Other structures are also conceivable, but please pay attention to the points explained here.

Self-written functions 2:

Methods too

In this sample a function is described. However, it applies equally to methods.

For this purpose, by way of example, a self-written function for the counting and painting of objects is considered:

FUNCTION F_CountAndDrawObjects : HRESULT

Declaration part

The attributes of the function are declared as follows in the VAR_INPUT part. The original image is transferred directly as ITcVnImage. Since no variable values are stored in a function or method, nothing else needs to be observed in this case. On the other hand, the result image is passed as REFERENCE TO ITcVnDisplayableImage, since it is created in the function and is to be returned externally for further processing. In this case, no copy of the interface pointer is created due to the reference.

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

In addition, some auxiliary variables required internally by the function are declared in the VAR.

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

Input checks

At the start of the function, some input checks are performed in order to ensure that the function can be executed properly.

Initially, FAILED(hrPrev) is used to check whether an error has occurred in the previous processing chain. If so, the same error is displayed and the function is ended directly.

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

A check is also performed to ascertain whether all interface pointers that are transferred to the function as VAR_INPUT are valid. Otherwise the function cannot do anything with them and returns INVALIDPARM as the return code.

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

If all input checks were successful, the reference counter of all interface pointers transferred as VAR_INPUT must be incremented, because due to the transfer of the interface pointer a copy is created that is retained after the function block is executed and has to be mapped in the reference counter. The method TcAddRef can be executed here directly without a prior <> 0 check, as this has already taken place during the input checks. As already described in the declaration part, incrementing the reference counter is not necessary for functions and methods, because the variable values, like in this case the pointer address, are not preserved after execution.

Main processing

The actual image processing sequence is located in the main part of the function. This is only an example here and will not be considered any further. The call of F_VN_ConvertColorSpace illustrates that interface pointers, which are transferred as REFERENCE TO for the purpose of the result return, can be written directly by TwinCAT Vision API functions.

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);

By means of this image processing sequence, objects are painted in the result image and their quantity returned as ULINT:

Original image

Result image

Self-written functions 3:

Self-written functions 4:

Number of objects found: 4

 

Tidy up and return

Following the actual image processing sequence, the interface pointers declared within the function are released again. This is the case because all variables declared in the function (i.e. the interface pointers too) are deleted after ending the function. If there are still data in the background that have not yet been released, this will lead to memory leaks.

FW_SafeRelease(ADR(ipContours));

Finally, the HRESULT is assigned to the function as the return value in order to report any errors to the outside. So that it is not falsified, the return values of the FW_SafeRelease functions should not be assigned to the HRESULT.

F_CountAndDrawObjects := hr;