Match Contours 1vsN (manuelle Formen)

In diesem Beispiel werden Konturen mit Hilfe der Funktion F_VN_MatchContours1vsN mit Referenz-Konturen verglichen. Dabei sind

Erläuterung

Die Funktion F_VN_MatchContours vergleicht zwei gegebene Konturen mit Hilfe der Hu Momente. Die Funktion F_VN_MatchContours1vsN stellt eine Erweiterung dar, mit der eine Kontur gleichzeitig mit mehreren anderen Konturen verglichen werden kann. Dies wird in diesem Beispiel benutzt, um Werkstücke bezüglich vorgegebener Referenzformen zu klassifizieren.

Die Referenzformen sind idealisierte, manuell erstellte Polygone eines gleichschenkligen Dreiecks, eines Rechtecks/Quadrats und eines Trapezes. Da bei den Polygonen nur die Eckpunkte angegeben wurden, unterscheiden sich die Referenzformen von den Testkonturen in der Anzahl der zu beschreibenden Konturpunkte stark. Weiterhin unterscheiden sie sich in Lage, Orientierung, Größe und dem Grad der Störungen innerhalb der Kontur.

Um die Form der Bauteile aus dem Bild zu extrahieren, werden mit Hilfe der Funktion F_VN_DetectBlobs Konturen gesucht, die eine gewisse Mindestgröße haben. Die gefundenen Konturen werden daraufhin für das beschriebene Matching genutzt.

Eingangsparameter

Neben den zu vergleichenden Konturen, muss der Funktion nur ein Parameter übergeben werden, der die Berechnungsmethode beschreibt, mit der aus den Hu Momenten das Ungleichheitsmaß bestimmt wird (eComparisonMethod vom Typ ETcVnContoursMatchComparisonMethod). Die Methode TCVN_CMCM_CONTOURS_MATCH_I1 berechnet die Summe über die Differenzen der Kehrwerte der individuellen Charakteristiken, während die Methode TCVN_CMCM_CONTOURS_MATCH_I2 die Summe über die Differenzen der reinen Charakteristiken bildet. Im Gegensatz zu den ersten beiden Methoden berechnet die dritte Variante TCVN_CMCM_CONTOURS_MATCH_I3 nur die maximale Differenz der individuellen Charakteristiken. Je nach Anwendungsfall kann eine andere der drei Methoden am besten geeignet sein für den Vergleich zweier Konturen.

Variablen

Match Contours 1vsN (manuelle Formen) 1:

Datentyp nur in diesem Beispiel

Der Datentyp CustomTcVnArray4_Point2_DINT ist nicht in TwinCAT Vision enthalten, sondern wurde explizit für dieses Beispiel erstellt. Die Implementierung finden Sie im Download dieses Beispiels.

// Indexes representing the different shapes
TRIANGLE              :   USINT := 0;
RECTANGLE             :   USINT := 1;
TRAPEZOID             :   USINT := 2;

// Images
ipImageIn             :   ITcVnImage;
ipImageInDisp         :   ITcVnDisplayableImage;
ipImageRes            :   ITcVnImage;
ipImageResDisp        :   ITcVnDisplayableImage;

// Contours
ipContourList         :   ITcVnContainer;
ipContour             :   ITcVnContainer;
ipIterator            :   ITcVnForwardIterator;
aShapeArrays          :   ARRAY [0..2] OF CustomTcVnArray4_Point2_DINT :=
                              [[[0,0],[40,0],[20, LREAL_TO_DINT(SQRT(1200))], [0,0]],  // Triangle
                               [[0,0],[40,0],[40,40],[0,40]],                          // Rectangle
                               [[0,0],[40,0],[60,22],[20,22]]];                        // Trapezoid;
aShapes               :   ARRAY[0..2] OF ITcVnContainer;
ipShapes              :   ITcVnContainer;

