Takes an object's 3D box with the representation of [x,y,z,theta,l,w,h] and
convert it to the 8 corners of the 3D box, the box is in the camera coordinate
with right x, down y, front z
Returns:
corners_3d: (8,3) array inin rect camera coord
box corner order is like follows
1 -------- 0top is bottom because y direction is negative
/| /|2 -------- 3.||||.5 -------- 4|/ |/
6 -------- 7
rect/ref camera coord:
right x, down y, front z
x -> w, z -> l, y -> h
上面为作者定义了立方体的坐标系
def iou(box_a, box_b, metric='giou_3d'):
''' Compute 3D/2D bounding box IoU, only working for object parallel to ground
Input:
Box3D instances
Output:
iou_3d: 3D bounding box IoU
iou_2d: bird's eye view 2D bounding box IoU
box corner order is like follows
1 -------- 0 top is bottom because y direction is negative
/|/|
2 -------- 3 .||||. 5 -------- 4
|/|/
6 -------- 7
rect/ref camera coord:
right x, down y, front z
'''
# compute 2D related measures
boxa_bot, boxb_bot = compute_bottom(box_a, box_b)
I_2D = compute_inter_2D(boxa_bot, boxb_bot)
# only needed for GIoU
if 'giou' in metric:
C_2D = convex_area(boxa_bot, boxb_bot)
if '2d' in metric: # return 2D IoU/GIoU
U_2D = box_a.w * box_a.l + box_b.w * box_b.l - I_2D
if metric == 'iou_2d': return I_2D / U_2D
if metric == 'giou_2d': return I_2D / U_2D - (C_2D - U_2D) / C_2D
elif '3d' in metric: # return 3D IoU/GIoU
overlap_height = compute_height(box_a, box_b)
I_3D = I_2D * overlap_height
U_3D = box_a.w * box_a.l * box_a.h + box_b.w * box_b.l * box_b.h - I_3D
if metric == 'iou_3d': return I_3D / U_3D
if metric == 'giou_3d':
union_height = compute_height(box_a, box_b, inter=False)
C_3D = C_2D * union_height
return I_3D / U_3D - (C_3D - U_3D) / C_3D
else:
assert False, '%s is not supported' % space
其中
I_2D = compute_inter_2D(boxa_bot, boxb_bot)
defcompute_inter_2D(boxa_bottom, boxb_bottom):# computer intersection over union of two sets of bottom corner points
_, I_2D = convex_hull_intersection(boxa_bottom, boxb_bottom)# a slower version# from shapely.geometry import Polygon# reca, recb = Polygon(boxa_bottom), Polygon(boxb_bottom)# I_2D = reca.intersection(recb).areareturn I_2D
defconvex_hull_intersection(p1, p2):""" Compute area of two convex hull's intersection area.
p1,p2 are a list of (x,y) tuples of hull vertices.
return a list of (x,y) for the intersection and its volume
"""
inter_p = polygon_clip(p1,p2)if inter_p isnotNone:
hull_inter = ConvexHull(inter_p)return inter_p, hull_inter.volume
else:returnNone,0.0
其中
inter_p = polygon_clip(p1,p2)
defpolygon_clip(subjectPolygon, clipPolygon):""" Clip a polygon with another polygon.
Ref: https://rosettacode.org/wiki/Sutherland-Hodgman_polygon_clipping#Python
Args:
subjectPolygon: a list of (x,y) 2d points, any polygon.
clipPolygon: a list of (x,y) 2d points, has to be *convex*
Note:
**points have to be counter-clockwise ordered**
Return:
a list of (x,y) vertex point for the intersection polygon.
"""definside(p):return(cp2[0]- cp1[0])*(p[1]- cp1[1])>(cp2[1]- cp1[1])*(p[0]- cp1[0])defcomputeIntersection():
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):ifnot inside(s): outputList.append(computeIntersection())
outputList.append(e)elif inside(s): outputList.append(computeIntersection())
s = e
cp1 = cp2
iflen(outputList)==0:returnNonereturn(outputList)
import matplotlib.pyplot as plt
from pylab import mpl
mpl.rcParams['font.sans-serif']=['STZhongsong']# 指定默认字体:解决plot不能显示中文问题
mpl.rcParams['axes.unicode_minus']=False# 解决保存图像是负号'-'显示为方块的问题defclip(subjectPolygon, clipPolygon):definside(p):return(cp2[0]-cp1[0])*(p[1]-cp1[1])>(cp2[1]-cp1[1])*(p[0]-cp1[0])defcomputeIntersection():
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):ifnot inside(s):
outputList.append(computeIntersection())
outputList.append(e)elif inside(s):
outputList.append(computeIntersection())
s = e
cp1 = cp2
return(outputList)
coord =[(50,150),(200,50),(350,150),(350,300),(250,300),(200,250),(150,350),(100,250),(100,200)]
coord1 =[(100,100),(300,100),(300,300),(100,300)]
out = clip(coord, coord1)
out.append(out[0])#repeat the first point to create a 'closed loop'
xs2, ys2 =zip(*out)#create lists of x and y values
coord.append(coord[0])#repeat the first point to create a 'closed loop'
coord1.append(coord1[0])#repeat the first point to create a 'closed loop'
xs, ys =zip(*coord)#create lists of x and y values
xs1, ys1 =zip(*coord1)#create lists of x and y values
plt.figure()
plt.plot(xs, ys, label ="被裁剪凸边形", color ='r')
plt.plot(xs1, ys1, label ="裁剪凸边形", color ='g', linestyle='--')
plt.plot(xs2, ys2, label ="结果", color ='b')
plt.legend()
plt.show()# if you need...