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/dota_utils.py
Views: 475
1
import sys
2
import codecs
3
import numpy as np
4
import shapely.geometry as shgeo
5
import os
6
import re
7
import math
8
# import polyiou
9
"""
10
some basic functions which are useful for process DOTA data
11
"""
12
13
wordname_15 = ['plane', 'baseball-diamond', 'bridge', 'ground-track-field', 'small-vehicle', 'large-vehicle', 'ship', 'tennis-court',
14
'basketball-court', 'storage-tank', 'soccer-ball-field', 'roundabout', 'harbor', 'swimming-pool', 'helicopter']
15
16
CLASSNAMES = ['plane', 'baseball-diamond', 'bridge', 'ground-track-field', 'small-vehicle', 'large-vehicle', 'ship', 'tennis-court',
17
'basketball-court', 'storage-tank', 'soccer-ball-field', 'roundabout', 'harbor', 'swimming-pool', 'helicopter', 'container-crane']
18
19
20
def custombasename(fullname):
21
return os.path.basename(os.path.splitext(fullname)[0])
22
23
24
def GetFileFromThisRootDir(dir, ext=None):
25
allfiles = []
26
needExtFilter = (ext != None)
27
for root, dirs, files in os.walk(dir):
28
for filespath in files:
29
filepath = os.path.join(root, filespath)
30
extension = os.path.splitext(filepath)[1][1:]
31
if needExtFilter and extension in ext:
32
allfiles.append(filepath)
33
elif not needExtFilter:
34
allfiles.append(filepath)
35
return allfiles
36
37
38
def TuplePoly2Poly(poly):
39
outpoly = [poly[0][0], poly[0][1],
40
poly[1][0], poly[1][1],
41
poly[2][0], poly[2][1],
42
poly[3][0], poly[3][1]
43
]
44
return outpoly
45
46
47
def parse_dota_poly(filename):
48
"""
49
parse the dota ground truth in the format:
50
[(x1, y1), (x2, y2), (x3, y3), (x4, y4)]
51
"""
52
objects = []
53
#print('filename:', filename)
54
f = []
55
if (sys.version_info >= (3, 5)):
56
fd = open(filename, 'r')
57
f = fd
58
elif (sys.version_info >= 2.7):
59
fd = codecs.open(filename, 'r')
60
f = fd
61
# count = 0
62
while True:
63
line = f.readline()
64
# count = count + 1
65
# if count < 2:
66
# continue
67
if line:
68
splitlines = line.strip().split(' ')
69
object_struct = {}
70
# clear the wrong name after check all the data
71
# if (len(splitlines) >= 9) and (splitlines[8] in classname):
72
if (len(splitlines) < 9):
73
continue
74
if (len(splitlines) >= 9):
75
object_struct['name'] = splitlines[8]
76
if (len(splitlines) == 9):
77
object_struct['difficult'] = '0'
78
elif (len(splitlines) >= 10):
79
# if splitlines[9] == '1':
80
# if (splitlines[9] == 'tr'):
81
# object_struct['difficult'] = '1'
82
# else:
83
object_struct['difficult'] = splitlines[9]
84
# else:
85
# object_struct['difficult'] = 0
86
object_struct['poly'] = [(float(splitlines[0]), float(splitlines[1])),
87
(float(splitlines[2]),
88
float(splitlines[3])),
89
(float(splitlines[4]),
90
float(splitlines[5])),
91
(float(splitlines[6]),
92
float(splitlines[7]))
93
]
94
gtpoly = shgeo.Polygon(object_struct['poly'])
95
object_struct['area'] = gtpoly.area
96
# poly = list(map(lambda x:np.array(x), object_struct['poly']))
97
# object_struct['long-axis'] = max(distance(poly[0], poly[1]), distance(poly[1], poly[2]))
98
# object_struct['short-axis'] = min(distance(poly[0], poly[1]), distance(poly[1], poly[2]))
99
# if (object_struct['long-axis'] < 15):
100
# object_struct['difficult'] = '1'
101
# global small_count
102
# small_count = small_count + 1
103
objects.append(object_struct)
104
else:
105
break
106
return objects
107
108
109
def parse_dota_poly2(filename):
110
"""
111
parse the dota ground truth in the format:
112
[x1, y1, x2, y2, x3, y3, x4, y4]
113
"""
114
objects = parse_dota_poly(filename)
115
for obj in objects:
116
obj['poly'] = TuplePoly2Poly(obj['poly'])
117
obj['poly'] = list(map(int, obj['poly']))
118
return objects
119
120
121
def parse_dota_rec(filename):
122
"""
123
parse the dota ground truth in the bounding box format:
124
"xmin, ymin, xmax, ymax"
125
"""
126
objects = parse_dota_poly(filename)
127
for obj in objects:
128
poly = obj['poly']
129
bbox = dots4ToRec4(poly)
130
obj['bndbox'] = bbox
131
return objects
132
# bounding box transfer for varies format
133
134
135
def dots4ToRec4(poly):
136
xmin, xmax, ymin, ymax = min(poly[0][0], min(poly[1][0], min(poly[2][0], poly[3][0]))), \
137
max(poly[0][0], max(poly[1][0], max(poly[2][0], poly[3][0]))), \
138
min(poly[0][1], min(poly[1][1], min(poly[2][1], poly[3][1]))), \
139
max(poly[0][1], max(poly[1][1], max(poly[2][1], poly[3][1])))
140
return xmin, ymin, xmax, ymax
141
142
143
def dots4ToRec8(poly):
144
xmin, ymin, xmax, ymax = dots4ToRec4(poly)
145
return xmin, ymin, xmax, ymin, xmax, ymax, xmin, ymax
146
# return dots2ToRec8(dots4ToRec4(poly))
147
148
149
def dots2ToRec8(rec):
150
xmin, ymin, xmax, ymax = rec[0], rec[1], rec[2], rec[3]
151
return xmin, ymin, xmax, ymin, xmax, ymax, xmin, ymax
152
153
154
def groundtruth2Task1(srcpath, dstpath):
155
filelist = GetFileFromThisRootDir(srcpath)
156
# names = [custombasename(x.strip())for x in filelist]
157
filedict = {}
158
for cls in wordname_15:
159
fd = open(os.path.join(dstpath, 'Task1_') + cls + r'.txt', 'w')
160
filedict[cls] = fd
161
for filepath in filelist:
162
objects = parse_dota_poly2(filepath)
163
164
subname = custombasename(filepath)
165
pattern2 = re.compile(r'__([\d+\.]+)__\d+___')
166
rate = re.findall(pattern2, subname)[0]
167
168
for obj in objects:
169
category = obj['name']
170
difficult = obj['difficult']
171
poly = obj['poly']
172
if difficult == '2':
173
continue
174
if rate == '0.5':
175
outline = custombasename(
176
filepath) + ' ' + '1' + ' ' + ' '.join(map(str, poly))
177
elif rate == '1':
178
outline = custombasename(
179
filepath) + ' ' + '0.8' + ' ' + ' '.join(map(str, poly))
180
elif rate == '2':
181
outline = custombasename(
182
filepath) + ' ' + '0.6' + ' ' + ' '.join(map(str, poly))
183
184
filedict[category].write(outline + '\n')
185
186
187
def Task2groundtruth_poly(srcpath, dstpath):
188
thresh = 0.1
189
filedict = {}
190
Tasklist = GetFileFromThisRootDir(srcpath, '.txt')
191
192
for Taskfile in Tasklist:
193
idname = custombasename(Taskfile).split('_')[-1]
194
# idname = datamap_inverse[idname]
195
f = open(Taskfile, 'r')
196
lines = f.readlines()
197
for line in lines:
198
if len(line) == 0:
199
continue
200
# print('line:', line)
201
splitline = line.strip().split(' ')
202
filename = splitline[0]
203
confidence = splitline[1]
204
bbox = splitline[2:]
205
if float(confidence) > thresh:
206
if filename not in filedict:
207
# filedict[filename] = codecs.open(os.path.join(dstpath, filename + '.txt'), 'w', 'utf_16')
208
filedict[filename] = codecs.open(
209
os.path.join(dstpath, filename + '.txt'), 'w')
210
# poly = util.dots2ToRec8(bbox)
211
poly = bbox
212
# filedict[filename].write(' '.join(poly) + ' ' + idname + '_' + str(round(float(confidence), 2)) + '\n')
213
# print('idname:', idname)
214
215
# filedict[filename].write(' '.join(poly) + ' ' + idname + '_' + str(round(float(confidence), 2)) + '\n')
216
217
filedict[filename].write(' '.join(poly) + ' ' + idname + '\n')
218
219
220
def polygonToRotRectangle(bbox):
221
"""
222
:param bbox: The polygon stored in format [x1, y1, x2, y2, x3, y3, x4, y4]
223
:return: Rotated Rectangle in format [cx, cy, w, h, theta]
224
"""
225
bbox = np.array(bbox, dtype=np.float32)
226
bbox = np.reshape(bbox, newshape=(2, 4), order='F')
227
angle = math.atan2(-(bbox[0, 1]-bbox[0, 0]), bbox[1, 1]-bbox[1, 0])
228
229
center = [[0], [0]]
230
231
for i in range(4):
232
center[0] += bbox[0, i]
233
center[1] += bbox[1, i]
234
235
center = np.array(center, dtype=np.float32)/4.0
236
237
R = np.array([[math.cos(angle), -math.sin(angle)],
238
[math.sin(angle), math.cos(angle)]], dtype=np.float32)
239
240
normalized = np.matmul(R.transpose(), bbox-center)
241
242
xmin = np.min(normalized[0, :])
243
xmax = np.max(normalized[0, :])
244
ymin = np.min(normalized[1, :])
245
ymax = np.max(normalized[1, :])
246
247
w = xmax - xmin + 1
248
h = ymax - ymin + 1
249
250
return [float(center[0]), float(center[1]), w, h, angle]
251
252
253
def cal_line_length(point1, point2):
254
return math.sqrt(math.pow(point1[0] - point2[0], 2) + math.pow(point1[1] - point2[1], 2))
255
256
257
def get_best_begin_point(coordinate):
258
x1 = coordinate[0][0]
259
y1 = coordinate[0][1]
260
x2 = coordinate[1][0]
261
y2 = coordinate[1][1]
262
x3 = coordinate[2][0]
263
y3 = coordinate[2][1]
264
x4 = coordinate[3][0]
265
y4 = coordinate[3][1]
266
xmin = min(x1, x2, x3, x4)
267
ymin = min(y1, y2, y3, y4)
268
xmax = max(x1, x2, x3, x4)
269
ymax = max(y1, y2, y3, y4)
270
combinate = [[[x1, y1], [x2, y2], [x3, y3], [x4, y4]], [[x2, y2], [x3, y3], [x4, y4], [x1, y1]],
271
[[x3, y3], [x4, y4], [x1, y1], [x2, y2]], [[x4, y4], [x1, y1], [x2, y2], [x3, y3]]]
272
dst_coordinate = [[xmin, ymin], [xmax, ymin], [xmax, ymax], [xmin, ymax]]
273
force = 100000000.0
274
force_flag = 0
275
for i in range(4):
276
temp_force = cal_line_length(combinate[i][0], dst_coordinate[0]) + cal_line_length(combinate[i][1],
277
dst_coordinate[
278
1]) + cal_line_length(
279
combinate[i][2], dst_coordinate[2]) + cal_line_length(combinate[i][3], dst_coordinate[3])
280
if temp_force < force:
281
force = temp_force
282
force_flag = i
283
if force_flag != 0:
284
print("choose one direction!")
285
return combinate[force_flag]
286
287