Spaces:
Running
Running
import sys | |
import codecs | |
import numpy as np | |
import shapely.geometry as shgeo | |
import os | |
import re | |
import math | |
# import polyiou | |
""" | |
some basic functions which are useful for process DOTA data | |
""" | |
wordname_15 = ['plane', 'baseball-diamond', 'bridge', 'ground-track-field', 'small-vehicle', 'large-vehicle', 'ship', 'tennis-court', | |
'basketball-court', 'storage-tank', 'soccer-ball-field', 'roundabout', 'harbor', 'swimming-pool', 'helicopter'] | |
def custombasename(fullname): | |
return os.path.basename(os.path.splitext(fullname)[0]) | |
def GetFileFromThisRootDir(dir,ext = None): | |
allfiles = [] | |
needExtFilter = (ext != None) | |
for root,dirs,files in os.walk(dir): | |
for filespath in files: | |
filepath = os.path.join(root, filespath) | |
extension = os.path.splitext(filepath)[1][1:] | |
if needExtFilter and extension in ext: | |
allfiles.append(filepath) | |
elif not needExtFilter: | |
allfiles.append(filepath) | |
return allfiles | |
def TuplePoly2Poly(poly): | |
outpoly = [poly[0][0], poly[0][1], | |
poly[1][0], poly[1][1], | |
poly[2][0], poly[2][1], | |
poly[3][0], poly[3][1] | |
] | |
return outpoly | |
def parse_dota_poly_refactor(filename, code): | |
""" | |
parse the dota ground truth in the format: | |
[(x1, y1), (x2, y2), (x3, y3), (x4, y4)] | |
""" | |
objects = [] | |
#print('filename:', filename) | |
f = [] | |
if (sys.version_info >= (3, 5)): | |
fd = open(filename, 'r') | |
f = fd | |
elif (sys.version_info >= 2.7): | |
fd = codecs.open(filename, 'r', code) | |
f = fd | |
# count = 0 | |
while True: | |
line = f.readline() | |
# count = count + 1 | |
# if count < 2: | |
# continue | |
if line: | |
splitlines = line.strip().split(' ') | |
object_struct = {} | |
### clear the wrong name after check all the data | |
#if (len(splitlines) >= 9) and (splitlines[8] in classname): | |
if (len(splitlines) < 9): | |
continue | |
if (len(splitlines) >= 9): | |
object_struct['name'] = splitlines[8] | |
if (len(splitlines) == 9): | |
object_struct['difficult'] = '0' | |
elif (len(splitlines) >= 10): | |
# if splitlines[9] == '1': | |
# if (splitlines[9] == 'tr'): | |
# object_struct['difficult'] = '1' | |
# else: | |
object_struct['difficult'] = splitlines[9] | |
# else: | |
# object_struct['difficult'] = 0 | |
object_struct['poly'] = [(float(splitlines[0]), float(splitlines[1])), | |
(float(splitlines[2]), float(splitlines[3])), | |
(float(splitlines[4]), float(splitlines[5])), | |
(float(splitlines[6]), float(splitlines[7])) | |
] | |
gtpoly = shgeo.Polygon(object_struct['poly']) | |
object_struct['area'] = gtpoly.area | |
# poly = list(map(lambda x:np.array(x), object_struct['poly'])) | |
# object_struct['long-axis'] = max(distance(poly[0], poly[1]), distance(poly[1], poly[2])) | |
# object_struct['short-axis'] = min(distance(poly[0], poly[1]), distance(poly[1], poly[2])) | |
# if (object_struct['long-axis'] < 15): | |
# object_struct['difficult'] = '1' | |
# global small_count | |
# small_count = small_count + 1 | |
objects.append(object_struct) | |
else: | |
break | |
return objects | |
def parse_dota_poly(filename): | |
# 读进一个八个点坐标+类别+不知道啥的txt | |
# 最后生成一个列表,列表内是字典,每个字典表示一个物体,字典的键有:物体类别(name),难例(difficult),坐标(poly),面积(area) | |
# 这里的poly是dota8个点的坐标,注意更改,VOC最后要的是左上(小)右下坐标,coco要的是左上坐标和wh | |
# 注,我生成VOC可以不要area | |
""" | |
parse the dota ground truth in the format: | |
[(x1, y1), (x2, y2), (x3, y3), (x4, y4)] | |
""" | |
objects = [] | |
# print('filename:', filename) | |
f = [] | |
if (sys.version_info >= (3, 5)): | |
fd = open(filename, 'r') | |
f = fd | |
elif (sys.version_info >= 2.7): | |
fd = codecs.open(filename, 'r') | |
f = fd | |
# count = 0 | |
while True: | |
line = f.readline() | |
# count = count + 1 | |
# if count < 2: | |
# continue | |
if line: | |
splitlines = line.strip().split(' ') | |
object_struct = {} | |
### clear the wrong name after check all the data | |
#if (len(splitlines) >= 9) and (splitlines[8] in classname): | |
if (len(splitlines) < 9): | |
continue | |
if (len(splitlines) >= 9): | |
object_struct['name'] = splitlines[8] | |
if (len(splitlines) == 9): | |
object_struct['difficult'] = '0' | |
elif (len(splitlines) >= 10): | |
# if splitlines[9] == '1': | |
# if (splitlines[9] == 'tr'): | |
# object_struct['difficult'] = '1' | |
# else: | |
object_struct['difficult'] = splitlines[9] | |
# else: | |
# object_struct['difficult'] = 0 | |
object_struct['poly'] = [(float(splitlines[0]), float(splitlines[1])), | |
(float(splitlines[2]), float(splitlines[3])), | |
(float(splitlines[4]), float(splitlines[5])), | |
(float(splitlines[6]), float(splitlines[7])) | |
] | |
gtpoly = shgeo.Polygon(object_struct['poly']) | |
object_struct['area'] = gtpoly.area | |
# poly = list(map(lambda x:np.array(x), object_struct['poly'])) | |
# object_struct['long-axis'] = max(distance(poly[0], poly[1]), distance(poly[1], poly[2])) | |
# object_struct['short-axis'] = min(distance(poly[0], poly[1]), distance(poly[1], poly[2])) | |
# if (object_struct['long-axis'] < 15): | |
# object_struct['difficult'] = '1' | |
# global small_count | |
# small_count = small_count + 1 | |
objects.append(object_struct) | |
else: | |
break | |
return objects | |
def parse_dota_poly2(filename): | |
""" | |
parse the dota ground truth in the format: | |
[x1, y1, x2, y2, x3, y3, x4, y4] | |
""" | |
objects = parse_dota_poly(filename) | |
for obj in objects: | |
obj['poly'] = TuplePoly2Poly(obj['poly']) # 把tuple转成列表形式[x1, y1, x2, y2, x3, y3, x4, y4],所以为啥最开始要搞成tuple呢 | |
obj['poly'] = list(map(int, obj['poly'])) # dota把所有点都搞成整数,我应该不需要! | |
return objects | |
def parse_dota_rec(filename): | |
""" | |
parse the dota ground truth in the bounding box format: | |
"xmin, ymin, xmax, ymax" | |
""" | |
objects = parse_dota_poly(filename) | |
for obj in objects: | |
poly = obj['poly'] | |
bbox = dots4ToRec4(poly) | |
obj['bndbox'] = bbox | |
return objects | |
## bounding box transfer for varies format | |
def dots4ToRec4(poly): | |
xmin, xmax, ymin, ymax = min(poly[0][0], min(poly[1][0], min(poly[2][0], poly[3][0]))), \ | |
max(poly[0][0], max(poly[1][0], max(poly[2][0], poly[3][0]))), \ | |
min(poly[0][1], min(poly[1][1], min(poly[2][1], poly[3][1]))), \ | |
max(poly[0][1], max(poly[1][1], max(poly[2][1], poly[3][1]))) | |
return xmin, ymin, xmax, ymax | |
def dots4ToRec8(poly): | |
xmin, ymin, xmax, ymax = dots4ToRec4(poly) | |
return xmin, ymin, xmax, ymin, xmax, ymax, xmin, ymax | |
#return dots2ToRec8(dots4ToRec4(poly)) | |
def dots2ToRec8(rec): | |
xmin, ymin, xmax, ymax = rec[0], rec[1], rec[2], rec[3] | |
return xmin, ymin, xmax, ymin, xmax, ymax, xmin, ymax | |
def groundtruth2Task1(srcpath, dstpath): | |
filelist = GetFileFromThisRootDir(srcpath) | |
# names = [custombasename(x.strip())for x in filelist] | |
filedict = {} | |
for cls in wordname_15: | |
fd = open(os.path.join(dstpath, 'Task1_') + cls + r'.txt', 'w') | |
filedict[cls] = fd | |
for filepath in filelist: | |
objects = parse_dota_poly2(filepath) | |
subname = custombasename(filepath) | |
pattern2 = re.compile(r'__([\d+\.]+)__\d+___') | |
rate = re.findall(pattern2, subname)[0] | |
for obj in objects: | |
category = obj['name'] | |
difficult = obj['difficult'] | |
poly = obj['poly'] | |
if difficult == '2': | |
continue | |
if rate == '0.5': | |
outline = custombasename(filepath) + ' ' + '1' + ' ' + ' '.join(map(str, poly)) | |
elif rate == '1': | |
outline = custombasename(filepath) + ' ' + '0.8' + ' ' + ' '.join(map(str, poly)) | |
elif rate == '2': | |
outline = custombasename(filepath) + ' ' + '0.6' + ' ' + ' '.join(map(str, poly)) | |
filedict[category].write(outline + '\n') | |
def Task2groundtruth_poly(srcpath, dstpath): | |
thresh = 0.1 | |
filedict = {} | |
Tasklist = GetFileFromThisRootDir(srcpath, '.txt') | |
for Taskfile in Tasklist: | |
idname = custombasename(Taskfile).split('_')[-1] | |
# idname = datamap_inverse[idname] | |
f = open(Taskfile, 'r') | |
lines = f.readlines() | |
for line in lines: | |
if len(line) == 0: | |
continue | |
# print('line:', line) | |
splitline = line.strip().split(' ') | |
filename = splitline[0] | |
confidence = splitline[1] | |
bbox = splitline[2:] | |
if float(confidence) > thresh: | |
if filename not in filedict: | |
# filedict[filename] = codecs.open(os.path.join(dstpath, filename + '.txt'), 'w', 'utf_16') | |
filedict[filename] = codecs.open(os.path.join(dstpath, filename + '.txt'), 'w') | |
# poly = util.dots2ToRec8(bbox) | |
poly = bbox | |
# filedict[filename].write(' '.join(poly) + ' ' + idname + '_' + str(round(float(confidence), 2)) + '\n') | |
# print('idname:', idname) | |
# filedict[filename].write(' '.join(poly) + ' ' + idname + '_' + str(round(float(confidence), 2)) + '\n') | |
filedict[filename].write(' '.join(poly) + ' ' + idname + '\n') | |
def polygonToRotRectangle(bbox): | |
""" | |
:param bbox: The polygon stored in format [x1, y1, x2, y2, x3, y3, x4, y4] | |
:return: Rotated Rectangle in format [cx, cy, w, h, theta] | |
""" | |
bbox = np.array(bbox,dtype=np.float32) | |
bbox = np.reshape(bbox,newshape=(2,4),order='F') | |
angle = math.atan2(-(bbox[0,1]-bbox[0,0]),bbox[1,1]-bbox[1,0]) | |
center = [[0],[0]] | |
for i in range(4): | |
center[0] += bbox[0,i] | |
center[1] += bbox[1,i] | |
center = np.array(center,dtype=np.float32)/4.0 | |
R = np.array([[math.cos(angle), -math.sin(angle)], [math.sin(angle), math.cos(angle)]], dtype=np.float32) | |
normalized = np.matmul(R.transpose(),bbox-center) | |
xmin = np.min(normalized[0,:]) | |
xmax = np.max(normalized[0,:]) | |
ymin = np.min(normalized[1,:]) | |
ymax = np.max(normalized[1,:]) | |
w = xmax - xmin + 1 | |
h = ymax - ymin + 1 | |
return [float(center[0]),float(center[1]),w,h,angle] | |
def cal_line_length(point1, point2): | |
return math.sqrt( math.pow(point1[0] - point2[0], 2) + math.pow(point1[1] - point2[1], 2)) | |
def get_best_begin_point(coordinate): | |
x1 = coordinate[0][0] | |
y1 = coordinate[0][1] | |
x2 = coordinate[1][0] | |
y2 = coordinate[1][1] | |
x3 = coordinate[2][0] | |
y3 = coordinate[2][1] | |
x4 = coordinate[3][0] | |
y4 = coordinate[3][1] | |
xmin = min(x1, x2, x3, x4) | |
ymin = min(y1, y2, y3, y4) | |
xmax = max(x1, x2, x3, x4) | |
ymax = max(y1, y2, y3, y4) | |
combinate = [[[x1, y1], [x2, y2], [x3, y3], [x4, y4]], [[x2, y2], [x3, y3], [x4, y4], [x1, y1]], | |
[[x3, y3], [x4, y4], [x1, y1], [x2, y2]], [[x4, y4], [x1, y1], [x2, y2], [x3, y3]]] | |
dst_coordinate = [[xmin, ymin], [xmax, ymin], [xmax, ymax], [xmin, ymax]] | |
force = 100000000.0 | |
force_flag = 0 | |
for i in range(4): | |
temp_force = cal_line_length(combinate[i][0], dst_coordinate[0]) + cal_line_length(combinate[i][1], | |
dst_coordinate[ | |
1]) + cal_line_length( | |
combinate[i][2], dst_coordinate[2]) + cal_line_length(combinate[i][3], dst_coordinate[3]) | |
if temp_force < force: | |
force = temp_force | |
force_flag = i | |
if force_flag != 0: | |
print("choose one direction!") | |
return combinate[force_flag] | |