-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Add] Add rotate iou cpu evaluation on kitti dateset
- Loading branch information
Showing
2 changed files
with
267 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
252 changes: 252 additions & 0 deletions
252
mmdet3d/evaluation/functional/kitti_utils/rotate_iou_cpu.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,252 @@ | ||
# Copyright (c) OpenMMLab. All rights reserved. | ||
##################### | ||
# Based on https://github.com/hongzhenwang/RRPN-revise | ||
# Licensed under The MIT License | ||
# Author: yanyan, [email protected] | ||
##################### | ||
import math | ||
import numpy as np | ||
|
||
|
||
def div_up(m, n): | ||
return m // n + (m % n > 0) | ||
|
||
def trangle_area(a, b, c): | ||
return ((a[0] - c[0]) * (b[1] - c[1]) - (a[1] - c[1]) * | ||
(b[0] - c[0])) / 2.0 | ||
|
||
|
||
def area(int_pts, num_of_inter): | ||
area_val = 0.0 | ||
for i in range(num_of_inter - 2): | ||
area_val += abs( | ||
trangle_area(int_pts[:2], int_pts[2 * i + 2:2 * i + 4], | ||
int_pts[2 * i + 4:2 * i + 6])) | ||
return area_val | ||
|
||
|
||
def sort_vertex_in_convex_polygon(int_pts, num_of_inter): | ||
if num_of_inter > 0: | ||
center = np.zeros((2, ), dtype=np.float32) | ||
center[:] = 0.0 | ||
for i in range(num_of_inter): | ||
center[0] += int_pts[2 * i] | ||
center[1] += int_pts[2 * i + 1] | ||
center[0] /= num_of_inter | ||
center[1] /= num_of_inter | ||
v = np.zeros((2, ), dtype=np.float32) | ||
vs = np.zeros((16, ), dtype=np.float32) | ||
for i in range(num_of_inter): | ||
v[0] = int_pts[2 * i] - center[0] | ||
v[1] = int_pts[2 * i + 1] - center[1] | ||
d = math.sqrt(v[0] * v[0] + v[1] * v[1]) | ||
v[0] = v[0] / d | ||
v[1] = v[1] / d | ||
if v[1] < 0: | ||
v[0] = -2 - v[0] | ||
vs[i] = v[0] | ||
j = 0 | ||
temp = 0 | ||
for i in range(1, num_of_inter): | ||
if vs[i - 1] > vs[i]: | ||
temp = vs[i] | ||
tx = int_pts[2 * i] | ||
ty = int_pts[2 * i + 1] | ||
j = i | ||
while j > 0 and vs[j - 1] > temp: | ||
vs[j] = vs[j - 1] | ||
int_pts[j * 2] = int_pts[j * 2 - 2] | ||
int_pts[j * 2 + 1] = int_pts[j * 2 - 1] | ||
j -= 1 | ||
|
||
vs[j] = temp | ||
int_pts[j * 2] = tx | ||
int_pts[j * 2 + 1] = ty | ||
|
||
|
||
def line_segment_intersection(pts1, pts2, i, j, temp_pts): | ||
A = np.zeros((2, ), dtype=np.float32) | ||
B = np.zeros((2, ), dtype=np.float32) | ||
C = np.zeros((2, ), dtype=np.float32) | ||
D = np.zeros((2, ), dtype=np.float32) | ||
|
||
A[0] = pts1[2 * i] | ||
A[1] = pts1[2 * i + 1] | ||
|
||
B[0] = pts1[2 * ((i + 1) % 4)] | ||
B[1] = pts1[2 * ((i + 1) % 4) + 1] | ||
|
||
C[0] = pts2[2 * j] | ||
C[1] = pts2[2 * j + 1] | ||
|
||
D[0] = pts2[2 * ((j + 1) % 4)] | ||
D[1] = pts2[2 * ((j + 1) % 4) + 1] | ||
BA0 = B[0] - A[0] | ||
BA1 = B[1] - A[1] | ||
DA0 = D[0] - A[0] | ||
CA0 = C[0] - A[0] | ||
DA1 = D[1] - A[1] | ||
CA1 = C[1] - A[1] | ||
acd = DA1 * CA0 > CA1 * DA0 | ||
bcd = (D[1] - B[1]) * (C[0] - B[0]) > (C[1] - B[1]) * (D[0] - B[0]) | ||
if acd != bcd: | ||
abc = CA1 * BA0 > BA1 * CA0 | ||
abd = DA1 * BA0 > BA1 * DA0 | ||
if abc != abd: | ||
DC0 = D[0] - C[0] | ||
DC1 = D[1] - C[1] | ||
ABBA = A[0] * B[1] - B[0] * A[1] | ||
CDDC = C[0] * D[1] - D[0] * C[1] | ||
DH = BA1 * DC0 - BA0 * DC1 | ||
Dx = ABBA * DC0 - BA0 * CDDC | ||
Dy = ABBA * DC1 - BA1 * CDDC | ||
temp_pts[0] = Dx / DH | ||
temp_pts[1] = Dy / DH | ||
return True | ||
return False | ||
|
||
|
||
def line_segment_intersection_v1(pts1, pts2, i, j, temp_pts): | ||
a = np.zeros((2, ), dtype=np.float32) | ||
b = np.zeros((2, ), dtype=np.float32) | ||
c = np.zeros((2, ), dtype=np.float32) | ||
d = np.zeros((2, ), dtype=np.float32) | ||
|
||
a[0] = pts1[2 * i] | ||
a[1] = pts1[2 * i + 1] | ||
|
||
b[0] = pts1[2 * ((i + 1) % 4)] | ||
b[1] = pts1[2 * ((i + 1) % 4) + 1] | ||
|
||
c[0] = pts2[2 * j] | ||
c[1] = pts2[2 * j + 1] | ||
|
||
d[0] = pts2[2 * ((j + 1) % 4)] | ||
d[1] = pts2[2 * ((j + 1) % 4) + 1] | ||
|
||
area_abc = trangle_area(a, b, c) | ||
area_abd = trangle_area(a, b, d) | ||
|
||
if area_abc * area_abd >= 0: | ||
return False | ||
|
||
area_cda = trangle_area(c, d, a) | ||
area_cdb = area_cda + area_abc - area_abd | ||
|
||
if area_cda * area_cdb >= 0: | ||
return False | ||
t = area_cda / (area_abd - area_abc) | ||
|
||
dx = t * (b[0] - a[0]) | ||
dy = t * (b[1] - a[1]) | ||
temp_pts[0] = a[0] + dx | ||
temp_pts[1] = a[1] + dy | ||
return True | ||
|
||
|
||
def point_in_quadrilateral(pt_x, pt_y, corners): | ||
ab0 = corners[2] - corners[0] | ||
ab1 = corners[3] - corners[1] | ||
|
||
ad0 = corners[6] - corners[0] | ||
ad1 = corners[7] - corners[1] | ||
|
||
ap0 = pt_x - corners[0] | ||
ap1 = pt_y - corners[1] | ||
|
||
abab = ab0 * ab0 + ab1 * ab1 | ||
abap = ab0 * ap0 + ab1 * ap1 | ||
adad = ad0 * ad0 + ad1 * ad1 | ||
adap = ad0 * ap0 + ad1 * ap1 | ||
|
||
return abab >= abap and abap >= 0 and adad >= adap and adap >= 0 | ||
|
||
|
||
def quadrilateral_intersection(pts1, pts2, int_pts): | ||
num_of_inter = 0 | ||
for i in range(4): | ||
if point_in_quadrilateral(pts1[2 * i], pts1[2 * i + 1], pts2): | ||
int_pts[num_of_inter * 2] = pts1[2 * i] | ||
int_pts[num_of_inter * 2 + 1] = pts1[2 * i + 1] | ||
num_of_inter += 1 | ||
if point_in_quadrilateral(pts2[2 * i], pts2[2 * i + 1], pts1): | ||
int_pts[num_of_inter * 2] = pts2[2 * i] | ||
int_pts[num_of_inter * 2 + 1] = pts2[2 * i + 1] | ||
num_of_inter += 1 | ||
temp_pts = np.zeros((2, ), dtype=np.float32) | ||
for i in range(4): | ||
for j in range(4): | ||
has_pts = line_segment_intersection(pts1, pts2, i, j, temp_pts) | ||
if has_pts: | ||
int_pts[num_of_inter * 2] = temp_pts[0] | ||
int_pts[num_of_inter * 2 + 1] = temp_pts[1] | ||
num_of_inter += 1 | ||
|
||
return num_of_inter | ||
|
||
|
||
def rbbox_to_corners(corners, rbbox): | ||
# generate clockwise corners and rotate it clockwise | ||
angle = rbbox[4] | ||
a_cos = math.cos(angle) | ||
a_sin = math.sin(angle) | ||
center_x = rbbox[0] | ||
center_y = rbbox[1] | ||
x_d = rbbox[2] | ||
y_d = rbbox[3] | ||
corners_x = np.zeros((4, ), dtype=np.float32) | ||
corners_y = np.zeros((4, ), dtype=np.float32) | ||
corners_x[0] = -x_d / 2 | ||
corners_x[1] = -x_d / 2 | ||
corners_x[2] = x_d / 2 | ||
corners_x[3] = x_d / 2 | ||
corners_y[0] = -y_d / 2 | ||
corners_y[1] = y_d / 2 | ||
corners_y[2] = y_d / 2 | ||
corners_y[3] = -y_d / 2 | ||
for i in range(4): | ||
corners[2 * | ||
i] = a_cos * corners_x[i] + a_sin * corners_y[i] + center_x | ||
corners[2 * i | ||
+ 1] = -a_sin * corners_x[i] + a_cos * corners_y[i] + center_y | ||
|
||
|
||
def inter(rbbox1, rbbox2): | ||
corners1 = np.zeros((8, ), dtype=np.float32) | ||
corners2 = np.zeros((8, ), dtype=np.float32) | ||
intersection_corners = np.zeros((16, ), dtype=np.float32) | ||
|
||
rbbox_to_corners(corners1, rbbox1) | ||
rbbox_to_corners(corners2, rbbox2) | ||
|
||
num_intersection = quadrilateral_intersection(corners1, corners2, | ||
intersection_corners) | ||
sort_vertex_in_convex_polygon(intersection_corners, num_intersection) | ||
# print(intersection_corners.reshape([-1, 2])[:num_intersection]) | ||
|
||
return area(intersection_corners, num_intersection) | ||
|
||
|
||
def devRotateIoUEval(rbox1, rbox2, criterion=-1): | ||
area1 = rbox1[2] * rbox1[3] | ||
area2 = rbox2[2] * rbox2[3] | ||
area_inter = inter(rbox1, rbox2) | ||
if criterion == -1: | ||
return area_inter / (area1 + area2 - area_inter) | ||
elif criterion == 0: | ||
return area_inter / area1 | ||
elif criterion == 1: | ||
return area_inter / area2 | ||
else: | ||
return area_inter | ||
|
||
|
||
def rotate_iou_cpu_eval(dev_boxes, dev_query_boxes, criterion=-1): | ||
num_boxes = dev_boxes.shape[0] | ||
num_qboxes = dev_query_boxes.shape[0] | ||
dev_iou = np.zeros((num_boxes, num_qboxes)) | ||
for box_i in range(num_boxes): | ||
for qbox_i in range(num_qboxes): | ||
dev_iou[box_i, qbox_i] = devRotateIoUEval(dev_query_boxes[qbox_i], dev_boxes[box_i], criterion) | ||
|
||
return dev_iou |