Skip to content
Advertisement

How to check if contours are the same?

I’ve got two images, the second one is the first one after modification. I find contours of two images and then check if there any same contours. The problem is, that despite contours being the same (drawing contours of one image and another one gives totally same results) after checking that it never becomes true that one contour is equal to any another.

The code: Finding the contours:

List<MatOfPoint> contours1 = new ArrayList<>();
List<MatOfPoint> contours2 = new ArrayList<>();
Imgproc.findContours(contours1mat, contours1, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
Imgproc.findContours(contours2mat, contours2, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

Checking the contours (it never makes match variable true):

for(int i = 0; i < contours1.size(); i++)
{
    boolean match = false;

    for (int j = 0; j < contours2.size(); j++)
    {
        if (contours1.get(i) == contours2.get(j))
        {
            //never hits that place, despite passing through all contours
            match = true;
            break;
        }
    }

    if (!match)
    {
        contours1.remove(i);
        i--;
    }
}

What am I doing wrong? Is this way of checking the similarity of the contours is incorrect? If so, how can I check if two contours are the same? How would You check the contour match if you would need to?

First image:

enter image description here

Second image:

enter image description here

The logic behind the second image is that it is the first image but with holes punched in it. I am checking if those holes cross the side of the white zone, if it does not, there should be two same contours in first and second image. I am only finding the outer contours, so the contour size is the same in both images.

UPDATE!!! This code gives me the desired result, but the problem is that it is really time consuming, and, obviously, there is a huge room for improvement in the algorythm itself (probably some approximation of contours could be done before the check) or the method I use. I really hope that there is an easy direct result to solve my issue. Code:

for(int i = 0; i < contours1.size(); i++)
{
    boolean match = true;

    for (int j = 0; j < contours2.size(); j++)
    {
        if (contours1.get(i).toArray().length == contours2.get(j).toArray().length)
        {
            boolean match2 = true;
            for (int k = 0; k < contours1.get(i).toArray().length; k++)
            {
                if ((contours1.get(i).toArray()[k].x != contours2.get(j).toArray()[k].x) ||
                    (contours1.get(i).toArray()[k].y != contours2.get(j).toArray()[k].y))
                {
                    match2 = false;
                }
            }
            if (match2)
            {
                match = true;
                break;
            }
        }
        else
            match = false;
    }

    if (!match)
    {
        contours1.remove(i);
        i--;
    }
}

Advertisement

Answer

The equality operator == doesn’t work for objects the way it works for primitives.

For ints, chars, booleans, etc. comparing with == checks if their values are equal. For objects, it checks if the two variables refer to the same object, not if the fields within the objects are the same. In order to check for objects being equivalent, there is the method .equals(), which would be used like this:

if (contours1.get(i).equals(contours2.get(i)))

However, this will default to the same behavior as ==, checking if the two variables refer to the same object. In your MatOfPoint class, you will need to override the .equals() method to define how it should check for two objects being “equal”.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement