Match Contours (extracted shapes)
In this sample, two contours are compared using the function F_VN_MatchContours.
Explanation
The function F_VN_MatchContours compares two contours used in the sample based on the Hu moments. In this sample, the function is used to recognize a given component in a new situation. For this purpose, a component is selected in a reference image, its contour is saved and then compared with the contours from another image. In this way, the components that fall below a certain dissimilarity compared to the reference component are marked.
Input parameters
In addition to the contours to be compared, only a parameter hast to be passed to the function that describes the calculation method used to determine the dissimilarity from the Hu moments (eComparisonMethod of type ETcVnContoursMatchComparisonMethod). The method TCVN_CMCM_CONTOURS_MATCH_I1 calculates the sum of the differences in the reciprocal values of the individual characteristics, while the method TCVN_CMCM_CONTOURS_MATCH_I2 calculates the sum of the differences in the pure characteristics. Unlike the first two methods, the third variant TCVN_CMCM_CONTOURS_MATCH_I3 only calculates the maximum difference between the individual characteristics. Which of the three methods is best suited for comparing two contours depends on the use case.
Variables
hr : HRESULT;
ipImageIn : ITcVnImage;
ipImageInDisp : ITcVnDisplayableImage;
ipImageRes : ITcVnImage;
ipImageResDisp : ITcVnDisplayableImage;
ipIterator : ITcVnForwardIterator;
// result
ipContourList : ITcVnContainer;
ipContourReference : ITcVnContainer;
ipContourCheck : ITcVnContainer;
fBestDissimilarity : LREAL;
fDissimilarity : LREAL;
// parameters
fThreshold : REAL := 170;
fMinArea : REAL := 10000;
fMaxDissimilarity : LREAL := 0.01;
eComparisonMethod : ETcVnContoursMatchComparisonMethod := TCVN_CMCM_CONTOURS_MATCH_I3;
// drawing
aColorGreen : TcVnVector4_LREAL := [0, 175, 0];
aColorBlue : TcVnVector4_LREAL := [0, 0, 255];
aColorRed : TcVnVector4_LREAL := [255, 0, 0];
aColorRes : TcVnVector4_LREAL;
sText : STRING(255);
sTextReference : STRING(255) := 'Reference contour';
sTextCheck : STRING(255) := 'Check dissimilarity';
// other
bDarkBackground : BOOL;
nContours : ULINT;
nCounter : UINT := 0;
aPixelValue : TcVnVector4_LREAL;
stBoundingRectangle : TcVnRectangle_UDINT;
stParams : TcVnParamsBlobDetection;
Code
// Prepare result image
hr := F_VN_ConvertColorSpace(ipImageIn, ipImageRes, TCVN_CST_GRAY_TO_RGB, hr);
// Check if background is dark in order to identify reference image
hr := F_VN_GetPixel(ipImageIn, aPixelValue, 50, 50, hr);
bDarkBackground := SUCCEEDED(hr) AND_THEN aPixelValue[0] < 128;
IF bDarkBackground THEN
stParams.eThresholdType := TCVN_TT_BINARY;
ELSE
stParams.eThresholdType := TCVN_TT_BINARY_INV;
END_IF
// Find contours in image
hr := F_VN_DetectBlobs(ipImageIn, ipContourList, stParams, hr);
// Distinguish reference and test image
IF bDarkBackground THEN
// Select one of the found contours as reference for matching
hr := F_VN_GetNumberOfElements(ipContourList, nContours, hr);
hr := F_VN_GetAt_ITcVnContainer(ipContourList, ipContourReference, nCounter MOD nContours, hr);
// Draw selected contour and text
hr := F_VN_PutTextExp(sTextReference, ipImageRes, 50, 50, TCVN_FT_HERSHEY_SIMPLEX, 1.3, aColorBlue, 2, TCVN_LT_8_CONNECTED, FALSE, hr);
hr := F_VN_DrawContours(ipContourReference, -1, ipImageRes, aColorBlue, 5, hr);
nCounter := nCounter + 1;
ELSE
fBestDissimilarity := 10E300;
// 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, ipContourCheck, hr);
hr := F_VN_IncrementIterator(ipIterator, hr);
// Match the current contour with the selected reference contour
hr := F_VN_MatchContours(ipContourReference, ipContourCheck, eComparisonMethod, fDissimilarity, hr);
// Save best result
IF fBestDissimilarity > fDissimilarity THEN
fBestDissimilarity := fDissimilarity;
END_IF
// Choose action depending on the dissimilarity of both contours
IF SUCCEEDED(hr) AND_THEN fDissimilarity < fMaxDissimilarity THEN
aColorRes := aColorGreen;
ELSE
aColorRes := aColorRed;
END_IF
// Draw matching results
sText := REAL_TO_STRING(LREAL_TO_REAL(fDissimilarity));
hr := F_VN_UprightBoundingRectangle(ipContourCheck, stBoundingRectangle, hr);
hr := F_VN_DrawContours(ipContourCheck, -1, ipImageRes, aColorRes, 5, hr);
hr := F_VN_PutTextExp(sText, ipImageRes, LREAL_TO_UDINT(stBoundingRectangle.nX + 30), LREAL_TO_UDINT(stBoundingRectangle.nY + (stBoundingRectangle.nHeight / 2)), TCVN_FT_HERSHEY_SIMPLEX, 0.8, aColorRes, 2, TCVN_LT_8_CONNECTED, FALSE, hr);
END_WHILE
// Draw text
hr := F_VN_PutTextExp(sTextCheck, ipImageRes, 50, 50, TCVN_FT_HERSHEY_SIMPLEX, 1.3, aColorGreen, 2, TCVN_LT_8_CONNECTED, FALSE, hr);
sText := CONCAT('Best match: ', REAL_TO_STRING(LREAL_TO_REAL(fBestDissimilarity)));
hr := F_VN_PutTextExp(sText, ipImageRes, 50, 100, TCVN_FT_HERSHEY_SIMPLEX, 1.3, aColorGreen, 2, TCVN_LT_8_CONNECTED, FALSE, hr);
END_IF
hr := F_VN_TransformIntoDisplayableImage(ipImageRes, ipImageResDisp, hr);
hr := F_VN_TransformIntoDisplayableImage(ipImageIn, ipImageInDisp, hr);
Results
The currently selected reference contour is marked in blue on the reference image:
You can see that the contour is slightly curved by the lens distortion and has some minor flaws. In the test pattern, contours whose dissimilarity relative to the reference contour falls below the set threshold value are displayed in green, the other contours are shown in red. In addition, the calculated dissimilarity is superimposed over all contours. The following illustration shows the result for the MatchContours1.bmp input imaged when the rectangle is selected as a reference component:
It can be seen that the rectangular component has by far the smallest dissimilarity compared to the reference contour. If the parameter eComparisonMethod is changed from TCVN_CMCM_CONTOURS_MATCH_I3 to TCVN_CMCM_CONTOURS_MATCH_I2, the calculated dissimilarities change accordingly:
In this case, the result is even clearer, but this does not apply to all shapes. If the triangle is selected as the reference component, the result with this setting is significantly less clear than with the original setting:
This result demonstrates that different calculation methods can provide the best results, depending on the application.