// Matching
ipMatchIndexes        :   ITcVnContainer;
ipDissimilarities     :   ITcVnContainer;
aMatchIndexes         :   ARRAY [0..2] OF ULINT;
aDissimilarities      :   ARRAY [0..2] OF LREAL;

// Parameters
stBlobParams          :   TcVnParamsBlobDetection;
fThreshold            :   REAL := 170;
fMinArea              :   REAL := 10000;
fMaxDissimilarity     :   LREAL := 0.02;
eComparisonMethod     :   ETcVnContoursMatchComparisonMethod := TCVN_CMCM_CONTOURS_MATCH_I3;

// drawing
aColors               :   ARRAY[0..2] OF TcVnVector4_LREAL :=
                              [[0, 175, 0, 0], [0, 0, 255, 0], [255, 0, 0, 0]]; // green, blue, red
aColorWhite           :   TcVnVector4_LREAL := [255, 255, 255];
aColorBlack           :   TcVnVector4_LREAL := [0, 0, 0];
aTexts                :   ARRAY[0..2] OF STRING := ['Triangle', 'Rectangle', 'Trapezoid'];
sText                 :   STRING(255);
nTopLeftX             :   UDINT;
nTopLeftY             :   UDINT;

// Miscellaneous
aPixelValue           :   TcVnVector4_LREAL;
I                     :   USINT;
stBoundingRectangle   :   TcVnRectangle_UDINT;
aOffsets              :   ARRAY [0..2] OF TcVnPoint := [[20, 50], [20, 100], [20, 160]];
hr                    :   HRESULT;

Code

// Fill manually defined shapes into one container
hr := F_VN_CreateContainer(ipShapes, ContainerType_Vector_Vector_TcVnPoint2_DINT, 0, hr);
FOR i:=TRIANGLE TO TRAPEZOID DO
    hr := F_VN_CreateContainerFromArray(ADR(aShapeArrays[i]), aShapes[i], ContainerType_Vector_TcVnPoint2_DINT, 4, hr);
    hr := F_VN_InsertIntoContainer_ITcVnContainer(aShapes[i], ipShapes, i, hr);
END_FOR

// Prepare result image
hr := F_VN_ConvertColorSpace(ipImageIn, ipImageRes, TCVN_CST_GRAY_TO_RGB, hr);

// Check if background is light or dark
hr := F_VN_GetPixel(ipImageIn, aPixelValue, 50, 50, hr);
IF SUCCEEDED(hr) AND_THEN aPixelValue[0] < 128 THEN
    stBlobParams.eThresholdType := TCVN_TT_BINARY;
ELSE
    stBlobParams.eThresholdType := TCVN_TT_BINARY_INV;
END_IF

// Find contours in image
stBlobParams.bFilterByArea := TRUE;
stBlobParams.fMinArea := fMinArea;
stBlobParams.fMinThreshold := fThreshold;
hr := F_VN_DetectBlobs(ipImageIn, ipContourList, stBlobParams, hr);

