Inner circle by means of distance transformation

In this sample you will find the inner circle of a misshapen object by means of distance transformation. For this purpose you essentially use the following functions:

Explanation

External contour approximations such as an enclosing rectangle or the convex envelope can be calculated via appropriate API functions. Conversely, an inner circle with a maximum size inside a contour can be found by means of a distance transformation.

Inner circle by means of distance transformation 1:

For this purpose, the point with the greatest Euclidean distance to the object edges is determined with a distance transformation. This point is then the center point of the inner circle of the object.

If you use this sample with your own images, you should adjust the threshold value and the binarization via the variables bInvert and fThreshold. By means of the parameters eDistanceType and eMaskSize you can purposefully change the parameters of the function F_VN_DistanceTransformation.

Program

The first step is to binarize the input image. This achieves a clear distinction between object and background. The binarization is important for the distance transformation, as the distance transformation only reacts to pixels with the value 0. If the object is black on a white background, it must be inverted by means of the threshold type BINARY_INV.

IF bInvert THEN
    eThresholdType := TCVN_TT_BINARY_INV;
ELSE
    eThresholdType := TCVN_TT_BINARY;
END_IF
hr := F_VN_Threshold(ipImageIn, ipImageWork, fThreshold, 255, eThresholdType, hr);

Through the distance transformation you obtain an image in which each pixel value indicates the distance to the next pixel with a value of 0. The pixel with the highest value is thus the pixel with the greatest distance. If you use the L2 norm (Euclidean distance) as the distance type eDistanceType, you could interpret this pixel as the center point of a circle that fills out the object as much as possible. Therefore, determine the pixel with the maximum value using the function F_VN_MaxPixelValue and use its position as the center point of the circle and its value as the radius of the circle.

hr := F_VN_DistanceTransformation(
    ipSrcImage      :=  ipImageWork,
    ipDestImage     :=  ipImageWork,
    eDistanceType   :=  TCVN_DT_L2,
    eMaskSize       :=  TCVN_DTM_5,
    hrPrev          :=  hr
);
hr := F_VN_MaxPixelValue(ipImageWork, aMax, aPos, hr);
fRadius := aMax[0];
aCenter := aPos;

The mask size eMaskSize determines the accuracy of the distance calculation and has little influence on the result.

Finally, paint the circle in the result image on the basis of the determined center point and radius in order to be able to validate the execution.

hr := F_VN_DrawCircle(
    nCenterX    :=  TO_UDINT(aCenter[0]),
    nCenterY    :=  TO_UDINT(aCenter[1]),
    nRadius     :=  TO_UDINT(fRadius),
    ipDestImage :=  ipImageRes,
    aColor      :=  aRed,
    nThickness  :=  2,
    hrPrev      :=  hr
);
hr := F_VN_DrawPointExp(TO_UDINT(aCenter[0]), TO_UDINT(aCenter[1]), ipImageRes, TCVN_DS_X, aRed, 10, 2, TCVN_LT_ANTIALIASED, hr);