自动驾驶多边形iou计算Shapely库笔记
参考:https://cloud.tencent.com/developer/ask/42755,https://blog.csdn.net/u014421797/article/details/89501572,
 https://www.itranslater.com/qa/details/2582747861733606400
两个矩形的交并比计算交简单
 直接复制第二个参考链接中的代码
  
   - 
    
     
    
    
     
      def IoU(box1, box2):
     
    
- 
    
     
    
    
     
          '''
     
    
- 
    
     
    
    
     
          计算两个矩形框的交并比
     
    
- 
    
     
    
    
     
          :param box1: list,第一个矩形框的左上角和右下角坐标
     
    
- 
    
     
    
    
     
          :param box2: list,第二个矩形框的左上角和右下角坐标
     
    
- 
    
     
    
    
     
          :return: 两个矩形框的交并比iou
     
    
- 
    
     
    
    
     
          '''
     
    
- 
    
     
    
    
     
          x1 = max(box1[0], box2[0])   # 交集左上角x
     
    
- 
    
     
    
    
     
          x2 = min(box1[2], box2[2])   # 交集右下角x
     
    
- 
    
     
    
    
     
          y1 = max(box1[1], box2[1])   # 交集左上角y
     
    
- 
    
     
    
    
     
          y2 = min(box1[3], box2[3])   # 交集右下角y
     
    
- 
    
     
    
    
     
       
     
    
- 
    
     
    
    
     
          overlap = max(0., x2-x1) * max(0., y2-y1)
     
    
- 
    
     
    
    
     
          union = (box1[2]-box1[0]) * (box1[3]-box1[1]) \
     
    
- 
    
     
    
    
     
                  + (box2[2]-box2[0]) * (box2[3]-box2[1]) \
     
    
- 
    
     
    
    
     
                  - overlap
     
    
- 
    
     
    
    
     
       
     
    
- 
    
     
    
    
     
          return overlap/union
     
    
- 
    
     
    
    
     
      if __name__ == '__main__':
     
    
- 
    
     
    
    
     
          # box = [左上角x1,左上角y1,右下角x2,右下角y2]
     
    
- 
    
     
    
    
     
          box1 = [10, 0, 15, 10]
     
    
- 
    
     
    
    
     
          box2 = [12, 5, 20, 15]
     
    
- 
    
     
    
    
     
          iou = IoU(box1, box2)
     
    
 
 非规则四边形的IOU计算
 测试发现
 Polygon().convex_hull,排序的结果特点,以最低点的一点为起点,(若y值一样小,则比较x较小的作为起点)顺时针排列所有点
 1
  
   - 
    
     
    
    
     
      import shapely
     
    
- 
    
     
    
    
     
      import numpy as np
     
    
- 
    
     
    
    
     
      from shapely.geometry import Polygon, MultiPoint, mapping 
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      def bbox_iou_eval(box1, box2):
     
    
- 
    
     
    
    
     
          box1 = np.array(box1).reshape(4, 2)
     
    
- 
    
     
    
    
     
          poly1 = Polygon(box1).convex_hull #POLYGON ((0 0, 0 2, 2 2, 2 0, 0 0))
     
    
- 
    
     
    
    
     
          print(type(mapping(poly1)['coordinates'])) # (((0.0, 0.0), (0.0, 2.0), (2.0, 2.0), (2.0, 0.0), (0.0, 0.0)),)
     
    
- 
    
     
    
    
     
          poly_arr = np.array(poly1)
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
          box2 = np.array(box2).reshape(4, 2)
     
    
- 
    
     
    
    
     
          poly2 = Polygon(box2).convex_hull
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
          if not poly1.intersects(poly2):  # 如果两四边形不相交
     
    
- 
    
     
    
    
     
              iou = 0
     
    
- 
    
     
    
    
     
          else:
     
    
- 
    
     
    
    
     
              try:
     
    
- 
    
     
    
    
     
                  inter_area = poly1.intersection(poly2).area  # 相交面积
     
    
- 
    
     
    
    
     
                  iou = float(inter_area) / (poly1.area + poly2.area - inter_area)
     
    
- 
    
     
    
    
     
              except shapely.geos.TopologicalError:
     
    
- 
    
     
    
    
     
                  print('shapely.geos.TopologicalError occured, iou set to 0')
     
    
- 
    
     
    
    
     
                  iou = 0
     
    
- 
    
     
    
    
     
          return iou
     
    
