Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/DOTA_devkit/ImgSplit_multi_process.py
Views: 475
"""1-------------2This is the multi-process version3"""4import os5import codecs6import numpy as np7import math8from dota_utils import GetFileFromThisRootDir9import cv210import shapely.geometry as shgeo11import dota_utils as util12import copy13from multiprocessing import Pool14from functools import partial15import time161718def choose_best_pointorder_fit_another(poly1, poly2):19"""20To make the two polygons best fit with each point21"""22x1 = poly1[0]23y1 = poly1[1]24x2 = poly1[2]25y2 = poly1[3]26x3 = poly1[4]27y3 = poly1[5]28x4 = poly1[6]29y4 = poly1[7]30combinate = [np.array([x1, y1, x2, y2, x3, y3, x4, y4]), np.array([x2, y2, x3, y3, x4, y4, x1, y1]),31np.array([x3, y3, x4, y4, x1, y1, x2, y2]), np.array([x4, y4, x1, y1, x2, y2, x3, y3])]32dst_coordinate = np.array(poly2)33distances = np.array([np.sum((coord - dst_coordinate)**2)34for coord in combinate])35sorted = distances.argsort()36return combinate[sorted[0]]373839def cal_line_length(point1, point2):40return math.sqrt(math.pow(point1[0] - point2[0], 2) + math.pow(point1[1] - point2[1], 2))414243def split_single_warp(name, split_base, rate, extent):44split_base.SplitSingle(name, rate, extent)454647class splitbase():48def __init__(self,49basepath,50outpath,51code='utf-8',52gap=512,53subsize=1024,54thresh=0.7,55choosebestpoint=True,56ext='.png',57padding=True,58num_process=859):60"""61:param basepath: base path for dota data62:param outpath: output base path for dota data,63the basepath and outputpath have the similar subdirectory, 'images' and 'labelTxt'64:param code: encodeing format of txt file65:param gap: overlap between two patches66:param subsize: subsize of patch67:param thresh: the thresh determine whether to keep the instance if the instance is cut down in the process of split68:param choosebestpoint: used to choose the first point for the69:param ext: ext for the image format70:param padding: if to padding the images so that all the images have the same size71"""72self.basepath = basepath73self.outpath = outpath74self.code = code75self.gap = gap76self.subsize = subsize77self.slide = self.subsize - self.gap78self.thresh = thresh79self.imagepath = os.path.join(self.basepath, 'images')80self.labelpath = os.path.join(self.basepath, 'labelTxt')81self.outimagepath = os.path.join(self.outpath, 'images')82self.outlabelpath = os.path.join(self.outpath, 'labelTxt')83self.choosebestpoint = choosebestpoint84self.ext = ext85self.padding = padding86self.num_process = num_process87self.pool = Pool(num_process)88print('padding:', padding)8990# pdb.set_trace()91if not os.path.isdir(self.outpath):92os.mkdir(self.outpath)93if not os.path.isdir(self.outimagepath):94# pdb.set_trace()95os.mkdir(self.outimagepath)96if not os.path.isdir(self.outlabelpath):97os.mkdir(self.outlabelpath)98# pdb.set_trace()99# point: (x, y), rec: (xmin, ymin, xmax, ymax)100# def __del__(self):101# self.f_sub.close()102# grid --> (x, y) position of grids103104def polyorig2sub(self, left, up, poly):105polyInsub = np.zeros(len(poly))106for i in range(int(len(poly)/2)):107polyInsub[i * 2] = int(poly[i * 2] - left)108polyInsub[i * 2 + 1] = int(poly[i * 2 + 1] - up)109return polyInsub110111def calchalf_iou(self, poly1, poly2):112"""113It is not the iou on usual, the iou is the value of intersection over poly1114"""115inter_poly = poly1.intersection(poly2)116inter_area = inter_poly.area117poly1_area = poly1.area118half_iou = inter_area / poly1_area119return inter_poly, half_iou120121def saveimagepatches(self, img, subimgname, left, up):122subimg = copy.deepcopy(123img[up: (up + self.subsize), left: (left + self.subsize)])124outdir = os.path.join(self.outimagepath, subimgname + self.ext)125h, w, c = np.shape(subimg)126if (self.padding):127outimg = np.zeros((self.subsize, self.subsize, 3))128outimg[0:h, 0:w, :] = subimg129cv2.imwrite(outdir, outimg)130else:131cv2.imwrite(outdir, subimg)132133def GetPoly4FromPoly5(self, poly):134distances = [cal_line_length((poly[i * 2], poly[i * 2 + 1]), (poly[(135i + 1) * 2], poly[(i + 1) * 2 + 1])) for i in range(int(len(poly)/2 - 1))]136distances.append(cal_line_length(137(poly[0], poly[1]), (poly[8], poly[9])))138pos = np.array(distances).argsort()[0]139count = 0140outpoly = []141while count < 5:142#print('count:', count)143if (count == pos):144outpoly.append(145(poly[count * 2] + poly[(count * 2 + 2) % 10])/2)146outpoly.append(147(poly[(count * 2 + 1) % 10] + poly[(count * 2 + 3) % 10])/2)148count = count + 1149elif (count == (pos + 1) % 5):150count = count + 1151continue152153else:154outpoly.append(poly[count * 2])155outpoly.append(poly[count * 2 + 1])156count = count + 1157return outpoly158159def savepatches(self, resizeimg, objects, subimgname, left, up, right, down):160outdir = os.path.join(self.outlabelpath, subimgname + '.txt')161mask_poly = []162imgpoly = shgeo.Polygon([(left, up), (right, up), (right, down),163(left, down)])164with codecs.open(outdir, 'w', self.code) as f_out:165for obj in objects:166gtpoly = shgeo.Polygon([(obj['poly'][0], obj['poly'][1]),167(obj['poly'][2], obj['poly'][3]),168(obj['poly'][4], obj['poly'][5]),169(obj['poly'][6], obj['poly'][7])])170if (gtpoly.area <= 0):171continue172inter_poly, half_iou = self.calchalf_iou(gtpoly, imgpoly)173174# print('writing...')175if (half_iou == 1):176polyInsub = self.polyorig2sub(left, up, obj['poly'])177outline = ' '.join(list(map(str, polyInsub)))178outline = outline + ' ' + \179obj['name'] + ' ' + str(obj['difficult'])180f_out.write(outline + '\n')181elif (half_iou > 0):182# elif (half_iou > self.thresh):183# print('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<')184inter_poly = shgeo.polygon.orient(inter_poly, sign=1)185out_poly = list(inter_poly.exterior.coords)[0: -1]186if len(out_poly) < 4:187continue188189out_poly2 = []190for i in range(len(out_poly)):191out_poly2.append(out_poly[i][0])192out_poly2.append(out_poly[i][1])193194if (len(out_poly) == 5):195# print('==========================')196out_poly2 = self.GetPoly4FromPoly5(out_poly2)197elif (len(out_poly) > 5):198"""199if the cut instance is a polygon with points more than 5, we do not handle it currently200"""201continue202if (self.choosebestpoint):203out_poly2 = choose_best_pointorder_fit_another(204out_poly2, obj['poly'])205206polyInsub = self.polyorig2sub(left, up, out_poly2)207208for index, item in enumerate(polyInsub):209if (item <= 1):210polyInsub[index] = 1211elif (item >= self.subsize):212polyInsub[index] = self.subsize213outline = ' '.join(list(map(str, polyInsub)))214if (half_iou > self.thresh):215outline = outline + ' ' + \216obj['name'] + ' ' + str(obj['difficult'])217else:218# if the left part is too small, label as '2'219outline = outline + ' ' + obj['name'] + ' ' + '2'220f_out.write(outline + '\n')221# else:222# mask_poly.append(inter_poly)223self.saveimagepatches(resizeimg, subimgname, left, up)224225def SplitSingle(self, name, rate, extent):226"""227split a single image and ground truth228:param name: image name229:param rate: the resize scale for the image230:param extent: the image format231:return:232"""233img = cv2.imread(os.path.join(self.imagepath, name + extent))234if np.shape(img) == ():235return236fullname = os.path.join(self.labelpath, name + '.txt')237objects = util.parse_dota_poly2(fullname)238for obj in objects:239obj['poly'] = list(map(lambda x: rate*x, obj['poly']))240#obj['poly'] = list(map(lambda x: ([2 * y for y in x]), obj['poly']))241242if (rate != 1):243resizeimg = cv2.resize(244img, None, fx=rate, fy=rate, interpolation=cv2.INTER_CUBIC)245else:246resizeimg = img247outbasename = name + '__' + str(rate) + '__'248weight = np.shape(resizeimg)[1]249height = np.shape(resizeimg)[0]250251left, up = 0, 0252while (left < weight):253if (left + self.subsize >= weight):254left = max(weight - self.subsize, 0)255up = 0256while (up < height):257if (up + self.subsize >= height):258up = max(height - self.subsize, 0)259right = min(left + self.subsize, weight - 1)260down = min(up + self.subsize, height - 1)261subimgname = outbasename + str(left) + '___' + str(up)262# self.f_sub.write(name + ' ' + subimgname + ' ' + str(left) + ' ' + str(up) + '\n')263self.savepatches(resizeimg, objects,264subimgname, left, up, right, down)265if (up + self.subsize >= height):266break267else:268up = up + self.slide269if (left + self.subsize >= weight):270break271else:272left = left + self.slide273274def splitdata(self, rate):275"""276:param rate: resize rate before cut277"""278imagelist = GetFileFromThisRootDir(self.imagepath)279imagenames = [util.custombasename(x) for x in imagelist if (280util.custombasename(x) != 'Thumbs')]281if self.num_process == 1:282for name in imagenames:283self.SplitSingle(name, rate, self.ext)284else:285286# worker = partial(self.SplitSingle, rate=rate, extent=self.ext)287worker = partial(split_single_warp, split_base=self,288rate=rate, extent=self.ext)289self.pool.map(worker, imagenames)290291def __getstate__(self):292self_dict = self.__dict__.copy()293del self_dict['pool']294return self_dict295296def __setstate__(self, state):297self.__dict__.update(state)298299300if __name__ == '__main__':301split = splitbase(basepath=r'dataset/dataset_demo',302outpath=r'dataset/dataset_demo_rate1.0_split1024_gap200',303gap=200,304subsize=1024,305num_process=8)306split.splitdata(1)307308