File size: 5,751 Bytes
88b0dcb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"""
@date: 2021/6/29
@description:
The method with "_floorplan" suffix is only for comparison, which is used for calculation in LED2-net.
However, the floorplan is affected by show_radius. Setting too large will result in the decrease of accuracy,
and setting too small will result in the failure of calculation beyond the range.
"""
import numpy as np
from shapely.geometry import Polygon


def calc_inter_area(dt_xz, gt_xz):
    """
    :param dt_xz: Prediction boundaries can also be corners, format: [[x1, z1], [x2, z2], ...]
    :param gt_xz: Ground truth boundaries can also be corners, format: [[x1, z1], [x2, z2], ...]
    :return:
    """
    dt_polygon = Polygon(dt_xz)
    gt_polygon = Polygon(gt_xz)

    dt_area = dt_polygon.area
    gt_area = gt_polygon.area
    inter_area = dt_polygon.intersection(gt_polygon).area
    return dt_area, gt_area, inter_area


def calc_IoU_2D(dt_xz, gt_xz):
    """
    :param dt_xz: Prediction boundaries can also be corners, format: [[x1, z1], [x2, z2], ...]
    :param gt_xz: Ground truth boundaries can also be corners, format: [[x1, z1], [x2, z2], ...]
    :return:
    """
    dt_area, gt_area, inter_area = calc_inter_area(dt_xz, gt_xz)
    iou_2d = inter_area / (gt_area + dt_area - inter_area)
    return iou_2d


def calc_IoU_3D(dt_xz, gt_xz, dt_height, gt_height):
    """
    :param dt_xz: Prediction boundaries can also be corners, format: [[x1, z1], [x2, z2], ...]
    :param gt_xz: Ground truth boundaries can also be corners, format: [[x1, z1], [x2, z2], ...]
    :param dt_height:
    :param gt_height:
    :return:
    """
    dt_area, gt_area, inter_area = calc_inter_area(dt_xz, gt_xz)
    dt_volume = dt_area * dt_height
    gt_volume = gt_area * gt_height
    inter_volume = inter_area * min(dt_height, gt_height)
    iou_3d = inter_volume / (dt_volume + gt_volume - inter_volume)
    return iou_3d


def calc_IoU(dt_xz, gt_xz, dt_height, gt_height):
    """
    :param dt_xz: Prediction boundaries can also be corners, format: [[x1, z1], [x2, z2], ...]
    :param gt_xz: Ground truth boundaries can also be corners, format: [[x1, z1], [x2, z2], ...]
    :param dt_height:
    :param gt_height:
    :return:
    """
    dt_area, gt_area, inter_area = calc_inter_area(dt_xz, gt_xz)
    iou_2d = inter_area / (gt_area + dt_area - inter_area)

    dt_volume = dt_area * dt_height
    gt_volume = gt_area * gt_height
    inter_volume = inter_area * min(dt_height, gt_height)
    iou_3d = inter_volume / (dt_volume + gt_volume - inter_volume)

    return iou_2d, iou_3d


def calc_Iou_height(dt_height, gt_height):
    return min(dt_height, gt_height) / max(dt_height, gt_height)


# the following is for testing only
def calc_inter_area_floorplan(dt_floorplan, gt_floorplan):
    intersect = np.sum(np.logical_and(dt_floorplan, gt_floorplan))
    dt_area = np.sum(dt_floorplan)
    gt_area = np.sum(gt_floorplan)
    return dt_area, gt_area, intersect


def calc_IoU_2D_floorplan(dt_floorplan, gt_floorplan):
    dt_area, gt_area, inter_area = calc_inter_area_floorplan(dt_floorplan, gt_floorplan)
    iou_2d = inter_area / (gt_area + dt_area - inter_area)
    return iou_2d


def calc_IoU_3D_floorplan(dt_floorplan, gt_floorplan, dt_height, gt_height):
    dt_area, gt_area, inter_area = calc_inter_area_floorplan(dt_floorplan, gt_floorplan)
    dt_volume = dt_area * dt_height
    gt_volume = gt_area * gt_height
    inter_volume = inter_area * min(dt_height, gt_height)
    iou_3d = inter_volume / (dt_volume + gt_volume - inter_volume)
    return iou_3d


def calc_IoU_floorplan(dt_floorplan, gt_floorplan, dt_height, gt_height):
    dt_area, gt_area, inter_area = calc_inter_area_floorplan(dt_floorplan, gt_floorplan)
    iou_2d = inter_area / (gt_area + dt_area - inter_area)

    dt_volume = dt_area * dt_height
    gt_volume = gt_area * gt_height
    inter_volume = inter_area * min(dt_height, gt_height)
    iou_3d = inter_volume / (dt_volume + gt_volume - inter_volume)
    return iou_2d, iou_3d


if __name__ == '__main__':
    from visualization.floorplan import draw_floorplan, draw_iou_floorplan
    from visualization.boundary import draw_boundaries, corners2boundaries
    from utils.conversion import uv2xyz
    from utils.height import height2ratio

    # dummy data
    dt_floor_corners = np.array([[0.2, 0.7],
                                 [0.4, 0.7],
                                 [0.6, 0.7],
                                 [0.8, 0.7]])
    dt_height = 2.8

    gt_floor_corners = np.array([[0.3, 0.7],
                                 [0.5, 0.7],
                                 [0.7, 0.7],
                                 [0.9, 0.7]])
    gt_height = 3.2

    dt_xz = uv2xyz(dt_floor_corners)[..., ::2]
    gt_xz = uv2xyz(gt_floor_corners)[..., ::2]

    dt_floorplan = draw_floorplan(dt_xz, show=False, show_radius=1)
    gt_floorplan = draw_floorplan(gt_xz, show=False, show_radius=1)
    # dt_floorplan = draw_floorplan(dt_xz, show=False, show_radius=2)
    # gt_floorplan = draw_floorplan(gt_xz, show=False, show_radius=2)

    iou_2d, iou_3d = calc_IoU_floorplan(dt_floorplan, gt_floorplan, dt_height, gt_height)
    print('use floor plan image:', iou_2d, iou_3d)

    iou_2d, iou_3d = calc_IoU(dt_xz, gt_xz, dt_height, gt_height)
    print('use floor plan polygon:', iou_2d, iou_3d)

    draw_iou_floorplan(dt_xz, gt_xz, show=True, iou_2d=iou_2d, iou_3d=iou_3d)
    pano_bd = draw_boundaries(np.zeros([512, 1024, 3]), corners_list=[dt_floor_corners],
                              boundary_color=[0, 0, 1], ratio=height2ratio(dt_height), draw_corners=False)
    pano_bd = draw_boundaries(pano_bd, corners_list=[gt_floor_corners],
                              boundary_color=[0, 1, 0], ratio=height2ratio(gt_height), show=True, draw_corners=False)