def upload_model(self, extra): model_desc = self.api.simple_request('GenerateNewModelId', api_proto.ModelDescription, api_proto.Empty()) local_extra = { 'model_id': model_desc.id, 'model_hash': model_desc.hash } self.logger.trace('NEW_MODEL_ID', extra=local_extra) cur_checkpoint_dir = os.path.join(self.dir_results, extra['subdir']) storage = self.data_mgr.storage.nns if storage.check_storage_object(model_desc.hash): self.logger.critical('CHECKPOINT_ALREADY_EXISTS', extra=local_extra) raise RuntimeError() storage.write_object(cur_checkpoint_dir, model_desc.hash) model_config_path = osp.join(cur_checkpoint_dir, 'config.json') if osp.isfile(model_config_path): local_extra['model_config'] = sly.json_load(model_config_path) self.logger.info('MODEL_SAVED', extra=local_extra) # don't report TaskStep.UPLOAD because there should be multiple uploads res = { 'model_id': model_desc.id, 'model_hash': model_desc.hash, 'model_config': local_extra.get('model_config', {}) } return res
def load_ann(ann_fpath, classes_mapping, project_meta): ann_packed = sly.json_load(ann_fpath) ann = sly.Annotation.from_packed(ann_packed, project_meta) # ann.normalize_figures() # @TODO: enaaaable! (w, h) = ann.image_size_wh gt_boxes, classes_text, classes = [], [], [] for fig in ann['objects']: gt = np.zeros((h, w), dtype=np.uint8) # default bkg gt_idx = classes_mapping.get(fig.class_title, None) if gt_idx is None: raise RuntimeError( 'Missing class mapping (title to index). Class {}.'.format( fig.class_title)) fig.draw(gt, 1) if np.sum(gt) > 0: xmin, ymin, xmax, ymax = get_bbox(gt) gt_boxes.append([ymin / h, xmin / w, ymax / h, xmax / w]) classes_text.append( fig.class_title.encode('utf8') ) # List of string class name of bounding box (1 per box) classes.append( gt_idx) # List of integer class id of bounding box (1 per box) num_boxes = len( gt_boxes) # ops.convert_to_tensor(len(gt_boxes), dtype=dtypes.int32) # gt_boxes = ops.convert_to_tensor(gt_boxes, dtype=dtypes.float32) # classes = ops.convert_to_tensor(classes, dtype=dtypes.int64) return np.array(gt_boxes).astype('float32'), np.array(classes).astype( 'int64'), np.array([num_boxes]).astype('int32')[0]
def serve(): settings = { 'device_id': 0, 'cache_limit': 500, 'connection': { 'server_address': None, 'token': None, 'task_id': None, }, } new_settings = sly.json_load(sly.TaskPaths(determine_in_project=False).settings_path) logger.info('Input settings', extra={'settings': new_settings}) sly.update_recursively(settings, new_settings) logger.info('Full settings', extra={'settings': settings}) def model_creator(): res = UnetV2FastApplier(settings={ 'device_id': settings['device_id'] }) return res image_cache = SimpleCache(settings['cache_limit']) serv_instance = AgentRPCServicer(logger=logger, model_creator=model_creator, apply_cback=single_img_pipeline, conn_settings=settings['connection'], cache=image_cache) serv_instance.run_inf_loop()
def _construct_project_items_to_upload(cls, project_fs, project_id, ds_names_to_ids): project_items = list(project_fs) for it in project_items: ann = sly.json_load(it.ann_path) img_w, img_h = sly.Annotation.get_image_size_wh(ann) # get image hash & ext if it.img_path and sly.file_exists(it.img_path): it.ia_data['image_hash'] = sly.get_image_hash(it.img_path) # image_ext is already determined in project_fs img_sizeb = sly.get_file_size(it.img_path) else: for spec_field in ann_special_fields(): if spec_field not in ann: raise RuntimeError('Missing spec field in annotation: {}'.format(spec_field)) it.ia_data['image_hash'] = ann['img_hash'] it.ia_data['image_ext'] = ann['img_ext'] img_sizeb = ann['img_size_bytes'] # construct image info img_meta_str = create_img_meta_str(img_sizeb, width=img_w, height=img_h) img_proto_info = api_proto.Image(hash=it.ia_data['image_hash'], title=it.image_name, ext=it.ia_data['image_ext'], dataset_id=ds_names_to_ids[it.ds_name], project_id=project_id, meta=img_meta_str) it.ia_data['img_proto_info'] = img_proto_info return project_items
def upload_result_project(self, _): self.report_step_done(TaskStep.MAIN) self._read_verif_status() graph_pr_name = sly.get_res_project_name(self.info['graph']) no_image_files = not self.download_images if self.is_archive is False: pr_id = self.data_mgr.upload_project(self.dir_results, graph_pr_name, no_image_files=no_image_files) self.logger.info('PROJECT_CREATED', extra={ 'event_type': EventType.PROJECT_CREATED, 'project_id': pr_id }) else: # remove excess fields from json root_path, project_name = sly.ProjectFS.split_dir_project( self.dir_results) project_fs = sly.ProjectFS.from_disk(root_path, project_name, by_annotations=True) for item in project_fs: ann_path = item.ann_path ann = sly.json_load(ann_path) for exc_field in ann_special_fields(): ann.pop(exc_field, None) sly.json_dump(ann, ann_path) self.data_mgr.upload_archive(self.dir_results, graph_pr_name) self.report_step_done(TaskStep.UPLOAD) return {}
def run_inference(self): out_project_fs = copy(self.in_project_fs) out_project_fs.root_path = self.helper.paths.results_dir out_project_fs.make_dirs() inf_feeder = sly.InferenceFeederFactory.create(self.config, self.helper.in_project_meta, self.train_classes) out_pr_meta = inf_feeder.out_meta out_pr_meta.to_dir(out_project_fs.project_path) ia_cnt = out_project_fs.pr_structure.image_cnt progress = sly.progress_counter_inference(cnt_imgs=ia_cnt) for sample in self.in_project_fs: logger.info('Will process image', extra={'dataset_name': sample.ds_name, 'image_name': sample.image_name}) ann_packed = sly.json_load(sample.ann_path) ann = sly.Annotation.from_packed(ann_packed, self.helper.in_project_meta) img = cv2.imread(sample.img_path)[:, :, ::-1] res_ann = inf_feeder.feed(img, ann, self._infer_on_img) out_ann_fpath = out_project_fs.ann_path(sample.ds_name, sample.image_name) res_ann_packed = res_ann.pack() sly.json_dump(res_ann_packed, out_ann_fpath) if self.debug_copy_images: out_img_fpath = out_project_fs.img_path(sample.ds_name, sample.image_name) sly.ensure_base_path(out_img_fpath) shutil.copy(sample.img_path, out_img_fpath) progress.iter_done_report() sly.report_inference_finished()
def main(): sly.task_verification(check_in_graph) logger.info('DTL started') helper = sly.DtlHelper() net = Net(helper.graph, helper.in_project_metas, helper.paths.results_dir) helper.save_res_meta(net.get_result_project_meta()) # is_archive = net.is_archive() results_counter = 0 for pr_name, pr_dir in helper.in_project_dirs.items(): root_path, project_name = sly.ProjectFS.split_dir_project(pr_dir) project_fs = sly.ProjectFS.from_disk(root_path, project_name, by_annotations=True) progress = sly.progress_counter_dtl(pr_name, project_fs.image_cnt) for sample in project_fs: try: img_desc = sly.ImageDescriptor(sample) ann = sly.json_load(sample.ann_path) data_el = (img_desc, ann) export_output_generator = net.start(data_el) for res_export in export_output_generator: logger.trace("image processed", extra={'img_name': res_export[0][0].get_img_name()}) results_counter += 1 except Exception: ex = { 'project_name': sample.project_name, 'ds_name': sample.ds_name, 'image_name': sample.image_name } logger.warn('Image was skipped because some error occured', exc_info=True, extra=ex) progress.iter_done_report() logger.info('DTL finished', extra={'event_type': EventType.DTL_APPLIED, 'new_proj_size': results_counter})
def __init__(self): task_paths = sly.DtlPaths() self.in_dir = task_paths.data_dir self.out_dir = task_paths.results_dir self.settings = sly.json_load(task_paths.settings_path) self.classes = set() self.tags = set()
def __init__(self): task_paths = sly.DtlPaths() self.in_dir = task_paths.data_dir self.out_dir = task_paths.results_dir self.settings = sly.json_load(task_paths.settings_path) self.colors_file = osp.join(self.in_dir, 'colors.json') self._read_colors() self._read_datasets()
def _read_colors(self): if osp.isfile(self.colors_file): logger.info( 'Will try to read segmentation colors from provided file.') color_info = sly.json_load(self.colors_file) else: logger.info('Will use default Mapillary color mapping.') default_fpath = osp.join(osp.dirname(__file__), 'colors.json') color_info = sly.json_load(default_fpath) labels = color_info['labels'] self.instance_classes = [ el['readable'] for el in labels if el['instances'] ] self.cls2col = {el['readable']: tuple(el['color']) for el in labels} logger.info('Determined {} class(es).'.format(len(self.cls2col)), extra={'classes': list(self.cls2col.keys())}) self.cls_names = [el['readable'] for el in labels] # ! from order of labels
def __init__(self): task_paths = sly.DtlPaths() self.in_dir = task_paths.data_dir self.out_dir = task_paths.results_dir self.settings = sly.json_load(task_paths.settings_path) if len(task_paths.project_dirs) > 1: raise RuntimeError('The project should consist of only one folder.') self.dataset_dir = task_paths.project_dirs[0] self._define_classes()
def __init__(self): task_paths = sly.DtlPaths() self.in_dir = task_paths.data_dir self.out_dir = task_paths.results_dir self.settings = sly.json_load(task_paths.settings_path) if len(task_paths.project_dirs) != 1: raise RuntimeError( 'Invalid data format. Input folder should contain only "images_and_annotations" dir' ) self.data_dir = join(self.in_dir, 'images_and_annotations')
def __init__(self): task_paths = sly.DtlPaths() self.in_dir = task_paths.data_dir self.out_dir = task_paths.results_dir self.settings = sly.json_load(task_paths.settings_path) if not os.path.exists(join(self.in_dir, 'img')) or not os.path.exists( (join(self.in_dir, 'ann'))): raise RuntimeError( 'Invalid data format. Input folder should contain "img" and "ann" dirs' ) self.img_dir = join(self.in_dir, 'img') self.ann_dir = join(self.in_dir, 'ann')
def load_ann(ann_path, labels_mapping, in_pr_meta): ann_packed = sly.json_load(ann_path) ann = sly.Annotation.from_packed(ann_packed, in_pr_meta) # ann.normalize_figures() # @TODO: enaaaable! w, h = ann.image_size_wh gt = np.zeros((h, w), dtype=np.uint8) # default bkg = 0 for fig in ann['objects']: gt_color = labels_mapping.get(fig.class_title, None) if gt_color is None: err_str = 'Missing class mapping (title to index). Class {}.'.format(fig.class_title) print(err_str) # exception info may be suppressed raise RuntimeError(err_str) fig.draw(gt, gt_color) gt = gt.astype(np.float32) return gt
def ann2label(ann_fpath, class_mapping, project_meta, out_size_wh): ann_packed = sly.json_load(ann_fpath) ann = sly.Annotation.from_packed(ann_packed, project_meta) (w, h) = ann.image_size_wh # ann.normalize_figures() # @TODO: enaaaable! # will not resize figures: resize gt instead gt = np.zeros((h, w), dtype=np.uint8) # default bkg for fig in ann['objects']: gt_color = class_mapping.get(fig.class_title, None) if gt_color is None: raise RuntimeError( 'Missing class mapping (title to index). Class {}.'.format( fig.class_title)) fig.draw(gt, gt_color) gt = sly.resize_inter_nearest(gt, out_size_wh).astype(np.float32) return gt
def _load_citysc_annotation(self, ann_path): json_data = sly.json_load(ann_path) imsize_wh = json_data['imgWidth'], json_data['imgHeight'] figures = [] for obj in json_data['objects']: cls = obj['label'] if cls == 'out of roi': polygon = obj['polygon'][:5] interiors = [obj['polygon'][5:]] else: polygon = obj['polygon'] interiors = [] self.classes.add(cls) to_add = sly.FigurePolygon.from_np_points(cls, imsize_wh, polygon, interiors) figures.extend(to_add) ann = sly.Annotation.new_with_objects(imsize_wh, figures) return ann
def load_ann(ann_fpath, classes_mapping, project_meta): ann_packed = sly.json_load(ann_fpath) ann = sly.Annotation.from_packed(ann_packed, project_meta) (w, h) = ann.image_size_wh gt_boxes, classes_text, classes = [], [], [] for fig in ann['objects']: gt_idx = classes_mapping.get(fig.class_title, None) if gt_idx is None: raise RuntimeError( 'Missing class mapping (title to index). Class {}.'.format( fig.class_title)) rect = fig.get_bbox() x = (rect.left + rect.right) / (2 * w) y = (rect.bottom + rect.top) / (2 * h) r_width = (rect.right - rect.left) / w r_height = (rect.bottom - rect.top) / h gt_boxes.extend([gt_idx, x, y, r_width, r_height]) num_boxes = len(ann['objects']) return num_boxes, gt_boxes
def _get_sample_impl(self, img_fpath, ann_fpath): img = cv2.imread(img_fpath)[:, :, ::-1] # raises exc if img is None h, w = img.shape[:2] img = cv2.resize(img, self.out_size_wh) ann_packed = sly.json_load(ann_fpath) ann = sly.Annotation.from_packed(ann_packed, self.project_meta) # ann.normalize_figures() # @TODO: enaaaable! # will not resize figures: resize gt instead gt = np.ones((h, w), dtype=np.uint8) * self.bkg_color # default bkg for fig in ann['objects']: gt_color = self.class_mapping.get(fig.class_title, None) if gt_color is None: raise RuntimeError( 'Missing class mapping (title to index). Class {}.'.format( fig.class_title)) fig.draw(gt, gt_color) gt = sly.resize_inter_nearest(gt, self.out_size_wh).astype(np.int64) gt = np.expand_dims(gt, 0) return input_image_normalizer(img), gt
def main(): # Please note that auxiliary methods from sly (supervisely_lib) use supervisely_lib.logger to format output. # So don't replace formatters or handlers of the logger. # One may use other loggers or simple prints for other output, but it's recommended to use supervisely_lib.logger. logger.info('Hello ML world') print('Glad to see u') # TaskHelperTrain contains almost all needed to run training as Supervisely task, # including task settings and paths to data and models. task_helper = sly.TaskHelperTrain() # All settings and parameters are passed to task in json file. # Content of the file is entirely dependent on model implementation. training_settings = task_helper.task_settings logger.info('Task settings are read', extra={'task_settings': training_settings}) cnt_epochs = training_settings[ "epochs"] # in the fake model we want cnt of epochs cnt_iters_per_epoch = training_settings["iters_per_epoch"] # Let's imitate model weights loading. # Task acquires directory with input model weights (e.g. to continue training or to initialize some parameters). # Content of the directory is entirely dependent on model implementation. model_dir = task_helper.paths.model_dir if task_helper.model_dir_is_empty(): model = create_fake_model() logger.info('Model created from scratch') else: model = load_fake_model(model_dir) logger.info('Init model weights are loaded', extra={'model_dir': model_dir}) # We will save weights of trained model (checkpoints) into directories provided by the checkpoints_saver. checkpoints_saver = task_helper.checkpoints_saver logger.info('Ready to save checkpoints', extra={'results_dir': task_helper.paths.results_dir}) # Let's imitate reading input project with training data. # Of course in real implementations it is usually wrapped in some data loaders which are executed in parallel. project_meta = task_helper.in_project_meta # Project meta contains list of project classes. project_dir = task_helper.paths.project_dir project_fs = sly.ProjectFS.from_disk_dir_project(project_dir) # ProjectFS enlists all samples (image/annotation pairs) in input project. for item_descr in project_fs: logger.info('Processing input sample', extra={ 'dataset': item_descr.ds_name, 'image_name': item_descr.image_name }) # Open some image... img = cv2.imread(item_descr.img_path) logger.info('Read image from input project', extra={ 'width': img.shape[1], 'height': img.shape[0] }) # And read corresponding annotation... ann_packed = sly.json_load(item_descr.ann_path) ann = sly.Annotation.from_packed(ann_packed, project_meta) logger.info('Read annotation from input project', extra={ 'object_cnt': len(ann['objects']), 'tags': ann['tags'] }) # We are to report progress of task over sly.ProgressCounter if we want to observe the progress in web panel. # In fact one task may report progress for some sequential (not nested) subtasks, # but here we will report training progress only. progress = sly.progress_counter_train(cnt_epochs, cnt_iters_per_epoch) epoch_flt = 0 for epoch in range(cnt_epochs): logger.info("Epoch started", extra={'epoch': epoch}) for train_iter in range(cnt_iters_per_epoch): logger.info('Some forward-backward pass...') time.sleep(1) progress.iter_done_report( ) # call it after every iteration to report progress epoch_flt = sly.epoch_float(epoch, train_iter + 1, cnt_iters_per_epoch) # And we are to report some metrics if we want to observe those amazing charts in web panel. # Regrettably, only the fixed metric types may be displayed now: 'loss', 'accuracy' and 'dice'. metric_values_train = { 'loss': random.random(), 'my_metric': random.uniform(0, 100) } sly.report_metrics_training(epoch_flt, metric_values_train) logger.info("Epoch finished", extra={'epoch': epoch}) # Validation is not necessary but may be performed. So let's imitate validation... logger.info("Validation...") time.sleep(2) # Metrics for validation may also be reported. metric_values_val = { 'loss': random.random(), 'my_metric': random.uniform(0, 20) } sly.report_metrics_validation(epoch_flt, metric_values_val) # Save trained model weights when you want. # Model weights (checkpoint) should be written into directory provided by sly checkpoints_saver. # Content of the directory is entirely dependent on model implementation. cur_checkpoint_dir = checkpoints_saver.get_dir_to_write() dump_fake_model(cur_checkpoint_dir, model) checkpoints_saver.saved(is_best=True, optional_data={ 'epoch': epoch_flt, 'val_metrics': metric_values_val }) # It is necessary to call checkpoints_saver.saved after saving. # By default new model will be created from the best checkpoint over the whole training # (which is determined by "is_best" flag). # Some optional info may be provided. It will be linked with the checkpoint # and may help to distinguish checkpoints from same training. # Thank you for your patience. logger.info('Training finished')
def _read_verif_status(self): if not osp.isfile(self.verif_status_path): raise RuntimeError('VERIFY_FAILED') res = sly.json_load(self.verif_status_path) self.download_images = res['download_images'] self.is_archive = res['is_archive']
def convert(self): # determine dir level by project meta file meta_p = sly.ProjectMeta.find_in_dir(self.in_dir) if meta_p: # meta_file in input dir in_project_root_dir, pr_name_stub = sly.ProjectFS.split_dir_project(self.in_dir) else: # meta file in subdir of input dir possible_projects = sly.get_subdirs(self.in_dir) if len(possible_projects) != 1: raise RuntimeError('Wrong input project structure, or multiple projects are passed.') in_project_root_dir, pr_name_stub = self.in_dir, possible_projects[0] # read if it's possible try: in_fs = sly.ProjectFS.from_disk(in_project_root_dir, pr_name_stub) in_pr_meta = sly.ProjectMeta.from_dir(in_fs.project_path) except Exception: logger.error('Unable to read input meta.', exc_info=False) raise in_possible_datasets = sly.get_subdirs(in_fs.project_path) in_datasets = list(in_fs.pr_structure.datasets.keys()) if len(in_possible_datasets) != len(in_datasets): raise RuntimeError('Excess top-level directories without data (wrong img-ann structure?).') for ds_name, the_ds in in_fs.pr_structure.datasets.items(): req_cnt = the_ds.image_cnt dataset_path = in_fs.dataset_path(ds_name) anns_path = in_fs.dataset_anns_path(dataset_path) imgs_path = in_fs.dataset_imgs_path(dataset_path) for subdir in (anns_path, imgs_path): items_cnt = len(list(os.scandir(subdir))) if items_cnt != req_cnt: raise RuntimeError('Excess files or directories in dataset subdirectory.') found_exts = {x.ia_data['image_ext'] for x in in_fs} if not all(x in sly.ImportImgLister.extensions for x in found_exts): raise RuntimeError('Found image(s) with unsupported types (by extension).') sample_cnt = in_fs.pr_structure.image_cnt if sample_cnt == 0: raise RuntimeError('Empty project, no samples.') logger.info('Found source structure: Supervisely format, {} sample(s).'.format(sample_cnt)) out_pr = deepcopy(in_fs.pr_structure) out_pr.name = self.settings['res_names']['project'] out_pr_fs = sly.ProjectFS(self.out_dir, out_pr) out_pr_fs.make_dirs() in_pr_meta.to_dir(out_pr_fs.project_path) progress = sly.progress_counter_import(out_pr.name, out_pr.image_cnt) for s in out_pr_fs: try: src_img_path = in_fs.img_path(s.ds_name, s.image_name) sly.copy_file(src_img_path, s.img_path) # img is ready src_ann_path = in_fs.ann_path(s.ds_name, s.image_name) packed_ann = sly.json_load(src_ann_path) _ = sly.Annotation.from_packed(packed_ann, in_pr_meta) # to check if it is correct sly.copy_file(src_ann_path, s.ann_path) # ann is ready except Exception: logger.error('Error occurred while processing input sample', exc_info=False, extra={ 'dataset_name': s.ds_name, 'image_name': s.image_name, }) raise progress.iter_done_report()
def load(self): res = sly.json_load(self.train_config_fpath) return res
def main(): logger.info('Hello world.') # It isn't necessary, but let's suppose that our data will be stored as for Supervisely task: # input in '/sly_task_data/data` and results in '/sly_task_data/results'. # So TaskPaths provides the paths. task_paths = sly.TaskPaths() in_pr_dir = task_paths.project_dir # the paths includes project name in_pr_meta = sly.ProjectMeta.from_dir(in_pr_dir) # Now we've read meta of input project. logger.info('Input project meta: {} class(es).'.format( len(in_pr_meta.classes))) in_pr_fs = sly.ProjectFS.from_disk( *sly.ProjectFS.split_dir_project(in_pr_dir)) # Now we've read project structure. logger.info( 'Input project: "{}" contains {} dataset(s) and {} image(s).'.format( in_pr_fs.pr_structure.name, len(in_pr_fs.pr_structure.datasets), in_pr_fs.image_cnt)) # It's convenient to create output project structure and store source file paths in ia_data. out_pr_structure = sly.ProjectStructure( 'my_new_project') # rename project... just for fun for item_descr in in_pr_fs: # iterate over input project new_ia_data = { 'src_ann_path': item_descr.ann_path, 'src_img_path': item_descr.img_path, **item_descr.ia_data # contains 'image_ext' which is required to write images } out_pr_structure.add_item(item_descr.ds_name, item_descr.image_name, new_ia_data) # ProjectFS will provide out file paths out_pr_fs = sly.ProjectFS(task_paths.results_dir, out_pr_structure) # We will add the rectangle to each annotation. new_class_title = 'new-region' rect_to_add = sly.Rect(left=20, top=20, right=50, bottom=100) # Ok, start processing. out_pr_fs.make_dirs() # create all directories required for writing for item_descr in out_pr_fs: # iterate over output project logger.info('Processing sample', extra={ 'dataset': item_descr.ds_name, 'image_name': item_descr.image_name }) # Copy image unchanged. sly.copy_file(item_descr.ia_data['src_img_path'], item_descr.img_path) # Read annotation. ann_packed = sly.json_load(item_descr.ia_data['src_ann_path']) ann = sly.Annotation.from_packed(ann_packed, in_pr_meta) # Add new figure to the annotation. # Method to construct figures returns iterable of new figures. # (e.g., line cropped with image bounds may produce some lines), but here we'll get not more than one figure # ...or no figures if image is less than 20x20. new_figures = sly.FigureRectangle.from_rect(new_class_title, ann.image_size_wh, rect_to_add) ann['objects'].extend(new_figures) # Save annotation. sly.json_dump(ann.pack(), item_descr.ann_path) # OK, and don't forget to create and save output project meta. # We'll save given data and add new class with shape "rectangle". out_pr_meta = deepcopy(in_pr_meta) out_pr_meta.classes.add({ 'title': new_class_title, 'shape': 'rectangle', 'color': '#FFFF00' }) # Then store the meta. out_pr_meta.to_dir(out_pr_fs.project_path) logger.info('Done.')
def main(): # Please note that auxiliary methods from sly (supervisely_lib) use supervisely_lib.logger to format output. # So don't replace formatters or handlers of the logger. # One may use other loggers or simple prints for other output, but it's recommended to use supervisely_lib.logger. logger.info('Hello ML world') print('Glad to see u') # TaskHelperTrain contains almost all needed to run inference as Supervisely task, # including task settings and paths to data and model. task_helper = sly.TaskHelperInference() # All settings and parameters are passed to task in json file. # Content of the file is entirely dependent on model implementation. inference_settings = task_helper.task_settings logger.info('Task settings are read', extra={'task_settings': inference_settings}) # Let's imitate loading training model weights. Task acquires directory with the weights. # And content of the directory is entirely dependent on model implementation. model_dir = task_helper.paths.model_dir model = load_fake_model(model_dir) logger.info('Model weights are loaded', extra={'model_dir': model_dir}) # We are going to read input project with data for inference. project_meta = task_helper.in_project_meta # Project meta contains list of project classes. project_dir = task_helper.paths.project_dir project_fs = sly.ProjectFS.from_disk_dir_project(project_dir) # ProjectFS enlists all samples (image/annotation pairs) in input project. # We are to write inference results as sly project with same structure into provided results dir. # There is no need to save images, only annotations and project meta are required. results_dir = task_helper.paths.results_dir out_project_fs = sly.ProjectFS(results_dir, project_fs.pr_structure) # It's necessary to write project meta (with list of classes) for output project. out_meta = sly.ProjectMeta([{ 'title': 'hat', 'shape': 'point', 'color': '#FF0000' }]) # create meta out_meta.to_dir(out_project_fs.project_path) # and save # We are to report progress of task over sly.ProgressCounter if we want to observe the progress in web panel. # In fact one task may report progress for some sequential (not nested) subtasks, # but here we will report inference progress only. ia_cnt = out_project_fs.pr_structure.image_cnt progress = sly.progress_counter_inference(cnt_imgs=ia_cnt) # Iterating over samples (image/annotation pairs) in input project. for item_descr in project_fs: logger.info('Processing input sample', extra={ 'dataset': item_descr.ds_name, 'image_name': item_descr.image_name }) # Open some image... img = cv2.imread(item_descr.img_path) logger.info('Read image from input project', extra={ 'width': img.shape[1], 'height': img.shape[0] }) # And read corresponding annotation... ann_packed = sly.json_load(item_descr.ann_path) ann = sly.Annotation.from_packed(ann_packed, project_meta) logger.info('Read annotation from input project', extra={'tags': ann['tags']}) logger.info('Some forward pass...') time.sleep(1) # Let's imitate inference output. # We are to save results as sly Figures in annotation. ann['objects'] = [sly.FigurePoint.from_pt('hat', (800, 800)) ] # imagine that our model found the point out_ann_path = out_project_fs.ann_path(item_descr.ds_name, item_descr.image_name) sly.ensure_base_path(out_ann_path) # create intermediate directories sly.json_dump(ann.pack(), out_ann_path) # and save annotation # Note that there is no need to save image. progress.iter_done_report( ) # call it after every iteration to report progress # It's necessary to report that the inference task is finished. sly.report_inference_finished() # Thank you for your patience. logger.info('Applying finished.')
def main(): logger.info('Hello world.') # It isn't necessary, but let's suppose that our data will be stored as for Supervisely task: # input in '/sly_task_data/data` and results in '/sly_task_data/results'. # So TaskPaths provides the paths. task_paths = sly.TaskPaths() project_dir = task_paths.project_dir # the paths includes project name project_meta = sly.ProjectMeta.from_dir(project_dir) # Now we've read meta of input project. logger.info('Input project meta: {} class(es).'.format(len(project_meta.classes))) project_fs = sly.ProjectFS.from_disk(*sly.ProjectFS.split_dir_project(project_dir)) # Now we've read project structure. logger.info('Input project: "{}" contains {} dataset(s) and {} image(s).'.format( project_fs.pr_structure.name, len(project_fs.pr_structure.datasets), project_fs.image_cnt )) # prepare color mapping color_mapping = {} for cls_descr in project_meta.classes: color_s = cls_descr.get('color') if color_s is not None: color = sly.hex2rgb(color_s) # use color from project meta if exists else: color = sly.get_random_color() # or use random color otherwise color_mapping[cls_descr['title']] = color # enumerate all input samples (image/annotation pairs) for item_descr in project_fs: logger.info('Processing input sample', extra={'dataset': item_descr.ds_name, 'image_name': item_descr.image_name}) # Open image img = cv2.imread(item_descr.img_path) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # to work with r-g-b colors # And read corresponding annotation. ann_packed = sly.json_load(item_descr.ann_path) ann = sly.Annotation.from_packed(ann_packed, project_meta) # Draw annotations on image for fig in ann['objects']: color = color_mapping.get(fig.class_title) fig.draw(img, color) # Note that this method draws lines with width 1, and points as single pixels. # Save image. Please note that we just save images, not new Supervisely project. src_image_ext = item_descr.ia_data['image_ext'] # let's preserve source image format (by extension) out_fpath = osp.join( task_paths.results_dir, item_descr.project_name, item_descr.ds_name, item_descr.image_name + src_image_ext ) sly.ensure_base_path(out_fpath) # create intermediate dirs if required img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) # to work with r-g-b colors cv2.imwrite(out_fpath, img) # write image logger.info('Done.')