- 
    
     
    
    
     
      if __name__ == '__main__':
     
    
- 
    
     
    
    
     
          # box = [四个点的坐标,顺序无所谓]
     
    
- 
    
     
    
    
     
          box3 = [0, 0, 2, 2, 2, 0, 0, 2]   # 左上,右上,右下,左下
     
    
- 
    
     
    
    
     
          box4 = [1, 1, 1, 3, 3, 3, 3, 1]
     
    
- 
    
     
    
    
     
          iou = bbox_iou_eval(box3, box4)
     
    
- 
    
     
    
    
     
          print(iou)
     
    
 
 Polygon类型中的坐标数据的获得
 有时候想要用到到排序好的几个坐标数据,但Polygon中没有直接得到的坐标点的方法,下面是几种方法
 第一种:使用mapping
 总结:1.可使用nump的功能,将坐标点转化为n*2的形式,
 2.Polygon(n*2).convex_hull对坐标点进行排序
 3.使用mapping得到排序好对象的内容
 4.使用字典和元组切片的方式得到坐标点
 为了防止坐标点会多一个,为了闭合,切片方式中:-1
  
  
   - 
    
     
    
    
     
      from shapely.geometry import Polygon, MultiPoint, mapping 
     
    
- 
    
     
    
    
     
      box3 = [0, 0, 2, 2, 2, 0, 0, 2]
     
    
- 
    
     
    
    
     
      box1 = np.array(box1).reshape(4, 2)
     
    
- 
    
     
    
    
     
      poly1 = Polygon(box1).convex_hull
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      print(poly1)        # POLYGON ((0 0, 0 2, 2 2, 2 0, 0 0))
     
    
- 
    
     
    
    
     
      map_poly = mapping(poly1) # 这时的值就是一个字典可以通过字典方式访问
     
    
- 
    
     
    
    
     
      '''{'type': 'Polygon', 'coordinates': (((0.0, 0.0), (0.0, 2.0), (2.0, 2.0), (2.0, 0.0), (0.0, 0.0)),)}'''
     
    
- 
    
     
    
    
     
      print(['coordinates'])   # 这是一个元组
     
    
- 
    
     
    
    
     
      '''(((0.0, 0.0), (0.0, 2.0), (2.0, 2.0), (2.0, 0.0), (0.0, 0.0)),)'''
     
    
- 
    
     
    
    
     
      print(map_poly['coordinates'][0][:-1])
     
    
- 
    
     
    
    
     
      '''((0.0, 0.0), (0.0, 2.0), (2.0, 2.0), (2.0, 0.0)) '''
     
    
 
 第二种:使用内部属性.exterior.coords.xy
  
   - 
    
     
    
    
     
      box3 = [0, 0, 2, 2, 2, 0, 0, 2]   # 左上,右上,右下,左下
     
    
- 
    
     
    
    
     
      box1 = np.array(box3).reshape(4, 2)  # 将8个点转换为4*2的矩阵形式
     
    
- 
    
     
    
    
     
      poly1 = Polygon(box1).convex_hull 
     
    
- 
    
     
    
    
     
      x, y = poly1.exterior.coords.xy
     
    
- 
    
     
    
    
     
      print(x, y) #array('d', [0.0, 0.0, 2.0, 2.0, 0.0]) array('d', [0.0, 2.0, 2.0, 0.0, 0.0])
     
    
- 
    
     
    
    
     
      print(list(x)) #[0.0, 0.0, 2.0, 2.0, 0.0]
     
    
 
 第三种:使用指针*方式
 解释:
  
   - 
    
     
    
    
     
      list(zip(*poly1.exterior.coords.xy))
     
    
- 
    
     
    
    
     
      '''
     
    
- 
    
     
    
    
     
      1.*poly1.exterior.coords.xy,得到两个分开的arry类型的x,y的数组
     
    
- 
    
     
    
    
     
      2.使用zip将两个一维数组压缩成一对数值为一个元组的多个点坐标
     
    
- 
    
     
    
    
     
      3.将点坐标放在列表中
     
    
- 
    
     
    
    
     
      '''
     
    
 
 box3 = [0, 0, 2, 2, 2, 0, 0, 2]   # 左上,右上,右下,左下
 box1 = np.array(box3).reshape(4, 2)  # 将8个点转换为4*2的矩阵形式
 poly1 = Polygon(box1).convex_hull 
 x, y = poly1.exterior.coords.xy
 print(x, y)
 # array('d', [0.0, 0.0, 2.0, 2.0, 0.0]) array('d', [0.0, 2.0, 2.0, 0.0, 0.0])
 xy = poly1.exterior.coords.xy
 print(*xy)  #同上  ,相当于先.exterior.coords.xy,再使用*取的内容
