Spaces:
Runtime error
Runtime error
| 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] | |