Search code examples
pythonopencvcomputer-visionpolygon

Identify two figures for similarity


I am trying to find a reliable way to determine the similarity between geometric shapes (polygons).

In one of my approaches, I tried to use the cvopen library and the findContours() and matchShapes() methods. However, this is not an ideal way for me, since I can have very similar shapes, but with different point coordinates. And accordingly, two shapes are determined to be completely different. An example is below enter image description here

I started to explore the issue further, and tried to determine the identity of figures based on the area, perimeter, and comparison of the angles of the figures. But this option is also not entirely optimal, since similar figures can differ in size (and therefore in area and perimeter), and the angles of the figures can be slightly different. An example is below enter image description here

You may ask: which figures do I consider similar, and which figures are different? In the example below, the figures are categorically not similar to each other, but the first two photos, I will classify as similar figures enter image description here

I am not asking for a ready-made code for the solution, I am only asking for advice and ideas from you. What other methods can I try to correctly determine the similarity of figures?


Solution

  • One option is to use shape-similarity (a few modules) that uses mainly the Fréchet distance :

    from shapesimilarity import shape_similarity
    
    def are_similar(p1, p2, threshold=0.9): #  << adjust if needed
        try:
            sim = shape_similarity(p1, p2)
        except AssertionError:
            sim = 0
        return sim > threshold
    

    enter image description here

    Used inputs :

    yellow red
    case1 [[101, 0], [548, 4], [430, 216], [400, 211], [330, 313], [240, 324], [219, 245], [101, 0]] [[115, 12], [554, 10], [445, 219], [417, 212], [353, 317], [267, 330], [242, 254], [115, 12]]
    case2 [[104, 0], [534, 3], [421, 198], [390, 194], [321, 290], [236, 298], [217, 233], [104, 0]] [[158, 32], [554, 30], [430, 195], [413, 199], [328, 306], [233, 321], [251, 240], [158, 32]]
    case3 [[168, 0], [555, 1], [452, 212], [427, 209], [365, 309], [287, 319], [271, 247], [168, 0]] [[102, 232], [549, 190], [378, 255], [408, 298], [295, 334], [102, 232]]