CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hukaixuan19970627

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: hukaixuan19970627/yolov5_obb
Path: blob/master/DOTA_devkit/mAOE_evaluation.py
Views: 475
1
# --------------------------------------------------------
2
# mAOEevaluation
3
# --------------------------------------------------------
4
5
"""
6
To use the code, users should to config detpath, annopath and imagesetfile
7
detpath is the path for class result files. The evaluation is performed on the merging results.
8
"""
9
10
import numpy as np
11
import polyiou
12
from dota_poly2rbox import poly2rbox_single_v2, poly2rbox_single_v3
13
14
def parse_gt(filename):
15
"""
16
:param filename: ground truth file to parse
17
:return: all instances in a picture
18
"""
19
objects = []
20
with open(filename, 'r') as f:
21
while True:
22
line = f.readline()
23
if line:
24
splitlines = line.strip().split(' ')
25
object_struct = {}
26
if (len(splitlines) < 9):
27
continue
28
object_struct['name'] = splitlines[8]
29
30
if (len(splitlines) == 9):
31
object_struct['difficult'] = 0
32
elif (len(splitlines) == 10):
33
object_struct['difficult'] = int(splitlines[9])
34
object_struct['bbox'] = [float(splitlines[0]),
35
float(splitlines[1]),
36
float(splitlines[2]),
37
float(splitlines[3]),
38
float(splitlines[4]),
39
float(splitlines[5]),
40
float(splitlines[6]),
41
float(splitlines[7])]
42
objects.append(object_struct)
43
else:
44
break
45
return objects
46
47
48
def aoe_eval(detpath,
49
annopath,
50
imagesetfile,
51
classname,
52
# cachedir,
53
ovthresh=0.5):
54
"""rec, prec, ap = aoe_eval(detpath,
55
annopath,
56
imagesetfile,
57
classname,
58
[ovthresh])
59
60
detpath: Path to detections
61
detpath.format(classname) should produce the detection results file.
62
annopath: Path to annotations
63
annopath.format(imagename) should be the xml annotations file.
64
imagesetfile: Text file containing the list of images, one image per line.
65
classname: Category name (duh)
66
cachedir: Directory for caching the annotations
67
[ovthresh]: Overlap threshold (default = 0.7)
68
"""
69
70
with open(imagesetfile, 'r') as f:
71
lines = f.readlines()
72
imagenames = [x.strip() for x in lines]
73
74
recs = {}
75
for i, imagename in enumerate(imagenames):
76
recs[imagename] = parse_gt(annopath.format(imagename))
77
78
# extract gt objects for this class
79
class_recs = {}
80
npos = 0
81
for imagename in imagenames:
82
R = [obj for obj in recs[imagename] if obj['name'] == classname]
83
bbox = np.array([x['bbox'] for x in R])
84
difficult = np.array([x['difficult'] for x in R]).astype(np.bool)
85
det = [False] * len(R)
86
npos = npos + sum(~difficult)
87
class_recs[imagename] = {'bbox': bbox,
88
'difficult': difficult,
89
'det': det}
90
91
# read dets from Task1* files
92
detfile = detpath.format(classname)
93
with open(detfile, 'r') as f:
94
lines = f.readlines()
95
96
splitlines = [x.strip().split(' ') for x in lines]
97
image_ids = [x[0] for x in splitlines]
98
confidence = np.array([float(x[1]) for x in splitlines])
99
100
BB = np.array([[float(z) for z in x[2:]] for x in splitlines])
101
102
# sort by confidence
103
sorted_ind = np.argsort(-confidence)
104
# sorted_scores = np.sort(-confidence)
105
106
## note the usage only in numpy not for list
107
BB = BB[sorted_ind, :]
108
image_ids = [image_ids[x] for x in sorted_ind]
109
# go down dets and mark TPs and FPs
110
nd = len(image_ids)
111
112
angle_dif_list = []
113
for d in range(nd):
114
R = class_recs[image_ids[d]]
115
bb = BB[d, :].astype(float)
116
ovmax = -np.inf
117
BBGT = R['bbox'].astype(float)
118
119
## compute det bb with each BBGT
120
if BBGT.size > 0:
121
# 1. calculate the overlaps between hbbs, if the iou between hbbs are 0, the iou between obbs are 0, too.
122
# pdb.set_trace()
123
BBGT_xmin = np.min(BBGT[:, 0::2], axis=1)
124
BBGT_ymin = np.min(BBGT[:, 1::2], axis=1)
125
BBGT_xmax = np.max(BBGT[:, 0::2], axis=1)
126
BBGT_ymax = np.max(BBGT[:, 1::2], axis=1)
127
bb_xmin = np.min(bb[0::2])
128
bb_ymin = np.min(bb[1::2])
129
bb_xmax = np.max(bb[0::2])
130
bb_ymax = np.max(bb[1::2])
131
132
ixmin = np.maximum(BBGT_xmin, bb_xmin)
133
iymin = np.maximum(BBGT_ymin, bb_ymin)
134
ixmax = np.minimum(BBGT_xmax, bb_xmax)
135
iymax = np.minimum(BBGT_ymax, bb_ymax)
136
iw = np.maximum(ixmax - ixmin + 1., 0.)
137
ih = np.maximum(iymax - iymin + 1., 0.)
138
inters = iw * ih
139
140
# union
141
uni = ((bb_xmax - bb_xmin + 1.) * (bb_ymax - bb_ymin + 1.) +
142
(BBGT_xmax - BBGT_xmin + 1.) *
143
(BBGT_ymax - BBGT_ymin + 1.) - inters)
144
145
overlaps = inters / uni
146
147
BBGT_keep_mask = overlaps > 0
148
BBGT_keep = BBGT[BBGT_keep_mask, :]
149
# BBGT_keep_index = np.where(overlaps > 0)[0]
150
151
def calcoverlaps(BBGT_keep, bb):
152
overlaps = []
153
for index, GT in enumerate(BBGT_keep):
154
overlap = polyiou.iou_poly(polyiou.VectorDouble(BBGT_keep[index]), polyiou.VectorDouble(bb))
155
overlaps.append(overlap)
156
return overlaps
157
if len(BBGT_keep) > 0:
158
overlaps = calcoverlaps(BBGT_keep, bb)
159
ovmax = np.max(overlaps)
160
if ovmax > ovthresh:
161
jmax = np.argmax(overlaps)
162
angle_box_GT = poly2rbox_single_v3(BBGT_keep[jmax])
163
angel_GT = angle_box_GT[-1]
164
165
angle_box_bb = poly2rbox_single_v3(bb)
166
angel_bb = angle_box_bb[-1]
167
168
angle_dif = abs(angel_bb - angel_GT) * 57.32
169
angle_dif_list.append(angle_dif)
170
171
return angle_dif_list
172
173
def main():
174
# detpath = r'/mnt/SSD/lwt_workdir/data/dota_angle/result_merge_fasterrcnn/{:s}.txt'
175
# annopath = r'/mnt/SSD/lwt_workdir/data/dota_new/val/labelTxt/{:s}.txt' # change the directory to the path of val/labelTxt, if you want to do evaluation on the valset
176
# imagesetfile = r'/mnt/SSD/lwt_workdir/data/dota_new/val/test.txt'
177
detpath = r'/data1/OrientedRepPoints/tools/parse_pkl/evaluation_results/40epoch_detection_results_merged/Task1_{:s}.txt'
178
annopath = r'/dataset/buyingjia/Dota/Dota_V1.0/val/labelTxt/{:s}.txt' # change the directory to the path of val/labelTxt, if you want to do evaluation on the valset
179
imagesetfile = r'/data1/OrientedRepPoints/tools/parse_pkl/evaluation_results/imgnamefile_val1.0.txt'
180
181
# For DOTA-v1.0
182
classnames = ['plane', 'baseball-diamond', 'bridge', 'ground-track-field', 'small-vehicle', 'large-vehicle', 'ship', 'tennis-court',
183
'basketball-court', 'storage-tank', 'soccer-ball-field', 'roundabout', 'harbor', 'swimming-pool', 'helicopter']
184
185
# for hrsc2016
186
# classnames = ['ship']
187
188
# for ucas_aod
189
# classname = ['airplane', 'car']
190
191
classaps = []
192
for classname in classnames:
193
print('classname:', classname)
194
angel_dif_list = aoe_eval(detpath,
195
annopath,
196
imagesetfile,
197
classname,
198
ovthresh=0.7) # set 0.7 as default
199
200
angle_dif = 0.0
201
202
for item in angel_dif_list:
203
angle_dif = angle_dif+item
204
205
angle_dif_ave = angle_dif/len(angel_dif_list)
206
print('angle_dif_ave: ', angle_dif_ave)
207
classaps.append(angle_dif_ave)
208
209
print('mAOE: ', sum(classaps)/len(classaps))
210
if __name__ == '__main__':
211
main()
212
213