xy_list = list(zip(*poly1.exterior.coords.xy))  
 print(xy_list)#[(0.0, 0.0), (0.0, 2.0), (2.0, 2.0), (2.0, 0.0), (0.0, 0.0)]
 第四种,最简单直接
  
   - 
    
     
    
    
     
      xy = poly1.exterior.coords# 这里的xy是一个对象需要用list完成显示
     
    
- 
    
     
    
    
     
      print(list(xy)) #[(0.0, 0.0), (0.0, 2.0), (2.0, 2.0), (2.0, 0.0), (0.0, 0.0)]
     
    
 
 第五种
  
   - 
    
     
    
    
     
      xy = poly1.exterior.coords
     
    
- 
    
     
    
    
     
      for i,j in xy:
     
    
- 
    
     
    
    
     
          print(x,y)
     
    
 
 原文链接:https://blog.csdn.net/weixin_43794311/article/details/120783677
以下内容转自:
python Shapely包使用,实现多边形iou_未来男孩的博客-CSDN博客_python shapely
python Shapely 使用指南
 刚从学习了Shapely包使用,怕忘记,在这里记录一下。
 阅读目录
 1、引入包
 from shapely.geometry import Point
 from shapely.geometry import LineString
 2、共有的变量和方法
 object.area
Returns the area (float) of the object.
object.bounds
返回对象的(minx,miny,maxx,maxy)元组(float类型)
object.length
返回对象的长度
object.geom_type
返回对象类型
object.distance(other)
返回本对象和另一个对象的距离
object.representative_point()
Returns a cheaply computed point that is guaranteed to be within the geometric object.
  
   - 
    
     
    
    
     
      >>> from shapely.geometry import Point
     
    
- 
    
     
    
    
     
      >>> print Point(0,0).distance(Point(0,1))
     
    
- 
    
     
    
    
     
      1.0
     
    
- 
    
     
    
    
     
      >>> from shapely.geometry import LineString
     
    
- 
    
     
    
    
     
      >>> line = LineString([(0,0), (1,1), (1,2)])
     
    
- 
    
     
    
    
     
      >>> line.area
     
    
- 
    
     
    
    
     
      0.0
     
    
- 
    
     
    
    
     
      >>> line.bounds
     
    
- 
    
     
    
    
     
      (0.0, 0.0, 1.0, 2.0)
     
    
- 
    
     
    
    
     
      >>> line.length
     
    
- 
    
     
    
    
     
      2.414213562373095
     
    
- 
    
     
    
    
     
      >>> line.geom_type
     
    
- 
    
     
    
    
     
      'LineString'
     
    
 - 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
3、Point
 class Point(coordinates)
三种赋值方式
  
   - 
    
     
    
    
     
      >>> point = Point(0,0)
     
    
- 
    
     
    
    
     
      >>> point_2 = Point((0,0))
     
    
- 
    
     
    
    
     
      >>> point_3 = Point(point)
     
    
 - 1
- 2
- 3
一个点对象有area和长度都为0
  
   - 
    
     
    
    
     
      >>> point.area
     
    
- 
    
     
    
    
     
      0.0
     
    
- 
    
     
    
    
     
      >>> point.length
     
    
- 
    
     
    
    
     
      0.0
     
    
 坐标可以通过coords或x、y、z得到
  
   - 
    
     
    
    
     
      >>> p = Point(2,3)
     
    
- 
    
     
    
    
     
      >>> p.coords
     
    
- 
    
     
    
    
     
      <shapely.coords.CoordinateSequence object at 0x7ffbc3d60dd0>
     
    
- 
    
     
    
    
     
      >>> list(p.coords)
     
    
- 
    
     
    
    
     
      [(2.0, 3.0)]
     
    
- 
    
     
    
    
     
      >>> p.x
     
    
- 
    
     
    
    
     
      2.0
     
    
- 
    
     
    
    
     
      >>> p.y
     
    
- 
    
     
    
    
     
      3.0
     
    
 - 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
coords可以被切片
  
   - 
    
     
    
    
     
      >>> p.coords[:]
     
    
