【问题标题】:Calculate overlapped area between two rectangles计算两个矩形之间的重叠面积
【发布时间】:2015-01-25 00:03:38
【问题描述】:

我想计算红色和蓝色矩形之间的重叠区域“灰色区域”。

每个矩形由其四个角坐标定义。重叠区域的结果单位是单位正方形。

我无法想象我该怎么做?

任何有创意的 cmets 都将不胜感激。

【问题讨论】:

  • 那么你的问题到底是什么?如果你知道所有的角点,你可以很容易地计算出相交矩形的角。角坐标和minmax 函数应该是你所需要的。
  • shapely可以计算相交矩形的角吗?
  • 我不知道。但是,我很确定您可以弄清楚如何自己计算这些角。只要看看左上角:要在交叉路口,你必须有一个 x_coord 至少与红色和蓝色左端的最大值一样大,并且 y_coord 至多红色和蓝色上端的最小值......你有四个角点中的每一个都有类似的参数。
  • 这很容易,但主要问题是符号。你如何在你的代码中定义一个矩形?例如,一个元组的值如下:(xmin, ymin, xmax, ymax) 等?
  • @tom10 矩形的每个角定义为(x,y)坐标值,如你所说,可以用来获取(xmin, ymin, xmax, ymax)。

标签: python numpy matplotlib polygon shapely


【解决方案1】:

由于这篇文章与计算机视觉和对象检测有很大关系,我想放一些代码,用于查找边界框的交集以及查找框的 IOU。此代码最初由 Adrian RoseBrock 在this blog post 开发:

这是模块(我将其命名为 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)

我希望它对你有用。

【讨论】:

    【解决方案2】:

    由于这个问题有一个 标签,这里有一个使用它的解决方案。我将使用与tom10 answer 中相同的矩形:

    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 已经提供了 the ready ones。它不太容易出错(找出area 函数中的逻辑)。而且代码本身是不言自明的。


    参考:
    Docs for object.intersection(other) method

    【讨论】:

    【解决方案3】:

    这种类型的交集很容易通过“最大值的最小值”和“最小值的最大值”的想法来完成。要写出来,需要对矩形有一个特定的概念,为了清楚起见,我将使用一个命名元组:

    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])
    

    等等,或者你喜欢的任何符号。

    【讨论】:

    • 感谢接受,但即使蓝色多边形位于红色多边形的左侧,您的代码是否仍然有效?
    • @just:是的,无论哪种方式都可以。使用最大和最小方法只是一种简单的方法,否则将是一组复杂的条件来确定相对位置。也就是说,将max(a.xmin, b.xmin) 读作“最左角”等。此外,我将答案更改为现在包括矩形不相交的情况。
    • 如何得到重叠面积百分比?
    • @SanthoshDhaipuleChandrakanth:最好单独提出一个问题。例如,这里不清楚您所说的百分比是什么意思,具体来说,重叠区域很清楚,您将其与哪个区域进行比较——最大面积、两个初始矩形的面积等?
    • 请注意:一定要使用正确的点——在笛卡尔坐标轴上,“左上角”是 x.min,但 y.max。在显示器上,x.min, y.min 在左上角,x.max, y.max 在右下角。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-28
    • 2011-01-08
    • 2021-10-21
    • 2013-12-21
    • 2023-03-18
    • 2021-03-12
    相关资源
    最近更新 更多