计算轴未对齐的两个矩形之间的交叉区域

时间:2017-09-29 22:03:10

标签: python math machine-learning tensorflow computer-vision

我想计算两个矩形之间的交点 IoU ,这两个矩形的轴未对齐,但轴的角度小于30度。还寻求近似值。

一种可能的解决方案是检查两个矩形之间的角度是否小于30度,并且平行于轴线的方向旋转它们。从这里可以很容易地计算 IoU

另一种可能性是使用蒙特卡罗方法进行交叉(生成一个点,找到点是在一个矩形的某个线下面还是在另一个矩形的某个线上),但这看起来很昂贵,因为我需要使用这个计算很多次。

我跳来说那里有更好的东西;可能是几何图书馆,也可能是计算机视觉人员的算法。

我正在尝试使用深度神经网络学习掌握位置。我的算法应该预测rgb图像中对象的边界框(矩形)。对于任何图像,我也有地面实况(另一个矩形)边界框。从这两个矩形我需要 IoU

有什么想法吗?

5 个答案:

答案 0 :(得分:1)

对于计算两个凸多边形之间的交点有非常有效的算法,如O'Rourke的书“C中的计算几何”中所述。

C代码可用at the book page(convconv)。

算法遍历第一个多边形的边,检查第二个多边形顶点的方向以检测交叉点。当两个结果顶点位于边缘的不同侧时,会发生交叉(存在许多特技情况)。算法大纲为here

答案 1 :(得分:1)

你可以考虑一些数值方法,实际上"渲染"将矩形放入一些"画布" /画布中,并遍历像素以进行统计。画布的大小应该是整个场景的边界框的大小,实际上你可以通过选择每个轴的最小和最大坐标来找到它。

1)"大多数CG"方法:真正得到一个渲染库,用红色渲染一个矩形,用透明蓝色渲染另一个矩形。然后访问每个像素,如果它具有非0红色分量,则它属于第一个矩形,如果它具有非0蓝色分量,则它属于第二个矩形。如果两者都有,它也属于交叉点。这种方法对于编码来说很便宜,但是即使在渲染阶段也需要写入和读取画布,这比写入要慢。这甚至可以在GPU上完成,但我不确定设置成本和取回结果是否会影响这样一个简单场景的好处。

2)为了速度,另一种CG方法将呈现为2个阵列,最好是每像素1个字节的变体(为了找到这样的专用渲染,你可能需要稍微回过头来库)。这样,渲染器每个矩形只能写入一个数组,并且在创建统计信息时从两个读取

3)因为写入和读取像素需要时间,你可以做一些快捷方式,但它需要更多的编码:可以通过收集每条扫描线的最小和最大坐标来渲染凸形,然后在两者之间填充。如果你自己做,你可以省去填充部分以及最后的每个像素读取和检查步骤。为这两个矩形构建这样的最小 - 最大列表,然后你只需要#34;必须检查每条扫描线的关系/顺序,以识别重叠

然后有数学方法:这不是很有用,请参阅下面的编辑,而你不太可能找到一些计算交叉区域的理智算法,特别是对于矩形的情况,如果你找到这样的三角形算法,这是更有可能的,这就足够了。两个矩形可以分成两个三角形,分别是1A + 1B和2A + 2B,然后你只需要运行这样的算法4次:1A-2A,1A-2B,1B-2A,1B-2B,求和结果和那是你十字路口的一个区域。

编辑:对于数学方法(尽管这也来自图形),我认为https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm可以在这里应用(因为两个矩形都是凸多边形,AB和BA应该产生相同的结果)来找到交集多边形,然后剩下的任务是计算该多边形的面积(这里和现在我认为它将是凸的,然后它真的很容易)。

答案 2 :(得分:1)

由于您使用的是Python,我认为Shapely包可以满足您的需求。

答案 3 :(得分:1)

我最终使用Sutherland-Hodgman算法实现了这个功能:

def clip(subjectPolygon, clipPolygon):
   def inside(p):
      return(cp2[0]-cp1[0])*(p[1]-cp1[1]) > (cp2[1]-cp1[1])*(p[0]-cp1[0])

   def computeIntersection():
      dc = [ cp1[0] - cp2[0], cp1[1] - cp2[1] ]
      dp = [ s[0] - e[0], s[1] - e[1] ]
      n1 = cp1[0] * cp2[1] - cp1[1] * cp2[0]
      n2 = s[0] * e[1] - s[1] * e[0] 
      n3 = 1.0 / (dc[0] * dp[1] - dc[1] * dp[0])
      return [(n1*dp[0] - n2*dc[0]) * n3, (n1*dp[1] - n2*dc[1]) * n3]

   outputList = subjectPolygon
   cp1 = clipPolygon[-1]

   for clipVertex in clipPolygon:
      cp2 = clipVertex
      inputList = outputList
      outputList = []
      s = inputList[-1]

      for subjectVertex in inputList:
         e = subjectVertex
         if inside(e):
            if not inside(s):
               outputList.append(computeIntersection())
            outputList.append(e)
         elif inside(s):
            outputList.append(computeIntersection())
         s = e
      cp1 = cp2
   return(outputList)

def PolygonArea(corners):
    n = len(corners) # of corners
    area = 0.0
    for i in range(n):
        j = (i + 1) % n
        area += corners[i][0] * corners[j][1]
        area -= corners[j][0] * corners[i][1]
    area = abs(area) / 2.0
    return area

intersection = clip(rec1, rec2)
intersection_area = PolygonArea(intersection)
iou = intersection_area/(PolygonArea(rec1)+PolygonArea(rec2)-intersection_area)

另一种较慢的方法(不知道算法是什么)可能是:

from shapely.geometry import Polygon

p1 = Polygon(rec1)
p2 = Polygon(rec2)
inter_sec_area = p1.intersection(rec2).area
iou = inter_sec_area/(p1.area + p2.area - inter_sec_area)

值得一提的是,在一个较大的多边形(不是我的情况)的情况下,shapely模块的面积比第一个方法大两倍。我没有密集地测试这两种方法。

答案 4 :(得分:0)

This might help

使用毕达哥拉斯定理怎么样?由于你有两个矩形,当它们相交时,你将有一个或多个三角形,每个三角形都有一个90°的角度。

由于你也知道两个矩形(我的例子中是20°)和每个矩形的坐标之间的角度,你可以使用适当的函数(cos / sin / tan)来知道所有边的长度。三角形。

我希望这可以提供帮助