- 
    
     
    
    
     
      [(2.0, 3.0)]
     
    
 - 1
- 2
4、LineStrings
 LineStrings构造函数传入参数是2个或多个点序列
一个LineStrings对象area为0,长度非0
  
   - 
    
     
    
    
     
      >>> line = LineString([(0,0), (0,1), (1,2)])
     
    
- 
    
     
    
    
     
      >>> line.area
     
    
- 
    
     
    
    
     
      0.0
     
    
- 
    
     
    
    
     
      >>> line.length
     
    
- 
    
     
    
    
     
      2.414213562373095
     
    
 获得坐标
  
   - 
    
     
    
    
     
      >>> line.coords[:]
     
    
- 
    
     
    
    
     
      [(0.0, 0.0), (0.0, 1.0), (1.0, 2.0)]
     
    
- 
    
     
    
    
     
        >>> list(line.coords)
     
    
- 
    
     
    
    
       [(0.0, 0.0), (0.0, 1.0), (1.0, 2.0)]
     
    
 - 1
- 2
- 3
- 4
LineString依然可以接受一个同类型对象
  
   - 
    
     
    
    
     
      >>> line2 = LineString(line)
     
    
- 
    
     
    
    
     
      >>> line2.coords[:]
     
    
- 
    
     
    
    
     
      [(0.0, 0.0), (0.0, 1.0), (1.0, 2.0)]
     
    
 - 1
- 2
- 3
5、常见格式转换
 wkt: Well Know Text
wkb: Well Kown Binary
  
   - 
    
     
    
    
     
      >>> Point(1,1).wkt
     
    
- 
    
     
    
    
     
      'POINT (1 1)'
     
    
- 
    
     
    
    
     
      >>> Point(1,1).wkb
     
    
- 
    
     
    
    
     
      '\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\xf0?'
     
    
- 
    
     
    
    
     
      >>> Point(1,1).wkb.encode('hex')
     
    
- 
    
     
    
    
     
      '0101000000000000000000f03f000000000000f03f'
     
    
- 
    
     
    
    
     
      >>> 
     
    
- 
    
     
    
    
     
      >>> Point(1,1).wkb.encode('hex')
     
    
- 
    
     
    
    
     
      '0101000000000000000000f03f000000000000f03f'
     
    
 两者都有loads和dumps方法
对于wkt
  
   - 
    
     
    
    
     
      >>> from shapely.wkt import dumps, loads
     
    
- 
    
     
    
    
     
      >>> s = dumps(Point(1,2))
     
    
- 
    
     
    
    
     
      >>> s
     
    
- 
    
     
    
    
     
      'POINT (1.0000000000000000 2.0000000000000000)'
     
    
- 
    
     
    
    
     
      >>> ss = loads(s)
     
    
- 
    
     
    
    
     
      >>> ss
     
    
- 
    
     
    
    
     
      <shapely.geometry.point.Point object at 0x7ffbc3d783d0>
     
    
- 
    
     
    
    
     
      >>> ss.coords[:]
     
    
- 
    
     
    
    
     
      [(1.0, 2.0)]
     
    
 对于wkb
  
   - 
    
     
    
    
     
      >>> from shapely.wkb import dumps, loads
     
    
- 
    
     
    
    
     
      >>> s = dumps(Point(1,2), hex=True)
     
    
- 
    
     
    
    
     
      >>> s
     
    
- 
    
     
    
    
     
      '0101000000000000000000F03F0000000000000040'
     
    
- 
    
     
    
    
     
      >>> ss = loads(s, hex=True)
     
    
- 
    
     
    
    
     
      >>> ss
     
    
- 
    
     
    
    
     
      <shapely.geometry.point.Point object at 0x7ffbc3d78790>
     
    
- 
    
     
    
    
     
      >>> ss.coords
     
    
- 
    
     
    
    
     
      <shapely.coords.CoordinateSequence object at 0x7ffbc3d783d0>
     
    
- 
    
     
    
    
     
      >>> ss.coords[:]
     
    
- 
    
     
    
    
     
      [(1.0, 2.0)]
     
    
 补充代码:
  
   - 
    
     
    
    
     
      # ------------------------------------------------------------------------------------------------------------------
     
    
