def imgTranslation(oriImg: str, oriLabel: str, flag=True, labelFile='', factor=0.5): """ image translation factor : Translation factor """ 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(imgFlip)) return imgShape = img.shape if isinstance(oriLabel, str): if os.path.exists(labelFile): 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))) trans_h = random.randint(0, int(factor * imgShape[1])) trans_v = random.randint(0, int(factor * imgShape[0])) trans_mat = np.float32([[1, 0, trans_h], [0, 1, trans_v]]) transImg = cv2.warpAffine(img, trans_mat, (imgShape[1], imgShape[0])) transMask = cv2.warpAffine(mask, trans_mat, (imgShape[1], imgShape[0])) 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 + '_translation.jpg', transImg) transMask_j = getMultiShapes(parent_path + os.sep + 'jsons_' + os.sep + fileName + '_translation.jpg', transMask, flag=True, labelYamlPath='') saveJsonPath = parent_path + os.sep + 'jsons_' + os.sep + fileName + '_translation.json' if transMask_j is not None: with open(saveJsonPath, 'w') as f: f.write(transMask_j) else: pass else: d = dict() d['trans'] = Ori_Pro(transImg, transMask) return d
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 imgRotation(oriImg: str, oriLabel: str, angle=30, scale=1, flag=True, labelFile=''): """ 旋转 """ logger.warning( 'rotation may cause salt-and-pepper noise. in order to solve this issue, small objects may be missing!' ) 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(imgFlip)) return imgShape = img.shape if isinstance(oriLabel, str): if os.path.exists(labelFile): 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))) center = (0.5 * imgShape[1], 0.5 * imgShape[0]) mat = cv2.getRotationMatrix2D(center, angle, scale) affedImg = cv2.warpAffine(img, mat, (imgShape[1], imgShape[0])) affedMask = cv2.warpAffine(mask, mat, (imgShape[1], imgShape[0])) 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 + '_rotation.jpg', affedImg) affedMask_j = getMultiShapes(parent_path + os.sep + 'jsons_' + os.sep + fileName + '_rotation.jpg', affedMask, flag=True, labelYamlPath='') saveJsonPath = parent_path + os.sep + 'jsons_' + os.sep + fileName + '_rotation.json' if affedMask_j is not None: with open(saveJsonPath, 'w') as f: f.write(affedMask_j) else: pass else: d = dict() d['rotation'] = Ori_Pro(affedImg, affedMask) return d
def imgNoise(oriImg: str, oriLabel: str, flag=True, labelFile=''): """ see skimage.util.random_noise """ noise_type = ['gaussian', 'poisson', 's&p', 'speckle'] l = np.random.randint(2, size=len(noise_type)).tolist() # print(l) p = list(zip(noise_type, l)) 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') return for i in p: if i[1] != 0: img = snoise.random_noise(img, mode=i[0]) img = np.array(img * 255).astype(np.uint8) if flag: # parent_path = os.path.dirname(oriImg) (parent_path, file_path) = os.path.split(oriImg) if os.path.exists(parent_path + os.sep + 'jsons_'): pass else: os.makedirs(parent_path + os.sep + 'jsons_') # fileName = oriImg.split(os.sep)[-1].replace('.json', '') fileName = os.path.splitext(file_path)[0] io.imsave( parent_path + os.sep + 'jsons_' + os.sep + fileName + '_noise.jpg', img) try: if isinstance(oriLabel, str): shutil.copyfile( oriLabel, parent_path + os.sep + 'jsons_' + os.sep + fileName + '_noise.json') base64code = imgEncode(parent_path + os.sep + 'jsons_' + os.sep + fileName + '_noise.jpg') with open( parent_path + os.sep + 'jsons_' + os.sep + fileName + '_noise.json', 'r') as f: load_dict = json.load(f) load_dict['imageData'] = base64code with open( parent_path + os.sep + 'jsons_' + os.sep + fileName + '_noise.json', 'w') as f: # json.dump(load_dict,parent_path+os.sep+'jsons_'+os.sep+fileName+'_noise.json') f.write(json.dumps(load_dict)) elif isinstance(oriLabel, np.ndarray): """ labeled file can be an Image """ noisedMask_j = getMultiShapes(parent_path + os.sep + 'jsons_' + os.sep + fileName + '_noise.jpg', oriLabel, flag=True, labelYamlPath=labelFile) with open( parent_path + os.sep + 'jsons_' + os.sep + fileName + '_noise.json', 'w') as f: f.write(json.dumps(noisedMask_j)) except Exception: print(traceback.format_exc()) else: d = dict() # mask = processor(oriLabel,flag=True) if isinstance(oriLabel, str): if os.path.exists(labelFile): 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))) # print('======================') # print(np.max(mask)) # print('======================') d['noise'] = Ori_Pro(img, mask) return d
def imgFlip(oriImg: str, oriLabel: str, flip_list=[1, 0, -1], flag=True, labelFile=''): """ flipList: flip type. see cv2.flip : 1: 水平翻转 \n 0: 垂直翻转 \n -1: 同时翻转 \n >>> import cv2 >>> help(cv2.flip) """ 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(imgFlip)) return try: if len(flip_list) > 1 and (1 in flip_list or 0 in flip_list or -1 in flip_list): if isinstance(oriLabel, str): if os.path.exists(labelFile): 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") # print(type(mask)) h_ori = cv2.flip(img, 1) v_ori = cv2.flip(img, 0) h_v_ori = cv2.flip(img, -1) h_mask = cv2.flip(mask, 1) if 1 in flip_list else None v_mask = cv2.flip(mask, 0) if 0 in flip_list else None h_v_mask = cv2.flip(mask, -1) if -1 in flip_list else None """ maybe dict or zip is better :) """ 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 + '_h.jpg', h_ori) if 1 in flip_list else do_nothing() io.imsave( parent_path + os.sep + 'jsons_' + os.sep + fileName + '_v.jpg', v_ori) if 0 in flip_list else do_nothing() io.imsave( parent_path + os.sep + 'jsons_' + os.sep + fileName + '_h_v.jpg', h_v_ori) if -1 in flip_list else do_nothing() h_j = getMultiShapes( parent_path + os.sep + 'jsons_' + os.sep + fileName + '_h.jpg', h_mask, flag=True, labelYamlPath='') if h_mask is not None else None # h_j = getMultiShapes(parent_path+os.sep+'jsons_'+os.sep+fileName+'_h.jpg',h_mask,flag=True,labelYamlPath='D:\\testALg\\mask2json\\mask2json\\multi_objs_json\\info.yaml') v_j = getMultiShapes( parent_path + os.sep + 'jsons_' + os.sep + fileName + '_v.jpg', v_mask, flag=True, labelYamlPath='') if v_mask is not None else None h_v_j = getMultiShapes( parent_path + os.sep + 'jsons_' + os.sep + fileName + '_h_v.jpg', h_v_mask, flag=True, labelYamlPath='') if h_v_mask is not None else None for saveJsonPath in [ parent_path + os.sep + 'jsons_' + os.sep + fileName + '_h.json', parent_path + os.sep + 'jsons_' + os.sep + fileName + '_v.json', parent_path + os.sep + 'jsons_' + os.sep + fileName + '_H_V.json' ]: # if saveJsonPath is not None: # print(saveJsonPath) if saveJsonPath.endswith('_h.json'): if h_j is not None: with open(saveJsonPath, 'w') as f: f.write(h_j) else: pass elif saveJsonPath.endswith('_v.json'): if v_j is not None: with open(saveJsonPath, 'w') as f: f.write(v_j) else: pass elif saveJsonPath.endswith('_H_V.json'): if h_v_j is not None: with open(saveJsonPath, 'w') as f: f.write(h_v_j) else: pass rmQ.rm(saveJsonPath) if os.path.exists( saveJsonPath) else do_nothing() return "" else: d = dict() d['h'] = Ori_Pro(h_ori, h_mask) d['v'] = Ori_Pro(v_ori, v_mask) d['h_v'] = Ori_Pro(h_v_ori, h_v_mask) return d else: logger.warning("<===== param:flip_list is not valid =====>") except Exception: # print(e) print(traceback.format_exc())
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
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')