Innerer Kreis mittels Distanztransformation

In diesem Beispiel finden Sie den inneren Kreis eines unförmigen Objekts mittels der Distanztransformation. Dazu verwenden Sie im Wesentlichen folgende Funktionen:

Erklärung

Äußere Konturapproximationen wie ein umschließendes Rechteck oder die konvexe Hülle können über entsprechende API-Funktionen berechnet werden. Das Finden eines inneren Kreises mit maximaler Größe innerhalb einer Kontur kann hingegen mittels einer Distanztransformation gelöst werden.

Innerer Kreis mittels Distanztransformation 1:

Dafür wird mit einer Distanztransformation der Punkt ermittelt, der den größten euklidischen Abstand zu den Objekträndern hat. Dieser Punkt ist dann der Mittelpunkt des inneren Kreises des Objekts.

Wenn Sie dieses Beispiel mit eigenen Bildern benutzen, sollten Sie den Schwellwert und die Binarisierung über die Variablen bInvert und fThreshold anpassen. Mittels den Parametern eDistanceType und eMaskSize können Sie die Parameter der Funktion F_VN_DistanceTransformation gezielt verändern.

Programm

Der erste Schritt ist, das Eingangsbild zu binarisieren. Dadurch wird eindeutig zwischen Objekt und Hintergrund unterschieden. Die Binarisierung ist für die Distanztransformation wichtig, da die Distanztransformation nur auf Pixel mit dem Wert 0 reagiert. Falls das Objekt schwarz auf weißem Hintergrund ist, muss mittels des Schwellwerttyps BINARY_INV invertiert werden.

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

Durch die Distanztransformation erlangen Sie ein Bild, in dem jeder Pixelwert den Abstand zum nächsten 0-wertigen Pixel anzeigt. Das Pixel mit dem höchsten Wert ist somit das Pixel mit dem größten Abstand. Wenn Sie als Distanztyp eDistanceType die L2-Norm (euklidisch Abstand) verwenden, können Sie dieses Pixel als Mittelpunkt eines Kreises interpretieren, der das Objekt so viel wie möglich ausfüllt. Daher ermitteln Sie das höchstwertigsten Pixel mit der Funktion F_VN_MaxPixelValue und verwenden dessen Position als Kreismittelpunkt sowie dessen Wert als Kreisradius.

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;

Die Maskengröße eMaskSize bestimmt die Genauigkeit der Abstandsberechnung und hat wenig Einfluss auf das Ergebnis.

Schließlich malen Sie den Kreis anhand des ermittelten Mittelpunkts und Radius in ein Ergebnisbild ein, um die Ausführung validieren zu können.

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