Search code examples
pythonpython-3.xopencvcoordinates

Find area of overlapping rectangles in Python / OpenCV with a raw list of points


I have the coordinates x1, y1, x2, y2 of a rectangle and a list of other coordinates for other rectangles.

I want to compare the value of the one I already have over with the others to see if they overlap more than 50% of the original rectangle.

I checked other resources but still, I could get my head around it:


Solution

  • Let's first simplify your problem to a single dimension:

    You have an interval A = [a0, a1] and want to find out how much does another interval B = [b0, b1] intersects with it. I will represent A with = and B with -.

    There are 6 possible scenarios:

    • A contains B, intersection = b1 - b0

      a0  b0  b1  a1
      ==============
          ------
      
    • B contains A, intersection = a1 - a0

      b0  a0  a1  b1
          ======
      --------------
      
    • B intersects A from the left, intersection = b1 - a0

      b0  a0  b1  a1
          ==========
      ----------
      
    • B intersects A from the right, intersection = a1 - b0

      a0  b0  a1  b1
      ==========
          ----------
      
    • B is to the left of A, intersection = 0

      b0  b1  a0  a1
              ======
      ------
      
    • B is to the right of A, intersection = 0

      a0  a1  b0  b1
      ======
              ------
      

    Based on that, we can define a function that, given two intervals A = [a0, a1] and B = [b0, b1], returns how much they intersect:

    def calculateIntersection(a0, a1, b0, b1):
        if a0 >= b0 and a1 <= b1: # Contained
            intersection = a1 - a0
        elif a0 < b0 and a1 > b1: # Contains
            intersection = b1 - b0
        elif a0 < b0 and a1 > b0: # Intersects right
            intersection = a1 - b0
        elif a1 > b1 and a0 < b1: # Intersects left
            intersection = b1 - a0
        else: # No intersection (either side)
            intersection = 0
    
        return intersection
    

    That's pretty much everything you need. To find out how much do two rectangles intersect, you just need to execute this function on both the X and the Y axis and multiply those amounts to get the intersecting area:

    # The rectangle against which you are going to test the rest and its area:
    X0, Y0, X1, Y1, = [0, 0, 10, 10]
    AREA = float((X1 - X0) * (Y1 - Y0))
    
    # Rectangles to check
    rectangles = [[15, 0, 20, 10], [0, 15, 10, 20], [0, 0, 5, 5], [0, 0, 5, 10], [0, 5, 10, 100], [0, 0, 100, 100]]
    
    # Intersecting rectangles:
    intersecting = []
    
    for x0, y0, x1, y1 in rectangles:       
        width = calculateIntersection(x0, x1, X0, X1)        
        height = calculateIntersection(y0, y1, Y0, Y1)        
        area = width * height
        percent = area / AREA
    
        if (percent >= 0.5):
            intersecting.append([x0, y0, x1, y1])
    

    The result will be:

    • [15, 0, 20, 10] does not intersect in the X-axis, so width = 0.
    • [0, 15, 10, 20] does not intersect in the Y-axis, so height = 0.
    • [0, 0, 5, 5] intersects only 25%.
    • [0, 0, 5, 10] intersects 50% and will be added to intersecting.
    • [0, 5, 10, 100] intersects 50% and will be added to intersecting.
    • [0, 0, 100, 100] intersects 100% and will be added to intersecting.