Meetinger
Meetinger

Reputation: 375

Find the intersection and union of two rectangles

I need to find the area of ​​intersection and union of two rectangles, as well as the ratio of the intersection area to the union area. What is the best way to do this? Picture

def intersection_over_union(a, b):
    ax1 = a['left']
    ay1 = a['top']
    aw = a['width']
    ah = a['height']
    ax2 = ax1 + aw
    ay2 = ay1 + ah

    bx1 = b['left']
    by1 = b['top']
    bw = b['width']
    bh = b['height']
    bx2 = bx1 + bw
    by2 = by1 + bh

    delta_x = max(ax1, bx1) - min(ax2, bx2)
    delta_y = max(ay1, by1) - min(ay2, by2)

    overlap = delta_x * delta_y
    union = aw * ah + bw * bh - overlap

    print(overlap, union)

    return overlap / union

Upvotes: 2

Views: 3090

Answers (2)

Eantropix
Eantropix

Reputation: 1

One way I believe you could do this (although I am not sure it is the best solution as you've asked for), is to develop a function that creates a rectangle in a plane, and stores all of its corners' coordinates in a list.

Every time you create a rectangle (let's say you create it from the bottom left, increasing its x and y coordinates as you go), check for each coordinate if the x coordinate is within the other rectangle's x-range i.e. x_min < x < x_max. If so, check the y-coordinate. If the coordinate is within the x and y ranges of another rectangle, it's part of the intersection.

Repeat for all coordinates as you create them and save the intersection coordinates, and find the intersection's corners. With that, you can calculate the area of intersection and union between the two triangles, and their ratio to one another.

Upvotes: 0

Jakub D&#243;ka
Jakub D&#243;ka

Reputation: 2625

Assuming you are dealing with AABB (axis aligned bounding box) this little class defines everything you need:

class Rect:
    def __init__(self, x, y, w, h):
        self.x = x
        self.y = y
        self.w = w
        self.h = h
    
    def bottom(self):
        return self.y + self.h
    
    def right(self):
        return self.x + self.w
    
    def area(self):
        return self.w * self.h

    def union(self, b):
        posX = min(self.x, b.x)
        posY = min(self.y, b.y)
        
        return Rect(posX, posY, max(self.right(), b.right()) - posX, max(self.bottom(), b.bottom()) - posY)
    
    def intersection(self, b):
        posX = max(self.x, b.x)
        posY = max(self.y, b.y)
        
        candidate = Rect(posX, posY, min(self.right(), b.right()) - posX, min(self.bottom(), b.bottom()) - posY)
        if candidate.w > 0 and candidate.h > 0:
            return candidate
        return Rect(0, 0, 0, 0)
    
    def ratio(self, b):
        return self.intersection(b).area() / self.union(b).area()

if __name__ == "__main__":
    assert Rect(1, 1, 1, 1).ratio(Rect(1, 1, 1, 1)) == 1
    assert round(Rect(1, 1, 2, 2).ratio(Rect(2, 2, 2, 2)), 4) == 0.1111

Upvotes: 3

Related Questions