参考: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较小的作为起点)顺时针排列所有点
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)