Reputation: 375
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
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
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