我想计算红色和蓝色矩形之间的重叠区域“灰色区域”。
每个矩形由其四个角坐标定义。重叠区域的结果单位是单位正方形。
我无法想象我该怎么做?
任何有创意的评论将不胜感激。
我想计算红色和蓝色矩形之间的重叠区域“灰色区域”。
每个矩形由其四个角坐标定义。重叠区域的结果单位是单位正方形。
我无法想象我该怎么做?
任何有创意的评论将不胜感激。
这种类型的交集很容易通过“最大值中的最小值”和“最小值中的最大值”的想法来完成。要写出来,需要对矩形有一个特定的概念,为了清楚起见,我将使用一个命名元组:
from collections import namedtuple
Rectangle = namedtuple('Rectangle', 'xmin ymin xmax ymax')
ra = Rectangle(3., 3., 5., 5.)
rb = Rectangle(1., 1., 4., 3.5)
# intersection here is (3, 3, 4, 3.5), or an area of 1*.5=.5
def area(a, b): # returns None if rectangles don't intersect
dx = min(a.xmax, b.xmax) - max(a.xmin, b.xmin)
dy = min(a.ymax, b.ymax) - max(a.ymin, b.ymin)
if (dx>=0) and (dy>=0):
return dx*dy
print area(ra, rb)
# 0.5
如果您不喜欢 namedtuple 表示法,您可以使用:
dx = max(a[0], b[0]) - min(a[2], b[2])
等等,或者你喜欢的任何符号。
由于这个问题有一个匀称的标签,这里有一个使用它的解决方案。我将使用与tom10 答案中相同的矩形:
from shapely.geometry import Polygon
polygon = Polygon([(3, 3), (5, 3), (5, 5), (3, 5)])
other_polygon = Polygon([(1, 1), (4, 1), (4, 3.5), (1, 3.5)])
intersection = polygon.intersection(other_polygon)
print(intersection.area)
# 0.5
这比接受的答案中的版本简洁得多。您不必构建自己的Rectangle
类,因为 Shapely 已经提供了现成的类。它不太容易出错(找出该area
函数中的逻辑)。并且代码本身是不言自明的。
由于这篇文章与计算机视觉和对象检测有很大关系,所以我想放一些代码,用于查找边界框的交集以及查找框的 IOU。此代码最初由 Adrian RoseBrock 在此博客文章中开发:
这是模块(我将其命名为 bbox):
class Bbox:
def __init__(self, x1, y1, x2, y2):
self.x1 = max(x1, x2)
self.x2 = min(x1, x2)
self.y1 = max(y1, y2)
self.y2 = max(y1, y2)
self.box = [self.x1, self.y1, self.x2, self.y2]
self.width = abs(self.x1 - self.x2)
self.height = abs(self.y1 - self.y2)
@property
def area(self):
"""
Calculates the surface area. useful for IOU!
"""
return (self.x2 - self.x1 + 1) * (self.y2 - self.y1 + 1)
def intersect(self, bbox):
x1 = max(self.x1, bbox.x1)
y1 = max(self.y1, bbox.y1)
x2 = min(self.x2, bbox.x2)
y2 = min(self.y2, bbox.y2)
intersection = max(0, x2 - x1 + 1) * max(0, y2 - y1 + 1)
return intersection
def iou(self, bbox):
intersection = self.intersection(bbox)
iou = intersection / float(self.area + bbox.area - intersection)
# return the intersection over union value
return iou
并使用它:
a = Bbox([516, 289, 529, 303])
b = Bbox([487, 219, 533, 342])
result = a.intersect(b)
我希望它对你有用。