自动驾驶多边形iou计算Shapely库笔记

举报
风吹稻花香 发表于 2022/05/31 00:52:18 2022/05/31
【摘要】 参考:https://cloud.tencent.com/developer/ask/42755,https://blog.csdn.net/u014421797/article/details/89501572, https://www.itranslater.com/qa/details/2582747861733606400 ...

参考:https://cloud.tencent.com/developer/ask/42755,https://blog.csdn.net/u014421797/article/details/89501572,
https://www.itranslater.com/qa/details/2582747861733606400

两个矩形的交并比计算交简单
直接复制第二个参考链接中的代码


  
  1. def IoU(box1, box2):
  2.     '''
  3.     计算两个矩形框的交并比
  4.     :param box1: list,第一个矩形框的左上角和右下角坐标
  5.     :param box2: list,第二个矩形框的左上角和右下角坐标
  6.     :return: 两个矩形框的交并比iou
  7.     '''
  8.     x1 = max(box1[0], box2[0])   # 交集左上角x
  9.     x2 = min(box1[2], box2[2])   # 交集右下角x
  10.     y1 = max(box1[1], box2[1])   # 交集左上角y
  11.     y2 = min(box1[3], box2[3])   # 交集右下角y
  12.  
  13.     overlap = max(0., x2-x1) * max(0., y2-y1)
  14.     union = (box1[2]-box1[0]) * (box1[3]-box1[1]) \
  15.             + (box2[2]-box2[0]) * (box2[3]-box2[1]) \
  16.             - overlap
  17.  
  18.     return overlap/union
  19. if __name__ == '__main__':
  20.     # box = [左上角x1,左上角y1,右下角x2,右下角y2]
  21.     box1 = [10, 0, 15, 10]
  22.     box2 = [12, 5, 20, 15]
  23.     iou = IoU(box1, box2)



非规则四边形的IOU计算
测试发现
Polygon().convex_hull,排序的结果特点,以最低点的一点为起点,(若y值一样小,则比较x较小的作为起点)顺时针排列所有点
1


  
  1. import shapely
  2. import numpy as np
  3. from shapely.geometry import Polygon, MultiPoint, mapping 
  4. def bbox_iou_eval(box1, box2):
  5.     box1 = np.array(box1).reshape(4, 2)
  6.     poly1 = Polygon(box1).convex_hull #POLYGON ((0 0, 0 2, 2 2, 2 0, 0 0))
  7.     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)),)
  8.     poly_arr = np.array(poly1)
  9.     box2 = np.array(box2).reshape(4, 2)
  10.     poly2 = Polygon(box2).convex_hull
  11.     if not poly1.intersects(poly2):  # 如果两四边形不相交
  12.         iou = 0
  13.     else:
  14.         try:
  15.             inter_area = poly1.intersection(poly2).area  # 相交面积
  16.             iou = float(inter_area) / (poly1.area + poly2.area - inter_area)
  17.         except shapely.geos.TopologicalError:
  18.             print('shapely.geos.TopologicalError occured, iou set to 0')
  19.             iou = 0
  20.     return iou
  21. if __name__ == '__main__':
  22.     # box = [四个点的坐标,顺序无所谓]
  23.     box3 = [0, 0, 2, 2, 2, 0, 0, 2]   # 左上,右上,右下,左下
  24.     box4 = [1, 1, 1, 3, 3, 3, 3, 1]
  25.     iou = bbox_iou_eval(box3, box4)
  26.     print(iou)



Polygon类型中的坐标数据的获得
有时候想要用到到排序好的几个坐标数据,但Polygon中没有直接得到的坐标点的方法,下面是几种方法
第一种:使用mapping
总结:1.可使用nump的功能,将坐标点转化为n*2的形式,
2.Polygon(n*2).convex_hull对坐标点进行排序
3.使用mapping得到排序好对象的内容
4.使用字典和元组切片的方式得到坐标点
为了防止坐标点会多一个,为了闭合,切片方式中:-1
 


  
  1. from shapely.geometry import Polygon, MultiPoint, mapping 
  2. box3 = [0, 0, 2, 2, 2, 0, 0, 2]
  3. box1 = np.array(box1).reshape(4, 2)
  4. poly1 = Polygon(box1).convex_hull
  5. print(poly1)        # POLYGON ((0 0, 0 2, 2 2, 2 0, 0 0))
  6. map_poly = mapping(poly1) # 这时的值就是一个字典可以通过字典方式访问
  7. '''{'type': 'Polygon', 'coordinates': (((0.0, 0.0), (0.0, 2.0), (2.0, 2.0), (2.0, 0.0), (0.0, 0.0)),)}'''
  8. print(['coordinates'])   # 这是一个元组
  9. '''(((0.0, 0.0), (0.0, 2.0), (2.0, 2.0), (2.0, 0.0), (0.0, 0.0)),)'''
  10. print(map_poly['coordinates'][0][:-1])
  11. '''((0.0, 0.0), (0.0, 2.0), (2.0, 2.0), (2.0, 0.0)) '''



