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