// Iterate through all found contours
hr := F_VN_GetForwardIterator(ipContourList, ipIterator, hr);
WHILE hr = S_OK AND_THEN ipIterator.CheckIfEnd() <> S_OK DO
    hr := F_VN_GetContainer(ipIterator, ipContour, hr);
    hr := F_VN_IncrementIterator(ipIterator, hr);

    // Match the current contour with the reference shapes
    hr := F_VN_MatchContours1vsN(
        ipRefContour:= ipContour,
        ipContours:= ipShapes,
        ipMatchIndexes:= ipMatchIndexes,
        ipDissimilarities:= ipDissimilarities,
        fDissimilarityThreshold:= 100,
        eComparisonMethod:= eComparisonMethod,
        hrPrev:= hr
    );


    hr := F_VN_ExportContainer(ipMatchIndexes, ADR(aMatchIndexes), SIZEOF(aMatchIndexes), hr);
    hr := F_VN_ExportContainer(ipDissimilarities, ADR(aDissimilarities), SIZEOF(aDissimilarities), hr);

    // Draw matching results
    IF aDissimilarities[0] < fMaxDissimilarity THEN

        // Calculate position of object
        hr := F_VN_UprightBoundingRectangle(ipContour, stBoundingRectangle, hr);
        nTopLeftX := LREAL_TO_UDINT(stBoundingRectangle.nX + 30);
        nTopLeftY := LREAL_TO_UDINT(stBoundingRectangle.nY + (stBoundingRectangle.nHeight / 2));

        // Draw matching result
        hr := F_VN_DrawContours(ipContour, -1, ipImageRes, aColors[aMatchIndexes[0]], 5, hr);
        hr := F_VN_PutTextExp(aTexts[aMatchIndexes[0]], ipImageRes, nTopLeftX, nTopLeftY, TCVN_FT_HERSHEY_SIMPLEX, 0.8, aColors[aMatchIndexes[0]], 2, TCVN_LT_8_CONNECTED, FALSE, hr);
        hr := F_VN_DrawRectangle(nTopLeftX, nTopLeftY + 5, nTopLeftX + 200, nTopLeftY + 85, ipImageRes, aColorBlack, -1, hr);
        // Draw all dissimilarity values
        FOR i:=0 TO 2 DO
            sText := CONCAT(LEFT(aTexts[aMatchIndexes[i]], 4), CONCAT(' ', REAL_TO_STRING(LREAL_TO_REAL(aDissimilarities[i]))));
            hr := F_VN_PutTextExp(sText, ipImageRes, nTopLeftX + 5, nTopLeftY + 30 + 20*i, TCVN_FT_HERSHEY_SIMPLEX, 0.6, aColorWhite, 1, TCVN_LT_8_CONNECTED, FALSE, hr);
        END_FOR

    END_IF
END_WHILE

// Draw reference shapes
FOR i:=TRIANGLE TO TRAPEZOID DO
    hr := F_VN_DrawContoursExp(aShapes[i], -1, ipImageRes, aColors[i], 2, TCVN_LT_8_CONNECTED, 0, 0, aOffsets[i], hr);
END_FOR
hr := F_VN_TransformIntoDisplayableImage(ipImageRes, ipImageResDisp, hr);
hr := F_VN_TransformIntoDisplayableImage(ipImageIn, ipImageInDisp, hr);

Ergebnisse

Das Ergebnisbild zeigt die Referenzformen (linker Rand), sowie diejenigen gefundenen Konturen, deren Ungleichheitsmaß bezogen auf alle Referenzformen einen Maximalwert nicht überschreitet. Weiterhin wird visualisiert, welcher Referenzform die gefundene Kontur am meisten ähnelt. Ein entsprechender Beschreibungstext (inklusive Ungleichheitsmaße für jede Referenzform) wird über die jeweilige Kontur gezeichnet. Für die vorgegebenen Parameter sieht das Ergebnis für das Bild MatchContours1.bmp wie folgt aus:

Match Contours 1vsN (manuelle Formen) 2:

Es ist zu erkennen, dass der mit Abstand niedrigste Wert jeweils auf die korrekte Referenzkontur hinweist. Wird nun der Parameter eComparisonMethod von TCVN_CMCM_CONTOURS_MATCH_I3 auf TCVN_CMCM_CONTOURS_MATCH_I2 verändert, erkennt man, dass die Ergebnisse sich stark verändern. Dies führt auch dazu, dass der Parameter für die maximal akzeptierte Ungleichheit angepasst werden muss:

Match Contours 1vsN (manuelle Formen) 3:

Die neuen Werte lassen eine deutlich weniger eindeutige Zuordnung zu entsprechenden Referenzformen zu, außerdem wird das runde Bauteil fälschlicher Weise der Referenzform „Rectangle“ zugeordnet. Diese Berechnungsmethode ist für dieses Beispiel also offenbar weniger gut geeignet.

Ähnliche Beispiele