第二种:使用内部属性.exterior.coords.xy


  
  1. box3 = [0, 0, 2, 2, 2, 0, 0, 2]   # 左上,右上,右下,左下
  2. box1 = np.array(box3).reshape(4, 2)  # 将8个点转换为4*2的矩阵形式
  3. poly1 = Polygon(box1).convex_hull 
  4. x, y = poly1.exterior.coords.xy
  5. 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])
  6. print(list(x)) #[0.0, 0.0, 2.0, 2.0, 0.0]


第三种:使用指针*方式
解释:


  
  1. list(zip(*poly1.exterior.coords.xy))
  2. '''
  3. 1.*poly1.exterior.coords.xy,得到两个分开的arry类型的x,y的数组
  4. 2.使用zip将两个一维数组压缩成一对数值为一个元组的多个点坐标
  5. 3.将点坐标放在列表中
  6. '''



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

第四种,最简单直接


  
  1. xy = poly1.exterior.coords# 这里的xy是一个对象需要用list完成显示
  2. print(list(xy)) #[(0.0, 0.0), (0.0, 2.0), (2.0, 2.0), (2.0, 0.0), (0.0, 0.0)]



第五种


  
  1. xy = poly1.exterior.coords
  2. for i,j in xy:
  3.     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.


  
  1. >>> from shapely.geometry import Point
  2. >>> print Point(0,0).distance(Point(0,1))
  3. 1.0
  4. >>> from shapely.geometry import LineString
  5. >>> line = LineString([(0,0), (1,1), (1,2)])
  6. >>> line.area
  7. 0.0
  8. >>> line.bounds
  9. (0.0, 0.0, 1.0, 2.0)
  10. >>> line.length
  11. 2.414213562373095
  12. >>> line.geom_type
  13. 'LineString'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3、Point
class Point(coordinates)

三种赋值方式


  
  1. >>> point = Point(0,0)
  2. >>> point_2 = Point((0,0))
  3. >>> point_3 = Point(point)
  • 1
  • 2
  • 3

一个点对象有area和长度都为0


  
  1. >>> point.area
  2. 0.0
  3. >>> point.length
  4. 0.0

坐标可以通过coords或x、y、z得到


  
  1. >>> p = Point(2,3)
  2. >>> p.coords
  3. <shapely.coords.CoordinateSequence object at 0x7ffbc3d60dd0>
  4. >>> list(p.coords)
  5. [(2.0, 3.0)]
  6. >>> p.x
  7. 2.0
  8. >>> p.y
  9. 3.0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

coords可以被切片


  
  1. >>> p.coords[:]
  2. [(2.0, 3.0)]
  • 1
  • 2

4、LineStrings
LineStrings构造函数传入参数是2个或多个点序列

一个LineStrings对象area为0,长度非0


  
  1. >>> line = LineString([(0,0), (0,1), (1,2)])
  2. >>> line.area
  3. 0.0
  4. >>> line.length
  5. 2.414213562373095

获得坐标


  
  1. >>> line.coords[:]
  2. [(0.0, 0.0), (0.0, 1.0), (1.0, 2.0)]
  3. >>> list(line.coords)
  4. [(0.0, 0.0), (0.0, 1.0), (1.0, 2.0)]
  • 1
  • 2
  • 3
  • 4

LineString依然可以接受一个同类型对象


  
  1. >>> line2 = LineString(line)
  2. >>> line2.coords[:]
  3. [(0.0, 0.0), (0.0, 1.0), (1.0, 2.0)]
  • 1
  • 2
  • 3

5、常见格式转换
wkt: Well Know Text

wkb: Well Kown Binary


  
  1. >>> Point(1,1).wkt
  2. 'POINT (1 1)'
  3. >>> Point(1,1).wkb
  4. '\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\xf0?'
  5. >>> Point(1,1).wkb.encode('hex')
  6. '0101000000000000000000f03f000000000000f03f'
  7. >>>
  8. >>> Point(1,1).wkb.encode('hex')
  9. '0101000000000000000000f03f000000000000f03f'