- 
    
     
    
    
     
      # 在目标检测中一个很重要的问题就是NMS及IOU计算,而一般所说的目标检测检测的box是规则矩形框,计算IOU也非常简单,有两种方法:
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      # 1. 两个矩形的宽之和减去组合后的矩形的宽就是重叠矩形的宽,同比重叠矩形的高
     
    
- 
    
     
    
    
     
      # IOU = 交集部分/包含两个四边形最小多边形的面积
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      # 2. 右下角的minx减去左上角的maxx就是重叠矩形的宽,同比高
     
    
- 
    
     
    
    
     
      # IOU = 重叠面积 / (两矩形面积和—重叠面积)
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      # 不规则四边形就不能通过这种方式来计算,python的shapely包可以直接做到,下面给出的代码和注释
     
    
- 
    
     
    
    
     
      # 来自:白翔老师的textBoxes++论文源码,
     
    
- 
    
     
    
    
     
      # ------------------------------------------------------------------------------------------------------------------
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      import numpy as np
     
    
- 
    
     
    
    
     
      import shapely
     
    
- 
    
     
    
    
     
      from shapely.geometry import Polygon, MultiPoint  # 多边形
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      line1 = [2, 0, 2, 2, 0, 0, 0, 2]  # 四边形四个点坐标的一维数组表示,[x,y,x,y....];随意分别放入框的四个角坐标
     
    
- 
    
     
    
    
     
      a = np.array(line1).reshape(4, 2)  # 四边形二维坐标表示
     
    
- 
    
     
    
    
     
      poly1 = Polygon(a).convex_hull  # python四边形对象,会自动计算四个点,最后四个点顺序为:左上 左下 右下 右上 左上
     
    
- 
    
     
    
    
     
      print(Polygon(a).convex_hull)  # 可以打印看看是不是这样子(0 0, 0 2, 2 2, 2 0, 0 0)
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      line2 = [1, 1, 4, 1, 4, 4, 1, 4]
     
    
- 
    
     
    
    
     
      b = np.array(line2).reshape(4, 2)
     
    
- 
    
     
    
    
     
      poly2 = Polygon(b).convex_hull
     
    
- 
    
     
    
    
     
      print(Polygon(b).convex_hull)
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      union_poly = np.concatenate((a, b))  # 合并两个box坐标,变为8*2
     
    
- 
    
     
    
    
     
      print(union_poly)
     
    
- 
    
     
    
    
     
      print(MultiPoint(union_poly).convex_hull)  # 包含两四边形最小的多边形点;(0 0, 0 2, 1 4, 4 4, 4 1, 2 0, 0 0)
     
    
- 
    
     
    
    
     
      if not poly1.intersects(poly2):  # 如果两四边形不相交
     
    
- 
    
     
    
    
     
          iou = 0
     
    
- 
    
     
    
    
     
      else:
     
    
- 
    
     
    
    
         try:
     
    
- 
    
     
    
    
     
              inter_area = poly1.intersection(poly2).area  # 相交面积
     
    
- 
    
     
    
    
             print(inter_area)
     
    
- 
    
     
    
    
             # union_area = poly1.area + poly2.area - inter_area
     
    
- 
    
     
    
    
     
              union_area = MultiPoint(union_poly).convex_hull.area  # 最小多边形点面积
     
    
- 
    
     
    
    
             print(union_area)
     
    
- 
    
     
    
    
             if union_area == 0:
     
    
- 
    
     
    
    
     
                  iou = 0
     
    
- 
    
     
    
    
             # iou = float(inter_area) / (union_area-inter_area) #错了
     
    
- 
    
     
    
    
     
              iou = float(inter_area) / union_area
     
    
- 
    
     
    
    
             # iou=float(inter_area) /(poly1.area+poly2.area-inter_area)
     
    
- 
    
     
    
    
             # 源码中给出了两种IOU计算方式,第一种计算的是: 交集部分/包含两个四边形最小多边形的面积
     
    
- 
    
     
    
    
             # 第二种: 交集 / 并集(常见矩形框IOU计算方式)
     
    
- 
    
     
    
    
         except shapely.geos.TopologicalError:
     
    
- 
    
     
    
    
             print('shapely.geos.TopologicalError occured, iou set to 0')
     
    
- 
    
     
    
    
     
              iou = 0
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      print(a)
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      print(iou)
     
    
 文章来源: blog.csdn.net,作者:AI视觉网奇,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/jacke121/article/details/125039344
- 点赞
- 收藏
- 关注作者
 
             
           
评论(0)