def load_model_and_weights(args, mode, appcfg): log.debug("---------------------------->") from falcon.arch import Model as M archcfg = M.get_archcfg(appcfg) log.debug("archcfg: {}".format(archcfg)) cmdcfg = archcfg # modelcfg_path = os.path.join(appcfg.PATHS.AI_MODEL_CFG_PATH, cmdcfg.model_info) modelcfg_path = apputil.get_abs_path(appcfg, cmdcfg, 'AI_MODEL_CFG_PATH') log.info("modelcfg_path: {}".format(modelcfg_path)) modelcfg = M.get_modelcfg(modelcfg_path) log.info("modelcfg: {}".format(modelcfg)) num_classes_model = apputil.get_num_classes(modelcfg) name = modelcfg.name cmdcfg.name = name cmdcfg.config.NAME = name cmdcfg.config.NUM_CLASSES = num_classes_model dnnmod = M.get_module(cmdcfg.dnnarch) load_model_and_weights = M.get_module_fn(dnnmod, "load_model_and_weights") model = load_model_and_weights(args, mode, cmdcfg, modelcfg, appcfg) status = True return status
def load_model_and_weights(mode, cmdcfg, appcfg): """ Load the model and weights Preferences Device to load the neural network on. Useful if you're training a model on the same machine, in which case use CPU and leave the GPU for training. values: '/cpu:0' or '/gpu:0' """ log.info("load_model_and_weights:----------------------------->") device = appcfg['APP']['DEVICE'] dnncfg = get_dnncfg(cmdcfg['config']) log.info("device: {}".format(device)) log.info("dnncfg: {}".format(dnncfg)) model = None log_dir_path = apputil.get_abs_path(appcfg, cmdcfg, 'AI_LOGS') # # with tf.device(device): # # model = modellib.MaskRCNN(mode=mode, config=dnncfg, model_dir=log_dir_path) # # weights = cmdcfg['weights'] # # if weights and weights.lower() == "last": # # weights_path = model.find_last() # # else: # # weights_path = cmdcfg['weights_path'] # # log.debug("Loading weights from weights_path: {}".format(weights_path)) # # ## TODO: pass this error to the router for API consumption # # if not os.path.exists(weights_path) or not os.path.isfile(weights_path): # # raise Exception('weights_path does not exists: {}'.format(weights_path)) # # if mode == appcfg['APP']['TRAIN_MODE']: # # model.load_weights(weights_path, by_name=cmdcfg['load_weights']['by_name'], exclude=cmdcfg['load_weights']['exclude']) # # elif mode == appcfg['APP']['TEST_MODE']: # # model.load_weights(weights_path, by_name=cmdcfg['load_weights']['by_name']) # # log.info("Loaded weights successfully from weights_path: {}".format(weights_path)) ## used earlier for loading the model in the ckpt format ## Ref: lanenet-lane-detection/tools/predict.py # net = lanenet.LaneNet(phase='test', net_flag='vgg') weights_path = cmdcfg['weights_path'] log.debug("Loading weights from weights_path: {}".format(weights_path)) graph = load_graph(weights_path) return graph
def test_load_model(args, mode, appcfg): log.debug("---------------------------->") from falcon.arch import Model as M archcfg = M.get_archcfg(appcfg) log.debug("archcfg: {}".format(archcfg)) cmdcfg = archcfg modelcfg_path = os.path.join(appcfg.PATHS.AI_MODEL_CFG_PATH, cmdcfg.model_info) log.info("modelcfg_path: {}".format(modelcfg_path)) modelcfg = M.get_modelcfg(modelcfg_path) class_names = apputil.get_class_names(modelcfg) log.debug("class_names: {}".format(class_names)) num_classes = len(class_names) name = modelcfg.name cmdcfg.name = name cmdcfg.config.NAME = name cmdcfg.config.NUM_CLASSES = num_classes dnnmod = M.get_module(cmdcfg.dnnarch) weights_path = apputil.get_abs_path(appcfg, modelcfg, 'AI_WEIGHTS_PATH') cmdcfg['weights_path'] = weights_path load_model_and_weights = M.get_module_fn(dnnmod, "load_model_and_weights") model = load_model_and_weights(mode, cmdcfg, appcfg) log.debug("model: {}".format(model)) # modelsummary_path = os.path.join(appcfg.PATHS.AI_LOGS, name+"-summary.txt") # log.debug("modelsummary_path: {}".format(modelsummary_path)) # # msummary = model.keras_model.summary() # # log.debug("model.keras_model.summary(): {}".format(msummary)) # # with open(modelsummary_path, 'w') as fw: # # fw.write(msummary) return
def get_dataset_dicts(cfg, class_ids, id_map, imgs, anns, bbox_mode): # print(anns) ## => quick hack for running detectron2 with gaze data ## TODO: Convert to COCO -> if done in pre-processing, this step not required here imgs_anns = list(zip(imgs, anns)) dataset_dicts = [] extra_annotation_keys = None ## TODO: iscrowd is available in attributes as something like group ann_keys = ["iscrowd", "bbox", "keypoints", "category_id", "lbl_id" ] + (extra_annotation_keys or []) num_instances_without_valid_segmentation = 0 # print("imgs_anns: {}".format(imgs_anns[:2])) for (img_dict, anno_dict_list) in imgs_anns: # print("img_dict: {}".format(img_dict)) # print("anno_dict_list: {}".format(len(anno_dict_list))) filtered_anns = [] for key in anno_dict_list: if key["ant_type"] == "polygon": filtered_anns.append(key) # print("img_dict: {}".format(img_dict)) # print("anno_dict_list: {}".format(len(anno_dict_list))) # print("filtered_anns: {}".format(len(filtered_anns))) # print("filtered_anns: {}".format(filtered_anns)) # print("anno_dict_list: {}".format(anno_dict_list)) if len(filtered_anns) != 0: image_path = apputil.get_abs_path( cfg, img_dict, 'AI_ANNON_DATA_HOME_LOCAL') ##image_root filepath = os.path.join(image_path, img_dict['filename']) record = {} record["file_name"] = filepath record["height"] = img_dict["height"] record["width"] = img_dict["width"] image_id = record["image_id"] = img_dict["img_id"] ## coco: id objs = [] # for anno in anno_dict_list: for anno in filtered_anns: if anno["ant_type"] == "polygon": assert anno["img_id"] == image_id ## image_id obj = {key: anno[key] for key in ann_keys if key in anno} ##TODO: convert bbbox to coco format _bbox = obj['bbox'] ##TODO: verify what is BoxMode.XYWH_ABS coco_frmt_bbox = [ _bbox['xmin'], _bbox['ymin'], _bbox['width'], _bbox['height'] ] #print("coco_frmt_bbox: {}".format(coco_frmt_bbox)) obj['bbox'] = coco_frmt_bbox ## TODO: get polygon from shape_attributes and convert to coco format #segm = anno.get("segmentation", None) # assert not anno["region_attributes"] # segm=None # if anno["ant_type"]=="polygon": anno = anno["shape_attributes"] # print("anno: {}".format(anno)) px = anno["all_points_x"] py = anno["all_points_y"] poly = [(x + 0.5, y + 0.5) for x, y in zip(px, py)] poly = [p for x in poly for p in x] segm = [poly] if segm: # either list[list[float]] or dict(RLE) if not isinstance(segm, dict): # filter out invalid polygons (< 3 points) segm = [ poly for poly in segm if len(poly) % 2 == 0 and len(poly) >= 6 ] if len(segm) == 0: num_instances_without_valid_segmentation += 1 continue # ignore this instance obj["segmentation"] = segm obj["bbox_mode"] = bbox_mode obj["category_id"] = id_map[obj["lbl_id"]] ## category_id objs.append(obj) record["annotations"] = objs dataset_dicts.append(record) return dataset_dicts
def evaluate(args, mode, appcfg): """prepare the report configuration like paths, report names etc. and calls the report generation function """ log.debug("evaluate---------------------------->") subset = args.eval_on iou_threshold = args.iou log.debug("subset: {}".format(subset)) log.debug("iou_threshold: {}".format(iou_threshold)) get_mask = True auto_show = False datacfg = apputil.get_datacfg(appcfg) dbcfg = apputil.get_dbcfg(appcfg) log.debug("appcfg: {}".format(appcfg)) log.debug("datacfg: {}".format(datacfg)) dataset, num_classes, num_images, class_names, total_stats, total_verify = apputil.get_dataset_instance(appcfg, dbcfg, datacfg, subset) colors = viz.random_colors(len(class_names)) log.debug("-------") log.debug("len(colors), colors: {},{}".format(len(colors), colors)) log.debug("class_names: {}".format(class_names)) log.debug("len(class_names): {}".format(len(class_names))) log.debug("num_classes: {}".format(num_classes)) log.debug("num_images: {}".format(num_images)) log.debug("len(dataset.image_info): {}".format(len(dataset.image_info))) log.debug("len(dataset.image_ids): {}".format(len(dataset.image_ids))) # log.debug("dataset: {}".format(vars(dataset))) log.debug("-------") # log.debug("TODO: color: cc") # cc = dict(zip(class_names,colors)) name = dataset.name datacfg.name = name datacfg.classes = class_names datacfg.num_classes = num_classes archcfg = apputil.get_archcfg(appcfg) log.debug("archcfg: {}".format(archcfg)) cmdcfg = archcfg if 'save_viz_and_json' not in cmdcfg: cmdcfg.save_viz_and_json = False save_viz = args.save_viz log.debug("save_viz: {}".format(save_viz)) cmdcfg.save_viz_and_json = save_viz modelcfg_path = os.path.join(appcfg.PATHS.AI_MODEL_CFG_PATH, cmdcfg.model_info) log.info("modelcfg_path: {}".format(modelcfg_path)) modelcfg = apputil.get_modelcfg(modelcfg_path) ## for prediction, get the label information from the model information class_names_model = apputil.get_class_names(modelcfg) log.debug("class_names_model: {}".format(class_names_model)) cmdcfg.name = name cmdcfg.config.NAME = modelcfg.name cmdcfg.config.NUM_CLASSES = len(class_names_model) # class_names = apputil.get_class_names(datacfg) # log.debug("class_names: {}".format(class_names)) weights_path = apputil.get_abs_path(appcfg, modelcfg, 'AI_WEIGHTS_PATH') cmdcfg['weights_path'] = weights_path ## Prepare directory structure and filenames for reporting the evluation results now = datetime.datetime.now() ## create log directory based on timestamp for evaluation reporting timestamp = "{:%d%m%y_%H%M%S}".format(now) datacfg_ts = datacfg.timestamp if 'TIMESTAMP' in datacfg else timestamp save_viz_and_json = cmdcfg.save_viz_and_json # iou_threshold = cmdcfg.iou_threshold if 'evaluate_no_of_result' not in cmdcfg: evaluate_no_of_result = -1 else: evaluate_no_of_result = cmdcfg.evaluate_no_of_result def clean_iou(iou): return str("{:f}".format(iou)).replace('.','')[:3] path = appcfg['PATHS']['AI_LOGS'] # evaluate_dir = datacfg_ts+"-evaluate_"+clean_iou(iou_threshold)+"-"+name+"-"+subset+"-"+timestamp evaluate_dir = "evaluate_"+clean_iou(iou_threshold)+"-"+name+"-"+subset+"-"+timestamp filepath = os.path.join(path, cmdcfg.dnnarch, evaluate_dir) log.debug("filepath: {}".format(filepath)) common.mkdir_p(filepath) for d in ['splash', 'mask', 'annotations', 'viz']: common.mkdir_p(os.path.join(filepath,d)) ## gt - ground truth ## pr/pred - prediction def get_cfgfilename(cfg_filepath): return cfg_filepath.split(os.path.sep)[-1] ## generate the summary on the evaluation run evaluate_run_summary = defaultdict(list) evaluate_run_summary['name'] =name evaluate_run_summary['execution_start_time'] = timestamp evaluate_run_summary['subset'] = subset evaluate_run_summary['total_labels'] = num_classes evaluate_run_summary['total_images'] = num_images evaluate_run_summary['evaluate_no_of_result'] = evaluate_no_of_result evaluate_run_summary['evaluate_dir'] = evaluate_dir evaluate_run_summary['dataset'] = get_cfgfilename(appcfg.DATASET[appcfg.ACTIVE.DATASET].cfg_file) evaluate_run_summary['arch'] = get_cfgfilename(appcfg.ARCH[appcfg.ACTIVE.ARCH].cfg_file) evaluate_run_summary['model'] = cmdcfg['model_info'] ## classification report and confusion matrix - json and csv ## generate the filenames for what reports to be generated reportcfg = { 'filepath':filepath ,'evaluate_run_summary_reportfile':os.path.join(filepath, "evaluate_run_summary_rpt-"+subset) ,'classification_reportfile':os.path.join(filepath, "classification_rpt-"+subset) ,'confusionmatrix_reportfile':os.path.join(filepath, "confusionmatrix_rpt-"+subset) ,'iou_threshold':iou_threshold ,'evaluate_run_summary':evaluate_run_summary ,'save_viz_and_json':save_viz_and_json ,'evaluate_no_of_result':evaluate_no_of_result } log.debug("reportcfg: {}".format(reportcfg)) dnnmod = apputil.get_module(cmdcfg.dnnarch) fn_evaluate = apputil.get_module_fn(dnnmod, "evaluate") evaluate_run_summary = fn_evaluate(mode, cmdcfg, appcfg, modelcfg, dataset, datacfg, class_names, reportcfg, get_mask) return evaluate_run_summary
def predict(args, mode, appcfg): """Executes the prediction and stores the generated results TODO: 1. create the prediction configuration 2. PDB specification """ log.debug("predict---------------------------->") archcfg = apputil.get_archcfg(appcfg) log.debug("cmdcfg/archcfg: {}".format(archcfg)) cmdcfg = archcfg if 'save_viz_and_json' not in cmdcfg: cmdcfg.save_viz_and_json = False save_viz = args.save_viz show_bbox = args.show_bbox log.debug("save_viz: {}".format(save_viz)) cmdcfg.save_viz_and_json = save_viz modelcfg_path = os.path.join(appcfg.PATHS.AI_MODEL_CFG_PATH, cmdcfg.model_info) log.info("modelcfg_path: {}".format(modelcfg_path)) modelcfg = apputil.get_modelcfg(modelcfg_path) log.debug("modelcfg: {}".format(modelcfg)) api_model_key = apputil.get_api_model_key(modelcfg) log.debug("api_model_key: {}".format(api_model_key)) ## for prediction, get the label information from the model information class_names = apputil.get_class_names(modelcfg) log.debug("class_names: {}".format(class_names)) num_classes = len(class_names) name = modelcfg.name cmdcfg.name = name cmdcfg.config.NAME = name cmdcfg.config.NUM_CLASSES = num_classes dnnmod = apputil.get_module(cmdcfg.dnnarch) ## todo: hard-coding clear up cmdcfg['log_dir'] = 'predict' log_dir_path = apputil.get_abs_path(appcfg, cmdcfg, 'AI_LOGS') cmdcfg['log_dir_path'] = log_dir_path weights_path = apputil.get_abs_path(appcfg, modelcfg, 'AI_WEIGHTS_PATH') cmdcfg['weights_path'] = weights_path load_model_and_weights = apputil.get_module_fn(dnnmod, "load_model_and_weights") model = load_model_and_weights(mode, cmdcfg, appcfg) path_dtls = apputil.get_path_dtls(args, appcfg) log.debug("path_dtls: {}".format(path_dtls)) for t in ["images", "videos"]: if path_dtls[t] and len(path_dtls[t]) > 0: fname = "detect_from_"+t log.info("fname: {}".format(fname)) fn = getattr(this, fname) if fn: file_names, res = fn(appcfg, dnnmod, path_dtls[t], path_dtls['path'], model, class_names, cmdcfg, api_model_key, show_bbox) # log.debug("len(file_names), file_names: {}, {}".format(len(file_names), file_names)) else: log.error("Unkown fn: {}".format(fname)) # return file_names, res return
def train(args, mode, appcfg): log.debug("train---------------------------->") datacfg = apputil.get_datacfg(appcfg) ## Training dataset. subset = "train" log.info("subset: {}".format(subset)) dbcfg = apputil.get_dbcfg(appcfg) dataset_train, num_classes_train, num_images_train, class_names_train, total_stats_train, total_verify_train = apputil.get_dataset_instance(appcfg, dbcfg, datacfg, subset) colors = viz.random_colors(len(class_names_train)) log.info("-------") log.info("len(colors), colors: {},{}".format(len(colors), colors)) log.info("subset, class_names_train: {}, {}".format(subset, class_names_train)) log.info("subset, len(class_names_train): {}, {}".format(subset, len(class_names_train))) log.info("subset, num_classes_train: {}, {}".format(subset, num_classes_train)) log.info("subset, num_images_train: {}, {}".format(subset, num_images_train)) log.info("subset, len(dataset_train.image_info): {}, {}".format(subset, len(dataset_train.image_info))) log.info("subset, len(dataset_train.image_ids): {}, {}".format(subset, len(dataset_train.image_ids))) ## Validation dataset subset = "val" log.info("subset: {}".format(subset)) dataset_val, num_classes_val, num_images_val, class_names_val, total_stats_val, total_verify_val = apputil.get_dataset_instance(appcfg, dbcfg, datacfg, subset) log.info("-------") log.info("subset, class_names_val: {}, {}".format(subset, class_names_val)) log.info("subset, len(class_names_val): {}, {}".format(subset, len(class_names_val))) log.info("subset, num_classes_val: {}, {}".format(subset, num_classes_val)) log.info("subset, num_images_val: {}, {}".format(subset, num_images_val)) log.info("subset, len(dataset_val.image_info): {}, {}".format(subset, len(dataset_val.image_info))) log.info("subset, len(dataset_val.image_ids): {}, {}".format(subset, len(dataset_val.image_ids))) log.info("-------") ## Ensure label sequence and class_names of train and val dataset are excatly same, if not abort training assert class_names_train == class_names_val archcfg = apputil.get_archcfg(appcfg) log.debug("archcfg: {}".format(archcfg)) cmdcfg = archcfg name = dataset_train.name ## generate the modelinfo template to be used for evaluate and prediction modelinfocfg = { 'classes': class_names_train.copy() ,'classinfo': None ,'config': cmdcfg.config.copy() ,'dataset': cmdcfg.dbname ,'dbname': cmdcfg.dbname ,'dnnarch': cmdcfg.dnnarch ,'framework_type': cmdcfg.framework_type ,'id': None ,'load_weights': cmdcfg.load_weights.copy() ,'name': name ,'num_classes': num_classes_train ,'problem_id': None ,'rel_num': None ,'weights': None ,'weights_path': None ,'log_dir': None ,'checkpoint_path': None ,'model_info': None ,'timestamp': None ,'creator': None } datacfg.name = name datacfg.classes = class_names_train datacfg.num_classes = num_classes_train cmdcfg.name = name cmdcfg.config.NAME = name cmdcfg.config.NUM_CLASSES = num_classes_train modelcfg_path = os.path.join(appcfg.PATHS.AI_MODEL_CFG_PATH, cmdcfg.model_info) log.info("modelcfg_path: {}".format(modelcfg_path)) modelcfg = apputil.get_modelcfg(modelcfg_path) log_dir_path = apputil.get_abs_path(appcfg, cmdcfg, 'AI_LOGS') cmdcfg['log_dir_path'] = log_dir_path weights_path = apputil.get_abs_path(appcfg, modelcfg, 'AI_WEIGHTS_PATH') cmdcfg['weights_path'] = weights_path dnnmod = apputil.get_module(cmdcfg.dnnarch) load_model_and_weights = apputil.get_module_fn(dnnmod, "load_model_and_weights") model = load_model_and_weights(mode, cmdcfg, appcfg) modelinfocfg['log_dir'] = model.log_dir modelinfocfg['checkpoint_path'] = model.checkpoint_path if 'creator' in cmdcfg: modelinfocfg['creator'] = cmdcfg['creator'] log.info("modelinfocfg: {}".format(modelinfocfg)) fn_create_modelinfo = apputil.get_module_fn(dnnmod, "create_modelinfo") modelinfo = fn_create_modelinfo(modelinfocfg) create_modelinfo = args.create_modelinfo try: if not create_modelinfo: log.info("Training...") fn_train = apputil.get_module_fn(dnnmod, "train") fn_train(model, dataset_train, dataset_val, cmdcfg) log.info("Training Completed!!!") finally: ## save modelinfo ## popolate the relative weights_path of the last model from the training if any model is generated otherwise None logs_path = appcfg['PATHS']['AI_LOGS'] dnn = cmdcfg.dnnarch ##TODO list_of_files = glob.glob(os.path.join(model.log_dir,dnn+'*')) # * means all if need specific format then *.h5 latest_file = max(list_of_files, key=os.path.getctime) new_weights_path = re.sub('\{}'.format(logs_path+'/'), '', latest_file) modelinfo['weights_path'] = new_weights_path modelinfo_filepath = apputil.get_abs_path(appcfg, modelinfo, 'AI_MODEL_CFG_PATH') common.yaml_safe_dump(modelinfo_filepath, modelinfo) log.info("TRAIN:MODELINFO_FILEPATH: {}".format(modelinfo_filepath)) log.info("---x--x--x---") return modelinfo_filepath
def get_modelcfg(cfg, api_model_key=''): """ TODO - parameter checks as api_model_key is the client input - generic checks for SQLInjection - handle multiple concurrent connections """ log.info("----------------------------->") log.info("api_model_key: {}".format(api_model_key)) API_MODELINFO_TABEL = cfg['APP']['API_MODELINFO_TABEL'] query = {} modelcfg = None log_dir = 'api' if api_model_key: log_dir = os.path.join(log_dir, api_model_key) model_pkey = api_model_key.split('-') log.info("model_pkey: {}".format(model_pkey)) if len(model_pkey) > 0 and model_pkey[0]: query['org_name'] = model_pkey[0] if len(model_pkey) > 1 and model_pkey[1]: query['problem_id'] = model_pkey[1] ## TODO: release number change from integer to string if len(model_pkey) > 2 and model_pkey[2]: # query['rel_num'] = int(model_pkey[2]) query['rel_num'] = model_pkey[2] DBCFG = cfg['APP']['DBCFG'] OASISCFG = DBCFG['OASISCFG'] log.debug("OASISCFG: {}".format(OASISCFG)) mclient = MongoClient('mongodb://' + OASISCFG['host'] + ':' + str(OASISCFG['port'])) dbname = OASISCFG['dbname'] db = mclient[dbname] log.info("dbname, query: {}, {}".format(dbname, query)) modelinfo = db.get_collection(API_MODELINFO_TABEL) if len(query) == 3: modelcfg = modelinfo.find_one(query, {'_id': 0}) if modelcfg: modelcfg['log_dir'] = log_dir log_dir_path = apputil.get_abs_path(cfg, modelcfg, 'AI_LOGS') weights_path = apputil.get_abs_path(cfg, modelcfg, 'AI_WEIGHTS_PATH') modelcfg['log_dir_path'] = log_dir_path modelcfg['weights_path'] = weights_path else: modelcfg = list(modelinfo.find(query, {'_id': 0})) log.info("modelcfg: {}".format(modelcfg)) mclient.close() if type(modelcfg) != type([]): ## quick fix for name not present in config if modelcfg and modelcfg['config']: if 'name' in modelcfg: modelcfg['config']['NAME'] = modelcfg['name'] if 'num_classes' in modelcfg: modelcfg['config']['NUM_CLASSES'] = modelcfg['num_classes'] return modelcfg
def get_dataset_dicts(cfg, class_ids, id_map, imgs, anns, bbox_mode, config): # print(anns) ## => quick hack for running detectron2 with gaze data imgs_anns = list(zip(imgs, anns)) dataset_dicts = [] extra_annotation_keys = None ann_keys = ["iscrowd", "bbox", "keypoints", "category_id", "lbl_id" ] + (extra_annotation_keys or []) num_instances_without_valid_segmentation = 0 # log.debug("imgs_anns: {}".format(imgs_anns[:2])) for (img_dict, anno_dict_list) in imgs_anns: # log.debug("img_dict: {}".format(img_dict)) # log.debug("anno_dict_list: {}".format(len(anno_dict_list))) if config.MODEL.MASK_ON == True: filtered_anns = [] for key in anno_dict_list: if key["ant_type"] == "polygon": filtered_anns.append(key) # log.debug("img_dict: {}".format(img_dict)) # log.debug("anno_dict_list: {}".format(len(anno_dict_list))) # log.debug("filtered_anns: {}".format(len(filtered_anns))) # log.debug("filtered_anns: {}".format(filtered_anns)) # log.debug("anno_dict_list: {}".format(anno_dict_list)) if len(filtered_anns) != 0: image_path = apputil.get_abs_path( cfg, img_dict, 'AI_ANNON_DATA_HOME_LOCAL') ##image_root filepath = os.path.join(image_path, img_dict['filename']) record = {} record["file_name"] = filepath record["image_name"] = img_dict['filename'] # record["file_path"] = filepath record["height"] = img_dict["height"] record["width"] = img_dict["width"] image_id = record["image_id"] = img_dict["img_id"] ## coco: id objs = [] # for anno in anno_dict_list: for anno in filtered_anns: assert anno["img_id"] == image_id ## image_id obj = {key: anno[key] for key in ann_keys if key in anno} _bbox = obj['bbox'] coco_frmt_bbox = [ _bbox['xmin'], _bbox['ymin'], _bbox['width'], _bbox['height'] ] # log.debug("coco_frmt_bbox: {}".format(coco_frmt_bbox)) obj['bbox'] = coco_frmt_bbox anno = anno["shape_attributes"] # log.debug("anno: {}".format(anno)) px = anno["all_points_x"] py = anno["all_points_y"] poly = [(x + 0.5, y + 0.5) for x, y in zip(px, py)] poly = [p for x in poly for p in x] segm = [poly] segm = [ poly for poly in segm if len(poly) % 2 == 0 and len(poly) >= 6 ] obj["segmentation"] = segm obj["bbox_mode"] = bbox_mode obj["category_id"] = id_map[obj["lbl_id"]] ## category_id objs.append(obj) record["annotations"] = objs dataset_dicts.append(record) elif config.MODEL.MASK_ON == False: image_path = apputil.get_abs_path( cfg, img_dict, 'AI_ANNON_DATA_HOME_LOCAL') ##image_root filepath = os.path.join(image_path, img_dict['filename']) record = {} record["file_name"] = filepath record["image_name"] = img_dict['filename'] record["height"] = img_dict["height"] record["width"] = img_dict["width"] image_id = record["image_id"] = img_dict["img_id"] ## coco: id objs = [] for anno in anno_dict_list: assert anno["img_id"] == image_id ## image_id obj = {key: anno[key] for key in ann_keys if key in anno} _bbox = obj['bbox'] coco_frmt_bbox = [ _bbox['xmin'], _bbox['ymin'], _bbox['width'], _bbox['height'] ] # log.debug("coco_frmt_bbox: {}".format(coco_frmt_bbox)) obj['bbox'] = coco_frmt_bbox segm = None obj["bbox_mode"] = bbox_mode obj["category_id"] = id_map[obj["lbl_id"]] ## category_id # obj["segmentation"] = segm objs.append(obj) record["annotations"] = objs dataset_dicts.append(record) return dataset_dicts
def load_hmd(self, appcfg, dbcfg, datacfg, subset): """ - assume default file extension is json TODO: - csv file loading """ log.info("-------------------------------->") log.debug("datacfg: {}".format(datacfg)) class_ids = datacfg.class_ids if 'class_ids' in datacfg and datacfg[ 'class_ids'] else [] annon_type = datacfg.annon_type name = datacfg.name # class_map = datacfg.class_map if datacfg.class_map else None annon = self.annon = ANNON(dbcfg, datacfg, subset=subset) class_ids = annon.getCatIds(catIds=class_ids) image_ids = annon.getImgIds(catIds=class_ids) # log.debug("subset, image_ids: {}, {}".format(subset, image_ids)) log.debug("subset, class_ids: {}, {}".format(subset, class_ids)) ## Add images total_annotation = 0 total_maskarea = 0 total_bboxarea = 0 data_read_threshold = datacfg.data_read_threshold if 'data_read_threshold' in datacfg else -1 log.debug("data_read_threshold: {}".format(data_read_threshold)) images = annon.loadImgs(ids=image_ids) for i, img in enumerate(images): if data_read_threshold == i: log.info("Threshold reached: i: {}".format(i)) break # log.debug("img: {}".format(img)) image_path = apputil.get_abs_path(appcfg, img, 'AI_ANNON_DATA_HOME_LOCAL') filepath = os.path.join(image_path, img['filename']) # log.debug("filepath: {}".format(filepath)) ## TBD: width and height from a['file_attributes']['width'], a['file_attributes']['height'] if os.path.exists(filepath): try: ##log.info("Image file: {}".format(filepath)) if 'height' not in img or 'width' not in img: im = skimage.io.imread(filepath) height, width = im.shape[:2] else: height, width = img['height'], img['width'] # width = annon.imgs[i]["width"] # height = annon.imgs[i]["height"] img_id = img['img_id'] annotations = annon.loadAnns( annon.getAnnIds(imgIds=[img_id], catIds=class_ids)) total_annotation += len(annotations) self.add_image(name, image_id=name + '-' + str(img_id), path=filepath, width=width, height=height, annon_type=annon_type, annotations=annotations) except: log.info( "Error Reading file or adding annotation: {}".format( filepath)) log.error("Exception occurred", exc_info=True) else: log.info("file does not exists: {}".format(filepath)) total_img = len(image_ids) total_classes = len(class_ids) classinfo = annon.loadCats(ids=class_ids) for index, ci in enumerate(classinfo): class_idx = index + 1 class_source, class_lbl_id, class_name = ci['source'], ci[ 'lbl_id'], ci['name'] log.info( "Adding: class_source, class_lbl_id, class_name, class_dx: {}, {}, {}" .format(class_source, class_lbl_id, class_name, class_idx)) self.add_class(source=class_source, idx=class_idx, class_name=class_name, lbl_id=class_lbl_id, color=None) log.info("Total Images: {}".format(total_img)) log.info("Total Annotations: {}".format(total_annotation)) log.info("Total Classes without BG: {}".format(total_classes)) log.info("Total Classes including BG: {}".format(len(self.classinfo))) log.info("Classinfo: {}".format(self.classinfo)) log.info("-------") return total_img, total_annotation, total_classes, annon
def get_image_path(self, img): image_path = apputil.get_abs_path(self.appcfg, img, 'AI_ANNON_DATA_HOME_LOCAL') log.debug("image_path: {}".format(image_path)) return image_path
def evaluate(mode, cmdcfg, appcfg, modelcfg, dataset, datacfg, class_names, reportcfg, get_mask=True, auto_show=False): """API Execute the evaluation and generates the evaluation reports classification report with differet scores confusion matrix summary report Ref: https://github.com/matterport/Mask_RCNN/blob/master/samples/shapes/train_shapes.ipynb """ log.info("---------------------------->") dnncfg = get_dnncfg(cmdcfg.config) log_dir_path = apputil.get_abs_path(appcfg, cmdcfg, 'AI_LOGS') cmdcfg['log_dir_path'] = log_dir_path model = load_model_and_weights(mode, cmdcfg, appcfg) save_viz_and_json = reportcfg['save_viz_and_json'] evaluate_no_of_result = reportcfg['evaluate_no_of_result'] filepath = reportcfg['filepath'] evaluate_run_summary = reportcfg['evaluate_run_summary'] log.info("evaluate_no_of_result: {}".format(evaluate_no_of_result)) detection_on_dataset = [] ## TODO: put at right place iou_threshold_input = reportcfg['iou_threshold'] # iou_thresholds = None # iou_thresholds = iou_thresholds or np.arange(0.5, 1.0, 0.05) iou_thresholds = np.arange(0.5, 1.0, 0.05) size = len(iou_thresholds) _mAPs, _precisions, _recalls = size * [None], size * [None], size * [None] gt_total_annotation = 0 pred_total_annotation = 0 remaining_num_images = -1 image_ids = dataset.image_ids num_images = len(image_ids) pred_match_total_annotation = [] colors = viz.random_colors(len(class_names)) log.info("len(colors), colors: {},{}".format(len(colors), colors)) cc = dict(zip(class_names, colors)) ## for some reasons if gets an error in iterating through dataset, all the hardwork is lost, ## therefore, save the data to disk in finally clause via_jsonres = {} imagelist = [] class_ids_dataset = dataset.class_ids class_names_model = modelcfg['classes'] class_ids_model = np.arange(len(class_names_model)) log.debug("class_names dataset: {}".format(class_names)) log.debug("class_names_model: {}".format(class_names_model)) log.debug("class_ids_dataset: {}".format(class_ids_dataset)) log.debug("class_ids_model: {}".format(class_ids_model)) ## class_names consists of BG at index 0 ## class_names_model consists of BG at index 0 class_ids_map = False class_names_common = class_names.copy() if class_names != modelcfg['classes']: class_ids_map = True class_names_common, class_ids_common_dataset, class_ids_common_model, gt_to_model_map = class_ids_of_model_to_dataset( np.array(class_names), class_ids_dataset, np.array(class_names_model), class_ids_model) log.info("class_names_common: {}".format(class_names_common)) log.info( "class_ids_common_dataset: {}".format(class_ids_common_dataset)) log.info("class_ids_common_model: {}".format(class_ids_common_model)) ## TODO: Exception handling: if class_ids_of_model_to_dataset length is 1 then only BG is common class_names = np.array(class_names) T0 = time.time() try: for i, image_id in enumerate(image_ids): log.debug("-------") filepath_image_in = dataset.image_reference(image_id) image_filename = filepath_image_in.split(os.path.sep)[-1] image_name_without_ext = image_filename.split('.')[0] imagelist.append(filepath_image_in) log.debug("Running on {}".format(image_filename)) if evaluate_no_of_result == i: log.info("evaluate_no_of_result reached: i: {}\n".format(i)) break remaining_num_images = evaluate_no_of_result if evaluate_no_of_result and evaluate_no_of_result > 0 else num_images remaining_num_images = remaining_num_images - i - 1 log.info( "To be evaluated remaining_num_images:...................{}". format(remaining_num_images)) t0 = time.time() # im, gt_class_ids, gt_boxes, gt_masks, gt_active_class_ids = load_image_gt_without_resizing(dataset, datacfg, dnncfg, image_id) im, gt_image_meta, gt_class_ids, gt_boxes, gt_masks = modellib.load_image_gt( dataset, datacfg, dnncfg, image_id, use_mini_mask=False) molded_images = np.expand_dims(modellib.mold_image(im, dnncfg), 0) if class_ids_map: log.debug("Before gt_class_id_map...:") log.debug( "len(gt_class_ids): {}\nTotal Unique classes: len(set(gt_class_ids)): {}\ngt_class_ids: {}" .format(len(gt_class_ids), len(set(gt_class_ids)), gt_class_ids)) for _i, gt_id in enumerate(gt_class_ids): gt_class_ids[_i] = gt_to_model_map[gt_id] log.debug("After gt_class_id_map...:") log.debug( "len(gt_class_ids): {}\nTotal Unique classes: len(set(gt_class_ids)): {}\ngt_class_ids: {}" .format(len(gt_class_ids), len(set(gt_class_ids)), gt_class_ids)) t1 = time.time() time_taken_imread = (t1 - t0) log.debug('Total time taken in time_taken_imread: %f seconds' % (time_taken_imread)) gt_total_annotation += len(gt_class_ids) log.info("\nGround Truth-------->") log.info("i,image_id:{},{}".format(i, image_id)) log.debug( "len(gt_boxes), gt_boxes.shape, type(gt_boxes): {},{},{}". format(len(gt_boxes), gt_boxes.shape, type(gt_boxes))) log.debug( "len(gt_masks), gt_masks.shape, type(gt_masks): {},{},{}". format(len(gt_masks), gt_masks.shape, type(gt_masks))) log.debug("gt_boxes: {}".format(gt_boxes)) log.debug("gt_masks: {}".format(gt_masks)) log.info("--------") # Detect objects ##--------------------------------------------- t2 = time.time() r = detect(model, im=im, verbose=1)[0] ## N - total number of predictions ## (N, 4) pred_boxes = r['rois'] ## (H, W, N) pred_masks = r['masks'] ## N pred_class_ids = r['class_ids'] ## N pred_scores = r['scores'] log.debug("Prediction on Groud Truth-------->") log.debug('len(r): {}'.format(len(r))) log.debug("len(gt_class_ids), gt_class_ids: {},{}".format( len(gt_class_ids), gt_class_ids)) log.debug( "len(pred_class_ids), pred_class_ids, type(pred_class_ids): {},{},{}" .format(len(pred_class_ids), pred_class_ids, type(pred_class_ids))) log.debug("len(pred_scores), pred_scores: {},{}".format( len(pred_scores), pred_scores)) log.debug( "len(pred_boxes), pred_boxes.shape, type(pred_boxes): {},{},{}" .format(len(pred_boxes), pred_boxes.shape, type(pred_boxes))) log.debug( "len(pred_masks), pred_masks.shape, type(pred_masks): {},{},{}" .format(len(pred_masks), pred_masks.shape, type(pred_masks))) log.debug("--------") if class_ids_map: pred_class_ids_common_model_indices = np.where( np.in1d(pred_class_ids, class_ids_common_model))[0] class_ids_common_model_pred_class_ids_indices = np.where( np.in1d(class_ids_common_model, pred_class_ids))[0] # pred_class_ids_common_dataset_indices = np.where(np.in1d(class_ids_common_dataset, pred_class_ids_common_model_indices))[0] pred_boxes = pred_boxes[pred_class_ids_common_model_indices] pred_masks = pred_masks[..., pred_class_ids_common_model_indices] pred_class_ids = pred_class_ids[ pred_class_ids_common_model_indices] pred_scores = pred_scores[pred_class_ids_common_model_indices] log.debug( "Prediction on Groud Truth: After Model class filtering-------->" ) log.debug('len(r): {}'.format(len(r))) log.debug( "len(pred_class_ids_common_model_indices), pred_class_ids_common_model_indices: {},{}" .format(len(pred_class_ids_common_model_indices), pred_class_ids_common_model_indices)) log.debug( "len(class_ids_common_model_pred_class_ids_indices), class_ids_common_model_pred_class_ids_indices: {},{}" .format(len(class_ids_common_model_pred_class_ids_indices), class_ids_common_model_pred_class_ids_indices)) log.debug( "len(class_ids_common_dataset[class_ids_common_model_pred_class_ids_indices]), class_ids_common_dataset[class_ids_common_model_pred_class_ids_indices]: {},{}" .format( len(class_ids_common_dataset[ class_ids_common_model_pred_class_ids_indices]), class_ids_common_dataset[ class_ids_common_model_pred_class_ids_indices])) log.debug("len(gt_class_ids), gt_class_ids: {},{}".format( len(gt_class_ids), gt_class_ids)) log.debug( "len(pred_class_ids), pred_class_ids, type(pred_class_ids): {},{},{}" .format(len(pred_class_ids), pred_class_ids, type(pred_class_ids))) log.debug("len(pred_scores), pred_scores: {},{}".format( len(pred_scores), pred_scores)) log.debug( "len(pred_boxes), pred_boxes.shape, type(pred_boxes): {},{},{}" .format(len(pred_boxes), pred_boxes.shape, type(pred_boxes))) log.debug( "len(pred_masks), pred_masks.shape, type(pred_masks): {},{},{}" .format(len(pred_masks), pred_masks.shape, type(pred_masks))) log.debug("--------") pred_total_annotation += len(pred_class_ids) t3 = time.time() time_taken_in_detect = (t3 - t2) log.info('TIME_TAKEN_IN_DETECT:%f seconds' % (time_taken_in_detect)) t4 = time.time() ## TODO: gt via_json resp and pred via jsn res separate data strucure ## TODO: mAP calculation for per class and over enitre dataset ## TODO: this does not help; need to flatten the all ground truts for eniter dataset. ## np.zeros(len(gt_for_all_images)), ideally same number of predictions sohuld be there ## Insort; have to re-write the compute_matches function for entire dataset evaluate_run_summary['images'].append(image_filename) # evaluate_run_summary['gt_boxes'].append(gt_boxes) evaluate_run_summary['gt_class_ids'].append(list(gt_class_ids)) # evaluate_run_summary['gt_masks'].append(gt_masks) # evaluate_run_summary['pred_boxes'].append(pred_boxes) evaluate_run_summary['pred_class_ids'].append(list(pred_class_ids)) evaluate_run_summary['pred_scores'].append(list(pred_scores)) # evaluate_run_summary['pred_masks'].append(pred_masks) evaluate_run_summary['gt_total_annotation_per_image'].append( len(gt_class_ids)) evaluate_run_summary['pred_total_annotation_per_image'].append( len(pred_class_ids)) detection_on_dataset_item = defaultdict(list) __pred_match_total_annotation = np.zeros([len(iou_thresholds)], dtype=int) for count, iou_threshold in enumerate(iou_thresholds): log.info("count, iou_threshold: {}, {}".format( count, iou_threshold)) ## Compute Average Precision at a set IoU threshold ## -------------------------------------------- AP_per_image, precisions, recalls, gt_match, pred_match, overlaps, pred_match_scores, pred_match_class_ids = utils.compute_ap( gt_boxes, gt_class_ids, gt_masks, pred_boxes, pred_class_ids, pred_scores, pred_masks, iou_threshold=iou_threshold) __pred_match_total_annotation[count] += len( pred_match_class_ids) ## compute and returns f1 score metric ## -------------------------------------------- f1_per_image = utils.compute_f1score(precisions, recalls) ## Compute the recall at the given IoU threshold. It's an indication ## of how many GT boxes were found by the given prediction boxes. ## -------------------------------------------- recall_bbox, positive_ids_bbox = utils.compute_recall( gt_boxes, pred_boxes, iou_threshold) # log.info("len(precisions),precisions: {},{}".format(len(precisions), precisions)) # log.info("len(recalls),recalls: {},{}".format(len(recalls), recalls)) # log.info("len(pred_match_class_ids),pred_match_class_ids: {},{}".format(len(pred_match_class_ids), pred_match_class_ids)) # log.info("AP_per_image: {}".format(AP_per_image)) # log.info("len(overlaps),overlaps: {},{}".format(len(overlaps), overlaps)) pred_match_class_names = class_names[np.where( np.in1d(dataset.class_ids, pred_match_class_ids))[0]] detection_on_dataset_item['ap_per_image'].append(AP_per_image) detection_on_dataset_item['f1_per_image'].append(f1_per_image) detection_on_dataset_item['precisions'].append(precisions) detection_on_dataset_item['recalls'].append(list(recalls)) detection_on_dataset_item['recall_bbox'].append(recall_bbox) detection_on_dataset_item['positive_ids_bbox'].append( list(positive_ids_bbox)) detection_on_dataset_item['gt_match'].append(list(gt_match)) detection_on_dataset_item['pred_match'].append( list(pred_match)) detection_on_dataset_item['pred_match_scores'].append( list(pred_match_scores)) detection_on_dataset_item['overlaps_mask_iou'].append( list(overlaps)) detection_on_dataset_item['pred_match_class_ids'].append( list(pred_match_class_ids)) detection_on_dataset_item['pred_match_class_names'].append( list(pred_match_class_names)) detection_on_dataset_item[ 'pred_match_total_annotation'].append( len(pred_match_class_ids)) detection_on_dataset_item['iou_thresholds'].append( iou_threshold) if save_viz_and_json and iou_threshold == float( iou_threshold_input): fext = ".png" file_name = image_filename + fext log.info("@IoU, SAVED_FILE_NAME: {},{}".format( iou_threshold, file_name)) jsonres = viz.get_display_instances(im, pred_boxes, pred_masks, pred_class_ids, class_names_model, pred_scores, colors=cc, show_bbox=True, show_mask=True, get_mask=get_mask, filepath=filepath, filename=file_name, auto_show=auto_show) ## Convert Json response to VIA Json response ##--------------------------------------------- # size_image = 0 size_image = os.path.getsize(filepath_image_in) jsonres["filename"] = image_filename jsonres["size"] = size_image jsonres['file_attributes']['iou'] = iou_threshold ## TODO: if want to store in mongoDB, '.' (dot) should not be present in the key in the json data ## but, to visualize the results in VIA tool, this (dot) and size is expected # via_jsonres[image_filename.replace('.','-')+str(size_image)] = json.loads(common.numpy_to_json(jsonres)) via_jsonres[image_filename + str(size_image)] = json.loads( common.numpy_to_json(jsonres)) # log.debug("jsonres: {}".format(jsonres)) # log.debug("via_jsonres[image_filename+str(size_image)]: {}".format(via_jsonres[image_filename+str(size_image)])) detection_on_dataset.append(detection_on_dataset_item) pred_match_total_annotation.append(__pred_match_total_annotation) mean_ap_of_per_image, mean_f1_of_per_image, mean_recall_bbox_of_per_image, total_pred_match_total_annotation_of_per_image = compute_ap_of_per_image_over_dataset( detection_on_dataset) ## TODO: use detection_on_dataset for evaluation over entire dataset and per class ## fix the TODO items within compute_ap_dataset # _mAPs, _precisions, _recalls = compute_ap_dataset(detection_on_dataset, iou_thresholds) log.info("---x-x---") except Exception as e: log.info("Exception: {}".format(e)) log.error("Fatal error in main loop".format(e), exc_info=True) # log.error('Error occurred ' + str(e)) raise finally: log.info("--------X--------X--------X--------") T1 = time.time() evaluate_run_summary['total_execution_time'] = T1 - T0 evaluate_run_summary['mAP'] = _mAPs evaluate_run_summary['precision'] = _precisions evaluate_run_summary['recall'] = _recalls evaluate_run_summary['class_names_dataset'] = class_names evaluate_run_summary['class_ids_dataset'] = dataset.class_ids evaluate_run_summary['class_names_model'] = class_names_model evaluate_run_summary['class_ids_model'] = class_ids_model evaluate_run_summary['class_names_common'] = class_names_common evaluate_run_summary['mean_ap_of_per_image'] = mean_ap_of_per_image evaluate_run_summary['mean_f1_of_per_image'] = mean_f1_of_per_image evaluate_run_summary[ 'mean_recall_bbox_of_per_image'] = mean_recall_bbox_of_per_image evaluate_run_summary[ 'total_pred_match_total_annotation_of_per_image'] = total_pred_match_total_annotation_of_per_image evaluate_run_summary[ 'pred_match_total_annotation'] = pred_match_total_annotation evaluate_run_summary['gt_total_annotation'] = gt_total_annotation evaluate_run_summary['pred_total_annotation'] = pred_total_annotation evaluate_run_summary['iou_thresholds'] = iou_thresholds evaluate_run_summary['execution_end_time'] = "{:%d%m%y_%H%M%S}".format( datetime.datetime.now()) # evaluate_run_summary['detection_min_confidence'] = dnncfg.config['DETECTION_MIN_CONFIDENCE'] evaluate_run_summary['remaining_num_images'] = remaining_num_images log.debug("evaluate_run_summary: {}".format(evaluate_run_summary)) classification_reportfile_path = reportcfg[ 'classification_reportfile'] + '-per_dataset.json' with open(classification_reportfile_path, 'w') as fw: fw.write(common.numpy_to_json(detection_on_dataset)) evaluate_run_summary_reportfile_path = reportcfg[ 'evaluate_run_summary_reportfile'] + '.json' with open(evaluate_run_summary_reportfile_path, 'w') as fw: fw.write(common.numpy_to_json(evaluate_run_summary)) ## Save the image list for loading the response in VIA along with the images imagelist_filepath = os.path.join(filepath, 'annotations', "imagelist.csv") pd.DataFrame(imagelist).to_csv(imagelist_filepath) ## https://stackoverflow.com/questions/12309269/how-do-i-write-json-data-to-a-file via_jsonres_filepath = os.path.join(filepath, 'annotations', "annotations.json") if via_jsonres and len(via_jsonres) > 0: with open(via_jsonres_filepath, 'w') as fw: fw.write(json.dumps(via_jsonres)) print("EVALUATE_REPORT:ANNOTATION:{}".format(via_jsonres_filepath)) print("EVALUATE_REPORT:IMAGELIST:{}".format(imagelist_filepath)) print( "EVALUATE_REPORT:METRIC:{}".format(classification_reportfile_path)) print("EVALUATE_REPORT:SUMMARY:{}".format( evaluate_run_summary_reportfile_path)) log.info("--------") return evaluate_run_summary
def load_hmdcoco(cfg, datacfg, img_ids, bbox_mode): class_ids = datacfg.class_ids if 'class_ids' in datacfg and datacfg[ 'class_ids'] else [] class_ids = annon.getCatIds(catIds=class_ids) ## cat_ids classinfo = annon.loadCats(class_ids) ## cats # print("class_ids: {}".format(class_ids)) # print("classinfo: {}".format(classinfo)) # print(img_ids) imgs = annon.loadImgs(img_ids) anns = [annon.imgToAnns[img_id] for img_id in img_ids] # print(anns) ## => quick hack for running detectron2 with gaze data ## TODO: Convert to COCO -> if done in pre-processing, this step not required here imgs_anns = list(zip(imgs, anns)) dataset_dicts = [] extra_annotation_keys = None ## TODO: iscrowd is available in attributes as something like group ann_keys = ["iscrowd", "bbox", "keypoints", "category_id", "lbl_id" ] + (extra_annotation_keys or []) num_instances_without_valid_segmentation = 0 id_map = {v: i for i, v in enumerate(class_ids)} for (img_dict, anno_dict_list) in imgs_anns: image_path = apputil.get_abs_path( cfg, img_dict, 'AI_ANNON_DATA_HOME_LOCAL') ##image_root filepath = os.path.join(image_path, img_dict['filename']) record = {} record["file_name"] = filepath record["height"] = img_dict["height"] record["width"] = img_dict["width"] image_id = record["image_id"] = img_dict["img_id"] ## coco: id objs = [] for anno in anno_dict_list: assert anno["img_id"] == image_id ## image_id obj = {key: anno[key] for key in ann_keys if key in anno} ##TODO: convert bbbox to coco format _bbox = obj['bbox'] ##TODO: verify what is BoxMode.XYWH_ABS coco_frmt_bbox = [ _bbox['xmin'], _bbox['ymin'], _bbox['width'], _bbox['height'] ] #print("coco_frmt_bbox: {}".format(coco_frmt_bbox)) obj['bbox'] = coco_frmt_bbox ## TODO: get polygon from shape_attributes and conver to coco format #segm = anno.get("segmentation", None) segm = None if segm: # either list[list[float]] or dict(RLE) if not isinstance(segm, dict): # filter out invalid polygons (< 3 points) segm = [ poly for poly in segm if len(poly) % 2 == 0 and len(poly) >= 6 ] if len(segm) == 0: num_instances_without_valid_segmentation += 1 continue # ignore this instance obj["segmentation"] = segm obj["bbox_mode"] = bbox_mode if id_map: obj["category_id"] = id_map[obj["lbl_id"]] ## category_id objs.append(obj) record["annotations"] = objs dataset_dicts.append(record) return dataset_dicts