两者都有loads和dumps方法

对于wkt


  
  1. >>> from shapely.wkt import dumps, loads
  2. >>> s = dumps(Point(1,2))
  3. >>> s
  4. 'POINT (1.0000000000000000 2.0000000000000000)'
  5. >>> ss = loads(s)
  6. >>> ss
  7. <shapely.geometry.point.Point object at 0x7ffbc3d783d0>
  8. >>> ss.coords[:]
  9. [(1.0, 2.0)]

对于wkb


  
  1. >>> from shapely.wkb import dumps, loads
  2. >>> s = dumps(Point(1,2), hex=True)
  3. >>> s
  4. '0101000000000000000000F03F0000000000000040'
  5. >>> ss = loads(s, hex=True)
  6. >>> ss
  7. <shapely.geometry.point.Point object at 0x7ffbc3d78790>
  8. >>> ss.coords
  9. <shapely.coords.CoordinateSequence object at 0x7ffbc3d783d0>
  10. >>> ss.coords[:]
  11. [(1.0, 2.0)]

补充代码:


  
  1. # ------------------------------------------------------------------------------------------------------------------
  2. # 在目标检测中一个很重要的问题就是NMS及IOU计算,而一般所说的目标检测检测的box是规则矩形框,计算IOU也非常简单,有两种方法:
  3. # 1. 两个矩形的宽之和减去组合后的矩形的宽就是重叠矩形的宽,同比重叠矩形的高
  4. # IOU = 交集部分/包含两个四边形最小多边形的面积
  5. # 2. 右下角的minx减去左上角的maxx就是重叠矩形的宽,同比高
  6. # IOU = 重叠面积 / (两矩形面积和—重叠面积)
  7. # 不规则四边形就不能通过这种方式来计算,python的shapely包可以直接做到,下面给出的代码和注释
  8. # 来自:白翔老师的textBoxes++论文源码,
  9. # ------------------------------------------------------------------------------------------------------------------
  10. import numpy as np
  11. import shapely
  12. from shapely.geometry import Polygon, MultiPoint # 多边形
  13. line1 = [2, 0, 2, 2, 0, 0, 0, 2] # 四边形四个点坐标的一维数组表示,[x,y,x,y....];随意分别放入框的四个角坐标
  14. a = np.array(line1).reshape(4, 2) # 四边形二维坐标表示
  15. poly1 = Polygon(a).convex_hull # python四边形对象,会自动计算四个点,最后四个点顺序为:左上 左下 右下 右上 左上
  16. print(Polygon(a).convex_hull) # 可以打印看看是不是这样子(0 0, 0 2, 2 2, 2 0, 0 0)
  17. line2 = [1, 1, 4, 1, 4, 4, 1, 4]
  18. b = np.array(line2).reshape(4, 2)
  19. poly2 = Polygon(b).convex_hull
  20. print(Polygon(b).convex_hull)
  21. union_poly = np.concatenate((a, b)) # 合并两个box坐标,变为8*2
  22. print(union_poly)
  23. print(MultiPoint(union_poly).convex_hull) # 包含两四边形最小的多边形点;(0 0, 0 2, 1 4, 4 4, 4 1, 2 0, 0 0)
  24. if not poly1.intersects(poly2): # 如果两四边形不相交
  25. iou = 0
  26. else:
  27. try:
  28. inter_area = poly1.intersection(poly2).area # 相交面积
  29. print(inter_area)
  30. # union_area = poly1.area + poly2.area - inter_area
  31. union_area = MultiPoint(union_poly).convex_hull.area # 最小多边形点面积
  32. print(union_area)
  33. if union_area == 0:
  34. iou = 0
  35. # iou = float(inter_area) / (union_area-inter_area) #错了
  36. iou = float(inter_area) / union_area
  37. # iou=float(inter_area) /(poly1.area+poly2.area-inter_area)
  38. # 源码中给出了两种IOU计算方式,第一种计算的是: 交集部分/包含两个四边形最小多边形的面积
  39. # 第二种: 交集 / 并集(常见矩形框IOU计算方式)
  40. except shapely.geos.TopologicalError:
  41. print('shapely.geos.TopologicalError occured, iou set to 0')
  42. iou = 0
  43. print(a)
  44. print(iou)

文章来源: blog.csdn.net,作者:AI视觉网奇,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/jacke121/article/details/125039344

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

举报
请填写举报理由
0/200