def labels2yaml(labels: list, savePath='', savefile=True): # pass if '_background_' not in labels: labels.append('_background_') tmp = dict() tmp['_background_'] = 0 classId = 1 for i in range(0, len(labels)): x = labels[i].replace('\n','').strip() if x != '_background_': tmp[x] = classId classId += 1 data = dict() data['label_names'] = tmp del tmp if savefile: try: with open(savePath + os.sep + 'info.yaml', 'w', encoding='utf-8') as f: yaml.dump(data, f, allow_unicode=True) logger.info("successfully convert labels to yaml, see {}".format( savePath + os.sep + 'info.yaml')) except Exception as e: logger.error(e) return data
def imgDistort(filepath: str, flag=True): if isinstance(filepath, str): if os.path.exists(filepath): img = io.imread(filepath) else: raise FileNotFoundError('Image file not found!') elif isinstance(filepath, np.ndarray): img = filepath else: logger.error('Input file error') return imgShape = img.shape imgWidth = imgShape[1] imgHeight = imgShape[0] center = (random.randint(int(0.2 * imgWidth), int(0.8 * imgWidth)), random.randint(int(0.2 * imgHeight), int(0.8 * imgHeight))) mouse = (random.randint(int(0.2 * imgWidth), int(0.8 * imgWidth)), random.randint(int(0.2 * imgHeight), int(0.8 * imgHeight))) radious = random.randint(50, 250) input_img = Image.fromarray(img).convert('RGB') resImg = imgFilter(input_img, radious, center, mouse) resImg = np.array(resImg) if flag: image_path, _ = os.path.splitext(filepath) io.imsave(image_path + '_distort.jpg', resImg) logger.info('Saved to {}'.format(image_path + '_distort.jpg')) else: return resImg
def imgAug_LabelImg(imgPath, xmlpath, number=1): """ number : file number you want to generate. """ logger.info("currently, only *.jpg supported") oriImgs = glob.glob(imgPath + os.sep + '*.jpg') if os.path.isdir(imgPath) else [imgPath] xmlFiles = glob.glob(xmlpath + os.sep + '*.xml') if os.path.isdir(xmlpath) else [xmlpath] if type(number) != int: logger.error('Augumentation times error.Using 1 as default') number = 1 else: if number < 1: logger.warning( 'Augumentation times {} is less than 1.Using 1 as default'. format(number)) number = 1 pool = Pool(__CPUS__ - 1) pool_list = [] for i in oriImgs: for num in tqdm(range(0, number)): resultspool = pool.apply_async(proc_xml, (i, imgPath, xmlpath, num)) pool_list.append(resultspool) logger.info('successfully create {} tasks'.format(len(pool_list))) for pr in tqdm(pool_list): re_list = pr.get()
def do(self): if len(self.augs) == 0: logger.info('None methods founds') return pimgs = self.imgs # print(pimgs) for i in self.operations: i.setImgs(pimgs) pimgs = i.do() gc.collect() if not self.saveFile: return pimgs else: if not os.path.exists(self.saveDir) and self.saveDir != '': os.mkdir(self.saveDir) else: logger.error("Provided savedir is not valid") return if type(self.imgs) is not list: if type(self.imgs) is str: filename = os.path.split(self.imgs)[1] else: filename = 'test.jpg' io.imsave(self.saveDir + os.sep + filename, pimgs) else: for i in range(len(self.imgs)): if isinstance(self.augs[i], str): filename = os.path.split(i)[1] else: filename = 'test{}.jpg'.format(i) io.imsave(self.saveDir + os.sep + filename, pimgs[i]) logger.info("Done! See {}.".format(self.saveDir))
def getJsons(imgPath, maskPath, savePath, yamlPath=''): """ imgPath: origin image path \n maskPath : mask image path \n savePath : json file save path \n >>> getJsons(path-to-your-imgs,path-to-your-maskimgs,path-to-your-jsonfiles) """ logger.info("currently, only *.jpg supported") if os.path.isfile(imgPath): getMultiShapes.getMultiShapes(imgPath, maskPath, savePath, yamlPath) elif os.path.isdir(imgPath): oriImgs = glob.glob(imgPath + os.sep + '*.jpg') maskImgs = glob.glob(maskPath + os.sep + '*.jpg') for i in tqdm(oriImgs): i_mask = i.replace(imgPath, maskPath) if os.path.exists(i_mask): # print(i) getMultiShapes.getMultiShapes(i, i_mask, savePath, yamlPath) else: logger.warning('corresponding mask image not found!') continue else: logger.error( 'input error. got [{},{},{},{}]. file maybe missing.'.format( imgPath, maskPath, savePath, yamlPath)) logger.info('Done! See here. {}'.format(savePath))
def imgAug_withLabels(imgPath, labelPath, number=1, yamlFilePath=''): """ number : file number you want to generate. """ logger.info("currently, only *.jpg supported") oriImgs = glob.glob(imgPath + os.sep + '*.jpg') if os.path.isdir(imgPath) else [imgPath] jsonFiles = glob.glob(labelPath + os.sep + '*.json') if os.path.isdir(labelPath) else [ labelPath ] if type(number) != int: logger.error('Augumentation times error.Using 1 as default') number = 1 else: if number < 1: logger.warning( 'Augumentation times {} is less than 1.Using 1 as default'. format(number)) number = 1 for num in range(0, number): for i in tqdm(oriImgs): i_json = i.replace( imgPath, labelPath) if os.path.isdir(labelPath) else labelPath i_json = i_json.replace('.jpg', '.json') imgAug.aug_labelme(i, i_json, num=num, yamlFilePath=yamlFilePath)
def j2xConvert(jsonFilePath: str): with open(jsonFilePath, 'r', encoding='utf-8') as f: jsonObj = json.load(f) if isinstance(jsonObj, str): jsonObj = json.loads(jsonObj) tmpPath = jsonFilePath.replace('.json', '.xml') aimPath = tmpPath folder = os.path.abspath(jsonFilePath) filename = jsonObj['imagePath'] path = tmpPath width = jsonObj['imageWidth'] height = jsonObj['imageHeight'] objs = [] shapes = jsonObj['shapes'] # print(type(shapes)) for shape in shapes: label = shape['label'] points = shape['points'] # print(type(points)) tmp = np.array(points) # print(tmp) obj = dict() obj['name'] = label obj['difficult'] = 0 bndbox = dict() bndbox['xmin'] = np.min(tmp[:, 0]) if np.min( tmp[:, 0] ) > 0 else 1 # https://github.com/AlexeyAB/darknet the bounding box cannot be 0 bndbox['xmax'] = np.max(tmp[:, 0]) bndbox['ymin'] = np.min(tmp[:, 1]) if np.min(tmp[:, 1]) > 0 else 1 bndbox['ymax'] = np.max(tmp[:, 1]) obj['bndbox'] = bndbox if bndbox['ymax'] - bndbox['ymin'] < 10 or bndbox['xmax'] - bndbox[ 'xmin'] < 10: pass else: objs.append(obj) img2xml_multiobj(tmpPath, aimPath, folder, filename, path, width, height, objs) # print(objs) logger.info('Done! See {}'.format(tmpPath))
def imgAug_withoutLabels(imgPath, number=1): logger.info("currently, only *.jpg supported") oriImgs = glob.glob(imgPath + os.sep + '*.jpg') if os.path.isdir(imgPath) else [imgPath] if type(number) != int: logger.error('Augumentation times error.Using 1 as default') number = 1 else: if number < 1: logger.warning( 'Augumentation times {} is less than 1.Using 1 as default'. format(number)) number = 1 for num in range(0, number): for i in tqdm(oriImgs): imgAug_nolabel.aug(i, num=num)
def split(folder: str, savaFolder: str, nc: int = 42, multiprocesses=True): global RES txts = glob.glob(folder + os.sep + "*.txt") if not len(txts) > 0: logger.error('Folder is empty, none txt file found!') return trainFile = open(savaFolder + os.sep + 'train.txt', 'w+', encoding='utf-8') trainvalFile = open(savaFolder + os.sep + 'val.txt', 'w+', encoding='utf-8') logger.info('======== start analysing ========') pool = Pool(__CPUS__ - 1) pool_list = [] for t in txts: dic = dict() for k in range(0, nc): dic[k] = 0 resultpool = pool.apply_async(getInfo, (t, dic)) pool_list.append(resultpool) for pr in tqdm(pool_list): res = pr.get() RES.append(res) tmp = getSum(RES) r = getMean(tmp, nc) getTrainValSet(RES, r) global valList for i in list(set(valList)): trainvalFile.write(i.filename + '\n') trainList = list(set(RES).difference(set(valList))) for i in trainList: trainFile.write(i.filename + '\n') trainvalFile.close() trainFile.close()
def getXmls(imgPath, maskPath, savePath): logger.info("currently, only *.jpg supported") if os.path.isfile(imgPath): getMultiShapes.getMultiObjs_voc(imgPath, maskPath, savePath) elif os.path.isdir(imgPath): oriImgs = glob.glob(imgPath + os.sep + '*.jpg') maskImgs = glob.glob(maskPath + os.sep + '*.jpg') for i in tqdm(oriImgs): i_mask = i.replace(imgPath, maskPath) # print(i) if os.path.exists(i_mask): getMultiShapes.getMultiObjs_voc(i, i_mask, savePath) else: logger.warning('corresponding mask image not found!') continue else: logger.error('input error. got [{},{},{}]. file maybe missing.'.format( imgPath, maskPath, savePath)) logger.info('Done! See here. {}'.format(savePath))
def x2mConvert(xmlpath, labelPath='', yamlPath=''): flagY = True flagL = True if not os.path.exists(yamlPath): logger.info('yaml file not exists!') flagY = False if not os.path.exists(labelPath): logger.info('label file not exists!') flagL = False else: labels = readLabels(labelPath) label_masks = labels2yaml(labels, savefile=False) else: label_masks = yaml2dict(yamlPath) parent_path = os.path.dirname(xmlpath) if not os.path.exists(xmlpath): raise FileNotFoundError('file not found') else: if os.path.isfile(xmlpath): logger.info('single file found') if flagY or flagL: label_masks, maskPath = generateMask(xmlpath, parent_path, label_masks) else: label_masks, maskPath = generateMask(xmlpath, parent_path) print('Done!') return label_masks, maskPath else: xmls = glob.glob(xmlpath + os.sep + "*.xml") if not os.path.exists(parent_path + os.sep + 'masks_'): os.mkdir(parent_path + os.sep + 'masks_') logger.info('exists {} xml files'.format(len(xmls))) for xml in tqdm(xmls): if flagY or flagL: label_masks = generateMask(xml, parent_path, label_masks) else: label_masks = generateMask(xml, parent_path) print('Done!') print("see here {}".format(parent_path + os.sep + 'masks_')) return label_masks, parent_path + os.sep + 'masks_'
def x2jConvert_pascal(xmlpath, originImgPath, flag=True): # pass if not os.path.exists(xmlpath) or not os.path.exists(originImgPath): logger.error('file not exist') return base64Code = imgEncode(originImgPath) shapes = getPolygonPascal(xmlpath) (fatherPath, filename_ext) = os.path.split(originImgPath) (filename, _) = os.path.splitext(filename_ext) ob = dict() ob['imageData'] = base64Code ob['flags'] = {} ob['version'] = labelmeVersion ob['imagePath'] = filename_ext img = io.imread(originImgPath) imgShape = img.shape del img ob['imageHeight'] = imgShape[0] ob['imageWidth'] = imgShape[1] ob['shapes'] = shapes if flag: with open(fatherPath + os.sep + filename + '_p.json', 'w', encoding='utf-8') as f: j = json.dumps(ob, sort_keys=True, indent=4) f.write(j) logger.info('save to path {}'.format(fatherPath + os.sep + filename + '_p.json')) return fatherPath + os.sep + filename + '_p.json' else: return json.dumps(ob, sort_keys=True, indent=4)
def splitLongImagesWithOverlay(imgpath: str, xmlpath: str, savepath: str, imgExt: list = [ "jpg", ], multiprocesses=True, savePaddedFile=False): try: shutil.rmtree(savepath) except: pass if not os.path.exists(savepath): os.mkdir(savepath) padForSplitScript(imgpath, savepath, multiprocesses=multiprocesses) logger.info('padding images done!') imgpaths = [] for ext in imgExt: imgpaths.extend(glob(savepath + '*.{}'.format(ext))) if not multiprocesses: for i in tqdm.tqdm(imgpaths): splitSingleImages(i, savepath, xmlpath) if savePaddedFile: _, ext = os.path.splitext(i) xml = i.replace(savepath, xmlpath).replace(ext, '.xml') shutil.copyfile(xml, xml.replace( xmlpath, savepath)) if os.path.exists(xml) else do_nothing() os.remove(i) else: pool = Pool(__CPUS__ - 1) pool_list = [] for i in tqdm.tqdm(imgpaths): if savePaddedFile: _, ext = os.path.splitext(i) xml = i.replace(savepath, xmlpath).replace(ext, '.xml') shutil.copyfile(xml, xml.replace( xmlpath, savepath)) if os.path.exists(xml) else do_nothing() resultPool = pool.apply_async(splitSingleImages, (i, savepath, xmlpath)) pool_list.append(resultPool) for pr in tqdm.tqdm(pool_list): pr.get() if not savePaddedFile: logger.info('Delete cache files.') for i in tqdm.tqdm(imgpaths): os.remove(i) logger.info('Done!')
def x2yConvert(xmlpath, labelPath=''): labels = readLabels(labelPath) parent_path = os.path.dirname(xmlpath) if not os.path.exists(xmlpath): raise FileNotFoundError('file not found') else: if os.path.isfile(xmlpath): # pass logger.info('single file found') labels = readXmlSaveTxt(xmlpath, parent_path, labels) if len(labels) > 0: logger.warning('generate label file automaticly') with open(parent_path + os.sep + 'labels_.txt', 'w') as f: for i in labels: f.write(i + '\n') print('Done!') print("see here {}".format(parent_path)) else: xmls = glob.glob(xmlpath + os.sep + "*.xml") if not os.path.exists(parent_path + os.sep + 'txts_'): os.mkdir(parent_path + os.sep + 'txts_') logger.info('exists {} xml files'.format(len(xmls))) for xml in tqdm(xmls): labels = readXmlSaveTxt(xml, parent_path + os.sep + 'txts_', labels) if len(labels) > 0: logger.warning('generate label file automaticly') with open( parent_path + os.sep + 'txts_' + os.sep + 'labels_.txt', 'w') as f: for i in labels: f.write(i + '\n') logger.info('Done!') logger.info("see here {}".format(parent_path + os.sep + 'txts_'))
def script(): arguments = docopt(__doc__) if arguments.get('--version') or arguments.get('-v'): print(__version__) elif arguments.get('m2j'): logger.info("Masks to jsons") print("<==== please input origin image path ====>") inputOriimgPath = input() print("<==== please input mask path ====>") inputMaskPath = input() if not os.path.exists(inputMaskPath): raise FileNotFoundError('mask folder is not exist') savePath = inputMaskPath print("<==== please input yaml path (can be blank,better dont) ====>") inputYamlPath = input() getJsons(inputOriimgPath,inputMaskPath,savePath,inputYamlPath) print("Done!") elif arguments.get('m2x'): logger.info("Masks to xmls") print("<==== please input origin image path ====>") inputOriimgPath = input() print("<==== please input mask path ====>") inputMaskPath = input() if not os.path.exists(inputMaskPath): raise FileNotFoundError('mask folder is not exist') savePath = inputMaskPath getXmls(inputOriimgPath,inputMaskPath,savePath) print("Done!") elif arguments.get('j2m'): logger.info("Jsons to masks") print("<==== please input json files path ====>") inputJsonPath = input() processor(inputJsonPath) print('Done!') elif arguments.get('j2x'): logger.info("Json to xml (single file supported if version<=0.3)") print("<==== please input json file path ====>") inputJsonPath = input() j2xConvert(inputJsonPath) print('Done!') elif arguments.get('aug'): # logger.info("Image augmentation (single file supported if version<=0.3)") if not arguments.get('--nolabel'): print("<==== please input image file path ====>") inputFilePath = input() print("<==== please input json file path ====>") inputJsonPath = input() imgAug_withLabels(inputFilePath,inputJsonPath) else: print("<==== please input image file path ====>") inputFilePath = input() imgAug_withoutLabels(inputFilePath)
def convertWiderface(filepath: str, savepath='', mProcess=False): """Annotation of widerface is like 0--Parade/0_Parade_marchingband_1_849.jpg 1 449 330 122 149 0 0 0 0 0 0 The format of txt ground truth. \n File name \n Number of bounding box \n x1, y1, w, h, blur, expression, illumination, invalid, occlusion, pose which is not suitable for labelImg. Besides, convertion may take a really long time using single process. """ with open(filepath, 'r', encoding='utf-8') as f: lines = f.readlines() ids = list(index for (index, d) in enumerate(lines) if d.endswith('.jpg\n')) # print(len(ids)) if savepath == '': savepath = BASE_DIR + os.sep + 'xmls_' if not os.path.isdir(savepath): os.mkdir(savepath) folder = 'face' name = 'face' lastImg = lines[ids[-1]] imgname = lastImg.split('/')[-1].replace('\n', '') xmlname = imgname.replace('.jpg', '.xml') tmpPath = savepath + xmlname path = imgname width = 0 height = 0 objs = [] objlist = lines[ids[-1] + 2:] for ob in objlist: if len(ob) > 20: tmp = ob.split(' ') xmin = tmp[0] ymin = tmp[1] w = tmp[2] h = tmp[3] xmax = int(xmin) + int(w) ymax = int(ymin) + int(h) obj = dict() obj['name'] = name obj['diffcult'] = 0 bndbox = dict() bndbox['xmin'] = xmin bndbox['ymin'] = ymin bndbox['xmax'] = xmax bndbox['ymax'] = ymax obj['bndbox'] = bndbox objs.append(obj) img2xml_multiobj(tmpPath, tmpPath, folder, imgname, path, width, height, objs) if not mProcess: for i in tqdm(range(len(ids) - 1)): start = ids[i] end = ids[i + 1] imgname = lines[start].split('/')[-1] xmlname = imgname.replace('.jpg', '.xml').replace('\n', '') tmpPath = savepath + xmlname path = imgname width = 0 # for test height = 0 # for test objs = [] objlist = lines[start + 2:end] for ob in objlist: # print(ob) if len(ob) > 20: tmp = ob.split(' ') xmin = tmp[0] ymin = tmp[1] w = tmp[2] h = tmp[3] xmax = int(xmin) + int(w) ymax = int(ymin) + int(h) obj = dict() obj['name'] = name obj['diffcult'] = 0 bndbox = dict() bndbox['xmin'] = xmin bndbox['ymin'] = ymin bndbox['xmax'] = xmax bndbox['ymax'] = ymax obj['bndbox'] = bndbox objs.append(obj) img2xml_multiobj(tmpPath, tmpPath, folder, imgname, path, width, height, objs) logger.info('Done! See {}.'.format(savepath)) else: pool = Pool(__CPUS__ - 1) pool_list = [] for i in tqdm(range(len(ids) - 1)): start = ids[i] end = ids[i + 1] imgname = lines[start].split('/')[-1] objlist = lines[start + 2:end] resultsPool = pool.apply_async( writeXml, (imgname, objlist, savepath, folder, name)) pool_list.append(resultsPool) for pr in tqdm(pool_list): re_list = pr.get() logger.info('Done! See {}.'.format(savepath))
LastEditors: xiaoshuyui LastEditTime: 2020-10-20 11:13:32 ''' import sys sys.path.append("..") import os BASE_DIR = os.path.abspath(os.path.dirname(os.getcwd())) import convertmask.main_v_0_5_any as mainScript from convertmask.utils.methods.logger import logger mainScriptPath = mainScript.__file__ # print (mainScriptPath) if __name__ == "__main__": logger.info('1.version') code = 'python {} -v'.format(mainScriptPath) os.system(code) logger.info('2.no inout') code = 'python {} '.format(mainScriptPath) os.system(code) logger.info('3.random method') code = 'python {} ma'.format(mainScriptPath) os.system(code) code = 'python {} mask2json -H'.format(mainScriptPath) os.system(code) logger.info('4.mask2json') oriImgPath = BASE_DIR + '/static/multi_objs.jpg'
def aug(filepath, augs=['noise', 'rotation', 'trans', 'flip', 'zoom'], num=0): # augs = ['noise','rotation','trans','flip'] l = np.random.randint(2, size=len(augs)) if np.sum(l) == 0: l[0] = 1 l = l.tolist() p = list(zip(augs, l)) img = filepath for i in p: if i[1] == 1: if i[0] == 'noise': n = imgNoise(img, flag=False) tmp = n['noise'] img = tmp.oriImg del n, tmp elif i[0] == 'rotation': angle = random.randint(0, 45) r = imgRotation(img, flag=False, angle=angle) tmp = r['rotation'] img = tmp.oriImg del r, tmp elif i[0] == 'trans': t = imgTranslation(img, flag=False) tmp = t['trans'] img = tmp.oriImg del t, tmp elif i[0] == 'zoom': zoomFactor = random.uniform(0.8, 1.8) z = imgZoom(img, zoomFactor, flag=False) tmp = z['zoom'] img = tmp.oriImg del z, tmp elif i[0] == 'flip': imgList = [] f = imgFlip(img, flag=False) tmp = f['h_v'] imgList.append(tmp.oriImg) tmp = f['h'] imgList.append(tmp.oriImg) tmp = f['v'] imgList.append(tmp.oriImg) img = imgList del tmp, f, imgList parent_path = os.path.dirname(filepath) if os.path.exists(parent_path + os.sep + 'augimgs_'): pass else: os.makedirs(parent_path + os.sep + 'augimgs_') tmp = os.path.splitext(filepath)[0] fileName = tmp.split(os.sep)[-1] if isinstance(img, np.ndarray): io.imsave( parent_path + os.sep + 'augimgs_' + os.sep + fileName + '_{}_assumble.jpg'.format(num), img) logger.info("Done!") logger.info("see here {}".format(parent_path + os.sep + 'augimgs_')) elif isinstance(img, list): for i in range(0, len(img)): io.imsave( parent_path + os.sep + 'augimgs_' + os.sep + fileName + '_{}_assumble{}.jpg'.format(num, i), img[i]) logger.info("Done!") logger.info("see here {}".format(parent_path + os.sep + 'augimgs_'))
def mosiacScript_no_reshape(imgs: list, xmls: list, savePath: str, flag=False): heightFactor = random.uniform(0.1, 0.5) widthFactor = random.uniform(0.1, 0.5) img1, img2, img3, img4 = imgs[0], imgs[1], imgs[2], imgs[3] if not type(imgs) is list or not type(xmls) is list: logger.error('Input must be list!') return imgname = getName(xmls) # imgname = 'test1123' folder = savePath mosiacImg, res, _, _ = mosiac_img_no_reshape(imgs, heightFactor, widthFactor) front = res[0] # print(front) # print(heightFactor_,widthFactor_) heightFactor = min(heightFactor, 1 - heightFactor) widthFactor = min(widthFactor, 1 - widthFactor) # print(heightFactor, widthFactor) tree1 = ET.parse(xmls[0]) tree2 = resizeScript(img2, xmls[1], heightFactor=img1.shape[0] / img2.shape[0], widthFactor=img1.shape[1] / img2.shape[1], flag=False) tree3 = resizeScript(img3, xmls[2], heightFactor=img1.shape[0] / img3.shape[0], widthFactor=img1.shape[1] / img3.shape[1], flag=False) tree4 = resizeScript(img4, xmls[3], heightFactor=img1.shape[0] / img4.shape[0], widthFactor=img1.shape[1] / img4.shape[1], flag=False) root1 = tree1.getroot() root2 = tree2.getroot() for box in root2.iter('bndbox'): xmin = float(box.find('xmin').text) ymin = float(box.find('ymin').text) xmax = float(box.find('xmax').text) ymax = float(box.find('ymax').text) box.find('xmin').text = str( int(xmin + widthFactor * mosiacImg.shape[1])) box.find('xmax').text = str( int(xmax + widthFactor * mosiacImg.shape[1])) root3 = tree3.getroot() for box in root3.iter('bndbox'): xmin = float(box.find('xmin').text) ymin = float(box.find('ymin').text) xmax = float(box.find('xmax').text) ymax = float(box.find('ymax').text) box.find('ymin').text = str( int(ymin + heightFactor * mosiacImg.shape[0])) box.find('ymax').text = str( int(ymax + heightFactor * mosiacImg.shape[0])) root4 = tree4.getroot() for box in root4.iter('bndbox'): xmin = float(box.find('xmin').text) ymin = float(box.find('ymin').text) xmax = float(box.find('xmax').text) ymax = float(box.find('ymax').text) box.find('xmin').text = str( int(xmin + widthFactor * mosiacImg.shape[1])) box.find('xmax').text = str( int(xmax + widthFactor * mosiacImg.shape[1])) box.find('ymin').text = str( int(ymin + heightFactor * mosiacImg.shape[0])) box.find('ymax').text = str( int(ymax + heightFactor * mosiacImg.shape[0])) boxes = [] r1, r2, r3, r4 = getBoxes(front, root1, root2, root3, root4, mosiacImg.shape, heightFactor=heightFactor, widthFactor=widthFactor) for box in r1.iter('object'): # print(box) boxes.append(box) for box in r2.iter('object'): # print(box) boxes.append(box) for box in r3.iter('object'): # print(box) boxes.append(box) for box in r4.iter('object'): # print(box) boxes.append(box) # print(len(boxes)) imgshape = mosiacImg.shape objs = [] for o in boxes: obj = dict() name = o.find('name').text difficult = 0 xmlbox = o.find('bndbox') b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text)) tmp = dict() tmp['xmin'] = str(int(b[0])) tmp['ymin'] = str(int(b[2])) tmp['xmax'] = str(int(b[1])) tmp['ymax'] = str(int(b[3])) # print(tmp) if not (int(tmp['xmin']) == 0 and int(tmp['xmax']) == 0 and int(tmp['ymin']) == 0 and int(tmp['ymax']) == 0): obj['name'] = name obj['difficult'] = difficult obj['bndbox'] = tmp objs.append(obj) del tmp # print(len(objs)) tmpPath = savePath + os.sep + imgname + '.xml' filepath = tmpPath.replace('.xml', '.jpg') filename = imgname + '.jpg' img2xml_multiobj(tmpPath, tmpPath, folder, filename, filepath, imgshape[1], imgshape[0], objs) logger.info('Saved to {}.'.format(tmpPath)) if flag: skimage.io.imsave(filepath, mosiacImg)
def mosiacScript(imgs: list, xmls: list, savePath: str, flag=False): heightFactor = random.uniform(0.3, 0.7) widthFactor = random.uniform(0.3, 0.7) if not type(imgs) is list or not type(xmls) is list: logger.error('Input must be list!') return # imgs if len(imgs) == 0: logger.error('None image found!') return if len(imgs) == 1: for _ in range(0, 3): imgs.append(imgs[0]) if len(imgs) == 2: for _ in range(0, 2): imgs.append(imgs[0]) if len(imgs) == 3: for _ in range(0, 1): imgs.append(imgs[0]) # xmls if len(xmls) == 0: logger.error('None xml found!') return if len(xmls) == 1: for _ in range(0, 3): xmls.append(xmls[0]) if len(xmls) == 2: for _ in range(0, 2): xmls.append(xmls[0]) if len(xmls) == 3: for _ in range(0, 1): xmls.append(xmls[0]) imgname = getName(xmls) folder = savePath mHeight, mWidth = getMeanSize(imgs) mosiacImg = mosiac_img(imgs, heightFactor, widthFactor) objs = [] imgshape = mosiacImg.shape for idx in range(len(xmls)): in_file = open(xmls[idx]) tree = ET.parse(in_file) root = tree.getroot() for o in root.iter('object'): obj = dict() name = o.find('name').text difficult = 0 xmlbox = o.find('bndbox') b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text)) # print('===========================') # print(b) bb = x2yVert((mWidth, mHeight), b) x, y, w, h = bb[0], bb[1], bb[2], bb[3] if idx == 0: bbox = y2xVert( (imgshape[1] * widthFactor, imgshape[0] * heightFactor), x, y, w, h) elif idx == 1: bbox = y2xVert((imgshape[1] * (1 - widthFactor), imgshape[0] * heightFactor), x, y, w, h) bbox[0] = bbox[0] + int(widthFactor * imgshape[1]) bbox[1] = bbox[1] + int(widthFactor * imgshape[1]) elif idx == 2: bbox = y2xVert((imgshape[1] * widthFactor, imgshape[0] * (1 - heightFactor)), x, y, w, h) bbox[2] = bbox[2] + int(heightFactor * imgshape[0]) bbox[3] = bbox[3] + int(heightFactor * imgshape[0]) else: bbox = y2xVert((imgshape[1] * (1 - widthFactor), imgshape[0] * (1 - heightFactor)), x, y, w, h) bbox[0] = bbox[0] + int(widthFactor * imgshape[1]) bbox[2] = bbox[2] + int(heightFactor * imgshape[0]) bbox[1] = bbox[1] + int(widthFactor * imgshape[1]) bbox[3] = bbox[3] + int(heightFactor * imgshape[0]) # print(x, y, w, h) # w = w # h = h # bbox = y2xVert((imgshape[1],imgshape[0]), x, y, w, h) tmp = dict() tmp['xmin'] = str(int(bbox[0])) tmp['ymin'] = str(int(bbox[2])) tmp['xmax'] = str(int(bbox[1])) tmp['ymax'] = str(int(bbox[3])) obj['name'] = name obj['difficult'] = difficult obj['bndbox'] = tmp del tmp objs.append(obj) tmpPath = savePath + os.sep + imgname + '.xml' filepath = tmpPath.replace('.xml', '.jpg') filename = imgname + '.jpg' img2xml_multiobj(tmpPath, tmpPath, folder, filename, filepath, imgshape[1], imgshape[0], objs) logger.info('Saved to {}.'.format(tmpPath)) if flag: skimage.io.imsave(filepath, mosiacImg)
def y2xConvert(txtPath, imgPath, labelPath): logger.info('only *.jpg supported right now!') labels = readLabels(labelPath) if not os.path.exists(txtPath): raise FileNotFoundError('file not found') else: if os.path.isfile(txtPath): # pass parent_path = os.path.dirname(txtPath) filename = os.path.split(imgPath)[1] imgname = os.path.splitext(filename)[0] logger.info('single file found') image = io.imread(imgPath) folder = os.path.dirname(imgPath) imgShape = image.shape objs = [] with open(txtPath, 'r', encoding='utf-8') as f: contents = f.readlines() if len(contents) > 0: for c in contents: obj = dict() tmp = c.split(' ') clas, x, y, w, h = int( tmp[0]), tmp[1], tmp[2], tmp[3], tmp[4] bbox = convert(imgShape, float(x), float(y), float(w), float(h)) # print(bbox) obj['name'] = labels[clas] obj['difficult'] = 0 obj['bndbox'] = { 'xmin': bbox[0], 'ymin': bbox[2], 'xmax': bbox[1], 'ymax': bbox[3] } objs.append(obj) tmpPath = parent_path + os.sep + '_xmls_' + os.sep + imgname + '.xml' if not os.path.exists(parent_path + os.sep + '_xmls_'): os.mkdir(parent_path + os.sep + '_xmls_') img2xml_multiobj(tmpPath, tmpPath, folder, filename, imgPath, imgShape[1], imgShape[0], objs) logger.info('Done! See {} .'.format(tmpPath)) else: logger.info('Multiple files found') parent_path = os.path.dirname(txtPath) if not os.path.exists(parent_path + os.sep + '_xmls_'): os.mkdir(parent_path + os.sep + '_xmls_') txts = glob.glob(txtPath + os.sep + "*.txt") for i in tqdm(txts): filename = os.path.split(i)[1] imgname = os.path.splitext(filename)[0] i_imgPath = imgPath + os.sep + imgname + '*.jpg' if not os.path.exists(i_imgPath): logger.error('image not found!') return image = io.imread(i_imgPath) folder = imgPath imgShape = image.shape objs = [] with open(i, 'r', encoding='utf-8') as f: contents = f.readlines() if len(contents) > 0: for c in contents: obj = dict() tmp = c.split(' ') clas, x, y, w, h = int( tmp[0]), tmp[1], tmp[2], tmp[3], tmp[4] bbox = convert(imgShape, float(x), float(y), float(w), float(h)) # print(bbox) obj['name'] = labels[clas] obj['difficult'] = 0 obj['bndbox'] = { 'xmin': bbox[0], 'ymin': bbox[2], 'xmax': bbox[1], 'ymax': bbox[3] } objs.append(obj) tmpPath = parent_path + os.sep + '_xmls_' + os.sep + imgname + '.xml' img2xml_multiobj(tmpPath, tmpPath, folder, filename, imgPath, imgShape[1], imgShape[0], objs) logger.info('Done! See {} .'.format(parent_path + os.sep + '_xmls_'))
def script(): """ eg. argList = [('-l', '--labels', 'label files path','store_true')] """ argList = [ ('-n', '--nolabel', 'image augmentation without labels'), ('-H', '--HELP', 'show specific help informaton about supported method'), ('-X', '--labelImg', 'image augmentation for labelImg, default labelme. "X" for xml'), # ('--number', 'image augmentation numbers, default 1'), { 'shortName': '-N', 'fullName': '--number', 'type': int, 'help': 'image augmentation numbers, default 1' }, ('-L', '--nolog', 'remove "annoying" logs'), { 'shortName': '-c', 'fullName': '--classfilepath', 'type': str, 'help': 'class-information-path(for labelme is a *.yaml file,for labelImg is a *.txt file. without this file, this script has some errors when generate mask files and image augumentation.)' } ] p = Parser(argList, __appname__) parser = p.get_parser() args = vars(parser.parse_args()) # print(args) if args['version']: # print(1) from convertmask import __version__ print(__version__) del __version__ return if not args['method'] and not args['version']: parser.print_help() return if args['method'] and not args['input'] and not args['HELP']: logger.error('<=== INPUT FOLDER/FILE MUST NOT BE NULL ===>') return if args['nolog']: ccfg.setConfigParam(ccfg.cfp, 'log', 'show', 'False') if args['method'] not in __support_methods__ and args[ 'method'] not in supported_simplified_methods: # print(args['method']) kvs = getKV(__support_methods_simplified__) logger.warning(' only ==>{} are supported'.format('\n==>'.join(kvs))) lis = difflib.get_close_matches(args['method'], __support_methods__) # print(lis) if len(lis) > 0: logger.info('do you mean: {} ?'.format(' OR '.join(lis))) del lis return if args['method'] == 'mask2json' or args[ 'method'] == __support_methods_simplified__['mask2json']: if args['HELP']: print('\n') print("<==== {} detailed information ====>".format(args['method'])) print('\n') print('This method parameter list should follow this order.') print( ' origin-image-path(necessary), mask-image-path(necessary), yaml-file-path(can be blank,better dont)' ) print( ' origin images are used to generate base64 code. mask images are used to generate polygons. yaml file saves classes information' ) print('\n') print('<==== The End ====>') print('\n') else: params = args['input'] if len(params) < 2: raise MethodInputException('Not enough input parameters') elif len(params) == 2: inputOriimgPath = params[0] inputMaskPath = params[1] savePath = os.path.dirname(inputMaskPath) inputYamlPath = '' elif len(params) == 3: inputOriimgPath = params[0] inputMaskPath = params[1] savePath = os.path.dirname(inputMaskPath) inputYamlPath = params[2] else: raise MethodInputException('Too much input parameters') getJsons(inputOriimgPath, inputMaskPath, savePath, inputYamlPath) print('Done!') if args['method'] == 'mask2xml' or args[ 'method'] == __support_methods_simplified__['mask2xml']: if args['HELP']: print('\n') print("<==== {} detailed information ====>".format(args['method'])) print('\n') print('This method parameter list should follow this order.') print( ' origin-image-path(necessary), mask-image-path(necessary)') print('\n') print('<==== The End ====>') print('\n') else: params = args['input'] if len(params) < 2: raise MethodInputException('Not enough input parameters') elif len(params) == 2: inputOriimgPath = params[0] inputMaskPath = params[1] savePath = os.path.dirname(inputMaskPath) else: raise MethodInputException('Too much input parameters') getXmls(inputOriimgPath, inputMaskPath, savePath) print('Done!') if args['method'] == 'json2xml' or args[ 'method'] == __support_methods_simplified__['json2xml']: if args['HELP']: print('\n') print("<==== {} detailed information ====>".format(args['method'])) print('\n') print('This method parameter list should follow this order.') print(' json-file-path(necessary)') print('\n') print('<==== The End ====>') print('\n') else: params = args['input'] if len(params) < 1: raise MethodInputException('Not enough input parameters') elif len(params) == 1: inputJsonPath = params[0] else: raise MethodInputException('Too much input parameters') j2xConvert(inputJsonPath) print('Done!') if args['method'] == 'json2mask' or args[ 'method'] == __support_methods_simplified__['json2mask']: if args['HELP']: print('\n') print("<==== {} detailed information ====>".format(args['method'])) print('\n') print('This method parameter list should follow this order.') print(' json-file-path(necessary)') print('\n') print('<==== The End ====>') print('\n') else: params = args['input'] if len(params) < 1: raise MethodInputException('Not enough input parameters') elif len(params) == 1: inputJsonPath = params[0] else: raise MethodInputException('Too much input parameters') processor(inputJsonPath) print('Done!') if args['method'] == 'augmentation' or args[ 'method'] == __support_methods_simplified__['augmentation']: if not args['number']: number = 1 else: number = args['number'] if args['HELP']: print('\n') print("<==== {} detailed information ====>".format(args['method'])) print('\n') print('This method parameter list should follow this order.') print( ' origin-image-path(necessary), label-file-path(alternative).' ) print(' --nolabel can be added to just augment images.') print( ' --labelImg can be added to augment xmls, default jsons.') print('\n') print('<==== The End ====>') print('\n') else: params = args['input'] if args['classfilepath']: classFilePath = args['classfilepath'] else: classFilePath = '' if len(params) < 1: raise MethodInputException('Not enough input parameters') elif len(params) == 1 and args['nolabel']: inputFilePath = params[0] imgAug_withoutLabels(inputFilePath, number) print('Done!') elif len(params) == 2: inputFilePath = params[0] inputJsonPath = params[1] if not args['labelImg']: imgAug_withLabels(inputFilePath, inputJsonPath, number, yamlFilePath=classFilePath) else: imgAug_LabelImg(inputFilePath, inputJsonPath, number) print('Done!') else: raise MethodInputException('There must be some errors.') if args['method'] == 'xml2json' or args[ 'method'] == __support_methods_simplified__['xml2json']: logger.info('<=== This is a test function. ===>') if args['HELP']: print('\n') print("<==== {} detailed information ====>".format(args['method'])) print('\n') print('This method parameter list should follow this order.') print(' xml-file-path(necessary), origin-image-path(necessary)') print(' currently, only single file conversion supported.') print( ' --labelImg can be added which means xmls are generated by labelImg.' ) print('\n') print('<==== The End ====>') print('\n') else: params = args['input'] if len(params) < 2: raise MethodInputException('Not enough input parameters') elif len(params) == 2: inputFilePath = params[0] inputJsonPath = params[1] if not args['labelImg']: x2jConvert(inputFilePath, inputJsonPath) else: x2jConvert_pascal(inputFilePath, inputJsonPath) print('Done!') else: raise MethodInputException('Too much input parameters') if args['method'] == 'yolo2xml' or args[ 'method'] == __support_methods_simplified__['yolo2xml']: if args['HELP']: print('\n') print("<==== {} detailed information ====>".format(args['method'])) print('\n') print('This method parameter list should follow this order.') print( ' txt-file-path(necessary), origin-image-path(necessary), class-file-path(necessary' ) print(' currently, only single file conversion supported.') print('\n') print('<==== The End ====>') print('\n') else: params = args['input'] if len(params) < 3: raise MethodInputException('Not enough input parameters') elif len(params) == 3: txtpath = params[0] imgpath = params[1] labelPath = params[2] else: raise MethodInputException('Too much input parameters') y2xConvert(txtPath=txtpath, imgPath=imgpath, labelPath=labelPath) print('Done!') if args['method'] == 'xml2yolo' or args[ 'method'] == __support_methods_simplified__['xml2yolo']: if args['HELP']: print('\n') print("<==== {} detailed information ====>".format(args['method'])) print('\n') print('This method parameter list should follow this order.') print(' xml-file-path(necessary), class-file-path(alternative)') print( ' class-file is a txt file saves class information. without this file, a txt file will be generated automaticly, which may be in different orders' ) print('\n') print('<==== The End ====>') print('\n') else: params = args['input'] if len(params) < 1: raise MethodInputException('Not enough input parameters') elif len(params) == 1: xmlpath = params[0] x2yConvert(xmlpath) print('Done!') elif len(params) == 2: xmlpath = params[0] labelpath = params[1] x2yConvert(xmlpath, labelpath) print('Done!') else: raise MethodInputException('Too much input parameters')
def aug_labelimg(filepath, xmlpath, augs=None, num=0): default_augs = ['noise', 'rotation', 'trans', 'flip', 'zoom'] if augs is None: augs = ['noise', 'rotation', 'trans', 'flip', 'zoom'] else: if not isinstance(augs, list): try: augs = list(str(augs)) except: raise ValueError( "parameter:aug's type is wrong. expect a string or list,got {}" .format(str(type(augs)))) augs = list(set(augs).intersection(set(default_augs))) if len(augs) > 0 and augs is not None: pass else: logger.warning( 'augumentation method is not supported.using default augumentation method.' ) augs = ['noise', 'rotation', 'trans', 'flip', 'zoom'] if 'flip' in augs: augs.remove('flip') augs.append('flip') l = np.random.randint(2, size=len(augs)) if np.sum(l) == 0: l[0] = 1 # l[l != 1] = 1 ## For test l = l.tolist() p = list(zip(augs, l)) parent_path, file_name = os.path.split(filepath) filename, ext = os.path.splitext(file_name) if not os.path.exists(parent_path + os.sep + 'tmps_'): os.mkdir(parent_path + os.sep + 'tmps_') if not os.path.exists(parent_path + os.sep + 'augxmls_'): os.mkdir(parent_path + os.sep + 'augxmls_') labelPath = parent_path + os.sep + 'tmps_' + os.sep + filename + '_tmps.xml' shutil.copyfile(xmlpath, labelPath) img = io.imread(filepath) for i in p: if i[1] == 1: # if i[0] == 'test': # pass if i[0] == 'rotation': angle = random.randint(-10, 10) r = rotate(img, labelPath, angle) img, labelPath = r.oriImg, r.processedImg del r elif i[0] == 'trans': t = translation(img, labelPath) img, labelPath = t.oriImg, t.processedImg del t elif i[0] == 'zoom': z = zoom(img, labelPath) img, labelPath = z.oriImg, z.processedImg del z elif i[0] == 'noise': n = noise(img, labelPath) img, labelPath = n.oriImg, n.processedImg del n elif i[0] == 'flip': f = flip(img, labelPath) # img,labelPath = img = [] labelPath = [] for i in f: img.append(i.oriImg) labelPath.append(i.processedImg) del f if not isinstance(img, list): resXmlPath = parent_path + os.sep + 'augxmls_' + os.sep + filename + '_assumbel.xml' resImgPath = parent_path + os.sep + 'augxmls_' + os.sep + filename + '_assumbel.jpg' tree = ET.parse(labelPath) root = tree.getroot() root.find('folder').text = str(resImgPath.split(os.sep)[-1] if \ resImgPath.split(os.sep)[-1] != "" else resImgPath.split(os.sep)[-2] ) root.find('filename').text = filename + '_assumbel.jpg' root.find('path').text = resImgPath tree.write(resXmlPath) io.imsave(resImgPath, img) else: for i in range(0, len(img)): resXmlPath = parent_path + os.sep + 'augxmls_' + os.sep + filename + '_assumbel_{}.xml'.format( i) resImgPath = parent_path + os.sep + 'augxmls_' + os.sep + filename + '_assumbel_{}.jpg'.format( i) tree = ET.parse(labelPath[i]) root = tree.getroot() root.find('folder').text = str(resImgPath.split(os.sep)[-1] if \ resImgPath.split(os.sep)[-1] != "" else resImgPath.split(os.sep)[-2] ) root.find( 'filename').text = filename + '_assumbel_{}.jpg'.format(i) root.find('path').text = resImgPath tree.write(resXmlPath) io.imsave(resImgPath, img[i]) logger.info('Done! See {}.'.format(parent_path + os.sep + 'augxmls_'))
def imgZoom(oriImg: str, oriLabel: str, size: float = 0, flag=True, labelFile=''): """ size : The zoom factor along the axes, default 0.8~1.8 """ # pass if isinstance(oriImg, str): if os.path.exists(oriImg): img = io.imread(oriImg) else: raise FileNotFoundError('Original image not found') elif isinstance(oriImg, np.ndarray): img = oriImg else: logger.error('input {} type {} error'.format('oriImg', type(oriImg))) return try: size = float(size) # if size == 0.0: # raise ValueError('zoom factor cannot be zero') except: logger.warning('input {} type error ,got {}.'.format( 'size', type(size))) size = random.uniform(0.8, 1.8) size = round(size, 2) if size <= 0 or size == 1: size = random.uniform(0.8, 1.8) size = round(size, 2) resOri = _getZoomedImg(img, size) if isinstance(oriLabel, str): if os.path.exists(labelFile): # print(True) mask = processorWithLabel(oriLabel, labelFile, flag=True) else: mask = processor(oriLabel, flag=True) elif isinstance(oriLabel, np.ndarray): mask = oriLabel else: raise TypeError( "input parameter 'oriLabel' type {} is not supported".format( type(oriLabel))) maskImgs = _splitImg(mask) # print('========='+str(len(maskImgs))) resMask = np.zeros((resOri.shape[0], resOri.shape[1])) if len(maskImgs) > 0: for m in maskImgs: # print(np.max(m.img)) res = _getZoomedImg(m.img, size) res[res > 0] = m.clasId res[res != m.clasId] = 0 resMask += res # io.imsave('D:\\testALg\\mask2json\\mask2json\\static\\jsons_\\{}.png'.format(np.max(m.img)),resMask*255) resMask = resMask.astype(np.uint8) # io.imsave('D:\\testALg\\mask2json\\mask2json\\static\\jsons_\\12.png',resMask*255) # print(np.max(resMask)) if np.max(resMask) == 0: logger.warning( 'After zoom,none ROIs detected! Zoomfactor={} maybe too large.'. format(size)) # return if flag: parent_path = os.path.dirname(oriLabel) if os.path.exists(parent_path + os.sep + 'jsons_'): pass else: os.makedirs(parent_path + os.sep + 'jsons_') fileName = oriLabel.split(os.sep)[-1].replace('.json', '') io.imsave( parent_path + os.sep + 'jsons_' + os.sep + fileName + '_zoom.jpg', resOri) zoomedMask_j = getMultiShapes(parent_path + os.sep + 'jsons_' + os.sep + fileName + '_zoom.jpg', resMask, flag=True, labelYamlPath=labelFile) saveJsonPath = parent_path + os.sep + 'jsons_' + os.sep + fileName + '_zoom.json' if zoomedMask_j is not None: with open(saveJsonPath, 'w') as f: f.write(zoomedMask_j) logger.info('Done! See {} .'.format( saveJsonPath)) if LOGFlag == 'True' else entity.do_nothing() else: pass else: d = dict() # print(resOri.shape) # io.imsave('D:\\testALg\\mask2json\\mask2json\\static\\jsons_\\13.png',resMask*255) d['zoom'] = Ori_Pro(resOri, resMask) return d