def get_ann(img_path, inst_path): global classes_dict ann = sly.Annotation.from_img_path(img_path) instance_img = sly.image.read(inst_path) img_gray = cv2.cvtColor(instance_img, cv2.COLOR_BGR2GRAY) _, mask_foreground = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY) mask_background = (img_gray == 0) class_name = 'background' color = [1, 1, 1] bitmap = sly.Bitmap(data=mask_background) if not classes_dict.has_key(class_name): obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=color) classes_dict = classes_dict.add(obj_class) ann = ann.add_label(sly.Label(bitmap, classes_dict.get(class_name))) mask_foreground = mask_foreground.astype(np.bool) if np.any(mask_foreground): class_name = 'object' color = [255, 255, 255] bitmap = sly.Bitmap(data=mask_foreground) if not classes_dict.has_key(class_name): obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=color) classes_dict = classes_dict.add(obj_class) ann = ann.add_label(sly.Label(bitmap, classes_dict.get(class_name))) return ann
def get_masks(img): alpha = img[:, :, 3] mask_fg = alpha >= threshold mask_fuzzy = np.logical_and(alpha > 0, alpha < 255) fg = sly.Label(sly.Bitmap(mask_fg), foreground) fzz = None if np.any(mask_fuzzy) and need_fuzzy: fzz = sly.Label(sly.Bitmap(mask_fuzzy), fuzzy) return fg, fzz
def _generate_annotation(self, src_img_path, inst_path): ann = sly.Annotation.from_img_path(src_img_path) if os.path.isfile(inst_path): instance_img = self._read_img_unchanged(inst_path) col2coord = get_col2coord(instance_img) curr_col2cls = { col: self.cls_names[int( col // 256)] # some dirty hack to determine class correctly for col, coord in col2coord.items() } for color, class_name in curr_col2cls.items(): mask = instance_img == color # exact match for 1d uint16 bitmap = sly.Bitmap(data=mask) obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=self.cls2col.get( class_name, sly.color.random_rgb())) if not self.obj_classes.has_key(class_name): self.obj_classes = self.obj_classes.add(obj_class) ann = ann.add_label(sly.Label(bitmap, obj_class)) instance_img[mask] = 0 # to check missing colors, see below if np.sum(instance_img) > 0: sly.logger.warn( 'Not all objects or classes are captured from source segmentation.', extra={}) return ann
def convert_to_nonoverlapping(meta: sly.ProjectMeta, ann: sly.Annotation) -> (sly.ProjectMeta, sly.Annotation): common_img = np.zeros(ann.img_size, np.int32) # size is (h, w) for idx, lbl in enumerate(ann.labels, start=1): if need_convert(lbl.obj_class.geometry_type): if allow_render_for_any_shape(lbl) is True: lbl.draw(common_img, color=idx) else: sly.logger.warn( "Object of class {!r} (shape: {!r}) has non spatial shape {!r}. It will not be rendered." .format(lbl.obj_class.name, lbl.obj_class.geometry_type.geometry_name(), lbl.geometry.geometry_name())) new_classes = sly.ObjClassCollection() new_labels = [] for idx, lbl in enumerate(ann.labels, start=1): if not need_convert(lbl.obj_class.geometry_type): new_labels.append(lbl.clone()) else: if allow_render_for_any_shape(lbl) is False: continue # @TODO: get part of the common_img for speedup mask = common_img == idx if np.any(mask): # figure may be entirely covered by others g = lbl.geometry new_bmp = sly.Bitmap(data=mask) if new_classes.get(lbl.obj_class.name) is None: new_classes = new_classes.add(lbl.obj_class.clone(geometry_type=sly.Bitmap)) new_lbl = lbl.clone(geometry=new_bmp, obj_class=new_classes.get(lbl.obj_class.name)) new_labels.append(new_lbl) new_meta = meta.clone(obj_classes=new_classes) new_ann = ann.clone(labels=new_labels) return (new_meta, new_ann)
def get_ann(img_path, inst_path, default_classes_colors, default_colors_classes): global classes_dict global count_of_colors ann = sly.Annotation.from_img_path(img_path) curr_color_to_class = {} if inst_path is not None: instance_img = sly.image.read(inst_path) instance_img[np.where((instance_img == [0, 0, 0]).all(axis=2))] = [1, 1, 1] colored_img = instance_img * 10 instance_img = instance_img * 10 unique_colors = np.unique(instance_img.reshape(-1, instance_img.shape[2]), axis=0) ann_colors = np.array(unique_colors).tolist() for color in ann_colors: if not color in default_classes_colors.values(): default_classes_colors['object{}'.format(count_of_colors)] = color default_colors_classes[tuple(color)] = 'object{}'.format(count_of_colors) curr_color_to_class[tuple(color)] = 'object{}'.format(count_of_colors) count_of_colors += 1 else: curr_color_to_class[tuple(color)] = default_colors_classes[tuple(color)] for color, class_name in curr_color_to_class.items(): mask = np.all(colored_img == color, axis=2) bitmap = sly.Bitmap(data=mask) if not classes_dict.has_key(class_name): obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=list(color)) classes_dict = classes_dict.add(obj_class) # make it for meta.json ann = ann.add_label(sly.Label(bitmap, classes_dict.get(class_name))) return ann
def get_ann(img_path, inst_path, default_classes_colors): global classes_dict instance_img = sly.image.read(inst_path) colored_img = instance_img ann = sly.Annotation.from_img_path(img_path) unique_colors = np.unique(instance_img.reshape(-1, instance_img.shape[2]), axis=0) for color in unique_colors: mask = np.all(colored_img == color, axis=2) class_name = default_classes_colors[tuple(color)] mask = mask.astype(np.uint8) * 128 im2, contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for i in range(len(contours)): arr = np.array(contours[i], dtype=int) mask_temp = np.zeros(mask.shape, dtype=np.uint8) cv2.fillPoly(mask_temp, [arr], (254, 254, 254)) mask = mask_temp.astype(np.bool) bitmap = sly.Bitmap(data=mask) if not classes_dict.has_key(class_name): obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=list(color)) classes_dict = classes_dict.add(obj_class) ann = ann.add_label(sly.Label(bitmap, classes_dict.get(class_name))) return ann
def get_ann(img_path, inst_path, number_class, pixel_color): global classes_dict ann = sly.Annotation.from_img_path(img_path) if inst_path is not None: instance_img = sly.image.read(inst_path) instance_img = instance_img[:, :, 0] + 1 current_color2class = {} temp = np.unique(instance_img) for pixel in temp: current_color2class[pixel] = number_class[pixel] for pixel, class_name in current_color2class.items(): new_color = pixel_color[pixel] imgray = np.where(instance_img == pixel, instance_img, 0) ret, thresh = cv2.threshold(imgray, 1, 255, 0) im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for i in range(len(contours)): arr = np.array(contours[i], dtype=int) mask_temp = np.zeros(instance_img.shape, dtype=np.uint8) cv2.fillPoly(mask_temp, [np.int32(arr)], (255, 255, 255)) mask = mask_temp.astype(np.bool) bitmap = sly.Bitmap(data=mask) if not classes_dict.has_key(class_name): obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=new_color) classes_dict = classes_dict.add(obj_class) # make it for meta.json ann = ann.add_label(sly.Label(bitmap, classes_dict.get(class_name))) return ann
def get_ann(img_path, inst_path, number_class, pixel_color): global classes_dict instance_img = [] with open(inst_path) as file: for line in file: line = line.split('\n')[0] line = line.split(' ') instance_img.append(line) instance_img = np.array(instance_img, np.uint8) instance_img = instance_img + 2 curr_color_to_class = {} temp = np.unique(instance_img) for pixel in temp: if pixel == 255: continue curr_color_to_class[pixel] = number_class[pixel] ann = sly.Annotation.from_img_path(img_path) for color, class_name in curr_color_to_class.items(): new_color = list(pixel_color[color]) mask = np.where(instance_img == color, instance_img, 0) im2, contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for i in range(len(contours)): arr = np.array(contours[i], dtype=int) mask_temp = np.zeros(instance_img.shape, dtype=np.uint8) cv2.fillPoly(mask_temp, [np.int32(arr)], (254, 254, 254)) mask = mask_temp.astype(np.bool) bitmap = sly.Bitmap(data=mask) if not classes_dict.has_key(class_name): obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=new_color) classes_dict = classes_dict.add(obj_class) ann = ann.add_label(sly.Label(bitmap, classes_dict.get(class_name))) return ann
def get_ann(img_path, inst_path, number_class, pixel_color): global classes_dict ann = sly.Annotation.from_img_path(img_path) if inst_path is not None: mat = scipy.io.loadmat(inst_path) instance_img = mat['LabelMap'] colored_img = cv2.merge((instance_img, instance_img, instance_img)) current_color_to_class = {} temp = np.unique(instance_img) for pixel in temp: current_color_to_class[pixel] = number_class[str(pixel)] for pixel, class_name in current_color_to_class.items(): mask = np.all(colored_img == pixel, axis=2) # exact match (3-channel img & rgb color) new_color = pixel_color[str(pixel)] bitmap = sly.Bitmap(data=mask) if not classes_dict.has_key(class_name): obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=new_color) classes_dict = classes_dict.add(obj_class) # make it for meta.json ann = ann.add_label(sly.Label(bitmap, classes_dict.get(class_name))) # clear used pixels in mask to check missing colors, see below colored_img[mask] = (0, 0, 0) if np.sum(colored_img) > 0: sly.logger.warn('Not all objects or classes are captured from source segmentation.') return ann
def convert_to_nonoverlapping(src_ann: sly.Annotation) -> sly.Annotation: common_img = np.zeros(src_ann.img_size, np.int32) # size is (h, w) for idx, lbl in enumerate(src_ann.labels, start=1): if need_convert(lbl.obj_class.geometry_type): if allow_render_non_spatial_for_any_shape(lbl) == True: lbl.draw(common_img, color=idx) else: sly.logger.warn( "Object of class {!r} (class shape: {!r}) has non spatial shape {!r}. It will not be rendered." .format(lbl.obj_class.name, lbl.obj_class.geometry_type.geometry_name(), lbl.geometry.geometry_name())) new_labels = [] for idx, lbl in enumerate(src_ann.labels, start=1): new_cls = dst_project_meta.obj_classes.get(lbl.obj_class.name) if not need_convert(lbl.obj_class.geometry_type): new_lbl = lbl.clone(obj_class=new_cls) new_labels.append(new_lbl) else: if allow_render_non_spatial_for_any_shape(lbl) == False: continue mask = common_img == idx if np.any(mask): # figure may be entirely covered by others g = lbl.geometry new_bmp = sly.Bitmap(data=mask, labeler_login=g.labeler_login, updated_at=g.updated_at, created_at=g.created_at) new_lbl = lbl.clone(geometry=new_bmp, obj_class=new_cls) new_labels.append(new_lbl) return src_ann.clone(labels=new_labels)
def get_ann(img_path, inst_path, number_class, pixel_color): global classes_dict ann = sly.Annotation.from_img_path(img_path) mat = scipy.io.loadmat(inst_path) instance_img = mat['MM'][0][0][0] instance_img = instance_img.astype(np.uint8) + 1 colored_img = instance_img unique_pixels = np.unique(instance_img) for pixel in unique_pixels: color = pixel_color[pixel] class_name = number_class[pixel] imgray = np.where(colored_img == pixel, colored_img, 0) ret, thresh = cv2.threshold(imgray, 1, 255, 0) im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for i in range(len(contours)): arr = np.array(contours[i], dtype=int) mask_temp = np.zeros(instance_img.shape, dtype=np.uint8) cv2.fillPoly(mask_temp, [arr], (255, 255, 255)) mask = mask_temp.astype(np.bool) bitmap = sly.Bitmap(data=mask) if not classes_dict.has_key(class_name): obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=list(color)) classes_dict = classes_dict.add(obj_class) ann = ann.add_label(sly.Label(bitmap, classes_dict.get(class_name))) return ann
def _get_ann(self, img_path, segm_path, inst_path): segmentation_img = sly.image.read(segm_path) if inst_path is not None: instance_img = sly.image.read(inst_path) colored_img = instance_img instance_img16 = instance_img.astype(np.uint16) col2coord = get_col2coord(instance_img16) curr_col2cls = ((col, self.color2class_name.get(tuple(segmentation_img[coord]))) for col, coord in col2coord.items()) curr_col2cls = {k: v for k, v in curr_col2cls if v is not None} # _instance_ color -> class name else: colored_img = segmentation_img curr_col2cls = self.color2class_name ann = sly.Annotation.from_img_path(img_path) for color, class_name in curr_col2cls.items(): mask = np.all(colored_img == color, axis=2) # exact match (3-channel img & rgb color) bitmap = sly.Bitmap(data=mask) obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=color) if not self.obj_classes.has_key(class_name): self.obj_classes = self.obj_classes.add(obj_class) ann = ann.add_label(sly.Label(bitmap, obj_class)) # clear used pixels in mask to check missing colors, see below colored_img[mask] = (0, 0, 0) if np.sum(colored_img) > 0: sly.logger.warn('Not all objects or classes are captured from source segmentation.') return ann
def get_ann(img_path, inst_path, default_classes_colors): global classes_dict ann = sly.Annotation.from_img_path(img_path) instance_img = sly.image.read(inst_path) img_gray = cv2.cvtColor(instance_img, cv2.COLOR_BGR2GRAY) _, mask_foreground = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY) mask_background = (img_gray == 0) class_name = 'background' new_color = default_classes_colors[class_name] bitmap = sly.Bitmap(data=mask_background) if not classes_dict.has_key(class_name): obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=new_color) classes_dict = classes_dict.add(obj_class) ann = ann.add_label(sly.Label(bitmap, classes_dict.get(class_name))) im2, contours, hierarchy = cv2.findContours(mask_foreground, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) class_name = 'skin' new_color = default_classes_colors[class_name] for i in range(len(contours)): arr = np.array(contours[i], dtype=int) mask_temp = np.zeros(instance_img.shape, dtype=np.uint8) cv2.fillPoly(mask_temp, [np.int32(arr)], (255, 255, 255)) mask_temp = cv2.split(mask_temp)[0] mask = mask_temp.astype(np.bool) bitmap = sly.Bitmap(data=mask) if not classes_dict.has_key(class_name): obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=new_color) classes_dict = classes_dict.add(obj_class) ann = ann.add_label(sly.Label(bitmap, classes_dict.get(class_name))) return ann
def generate_example(augs_settings, augs=None, preview=True, product_id=None, img=None, ann=None): if product_id is None or img is None or ann is None: product_id, img, ann = get_random_product() if logging.getLevelName(sly.logger.level) == 'DEBUG': sly.image.write(os.path.join(vis_dir, "01_img.png"), img) label_image, label_mask = preprocess_product(img, ann, augs_settings, is_main=True) if logging.getLevelName(sly.logger.level) == 'DEBUG': sly.image.write(os.path.join(vis_dir, "02_label_image.png"), label_image) sly.image.write(os.path.join(vis_dir, "03_label_mask.png"), label_mask) orig_h, orig_w = label_image.shape[:2] for crop_f, place_f, range_index in zip(crops_funcs, place_funcs, list(range(0, 4))): if random.uniform(0, 1) <= augs_settings['noise']['corner_probability']: _, noise_img, noise_ann = get_random_product(ignore_id=product_id) noise_img, noise_ann = crop_label(noise_img, noise_ann, padding=0) noise_mask = draw_white_mask(noise_ann) if logging.getLevelName(sly.logger.level) == 'DEBUG': sly.image.write(os.path.join(vis_dir, "04_noise_img.png"), noise_img) if random.uniform(0, 1) <= augs_settings['noise']['aug_probability']: noise_img, noise_mask = augs.apply_to_foreground(noise_img, noise_mask) y_range = get_y_range(range_index, orig_h, portion=augs_settings["noise"]["max_occlusion_height"]) x_range = get_x_range(range_index, orig_w, portion=augs_settings["noise"]["max_occlusion_width"]) y = random.randint(int(y_range[0]), int(y_range[1])) x = random.randint(int(x_range[0]), int(x_range[1])) noise_img, noise_mask = crop_f(y, x, orig_h, orig_w, noise_img, noise_mask) if logging.getLevelName(sly.logger.level) == 'DEBUG': sly.image.write(os.path.join(vis_dir, f"04_noise_img_{range_index}.png"), noise_img) sly.image.write(os.path.join(vis_dir, f"05_noise_mask_{range_index}.png"), noise_mask) place_f(y, x, label_image, label_mask, noise_img, noise_mask) if logging.getLevelName(sly.logger.level) == 'DEBUG': sly.image.write(os.path.join(vis_dir, "06_final_mask.png"), label_mask) if not np.any(label_mask): # if empty mask - figure may be entirely covered by others return None, None, None label_preview = None if preview is True: label_preview = sly.Label( sly.Bitmap(label_mask[:, :, 0].astype(bool), origin=sly.PointLocation(0, 0)), RESULT_CLASS ) return label_image, label_mask, label_preview
def get_ann(img_path, inst_path): global classes_dict default_classes_colors = {} colors = [(0, 0, 0)] ann = sly.Annotation.from_img_path(img_path) if inst_path is not None: mat = scipy.io.loadmat(inst_path) mask = mat['anno'] all_objects = mask[0][0][1][0] class_mask, unique_class_mask = {}, [] for obj in all_objects: object_name, object_mask = obj[0], obj[2] class_mask[object_name[0]] = object_mask unique_class_mask.append([object_name[0], object_mask]) if len(obj[3]) > 0: all_parts = obj[3][0] for part in all_parts: class_mask[part[0][0]] = part[1] unique_class_mask.append([part[0][0], part[1]]) for class_name in class_mask.keys(): if class_name not in default_classes_colors: new_color = generate_rgb(colors) colors.append(new_color) default_classes_colors[class_name] = new_color for temp in unique_class_mask: class_name, cl_mask = temp mask = cl_mask.astype(np.bool) new_color = default_classes_colors[class_name] bitmap = sly.Bitmap(data=mask) if not classes_dict.has_key(class_name): obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=new_color) classes_dict = classes_dict.add( obj_class) # make it for meta.json ann = ann.add_label( sly.Label(bitmap, classes_dict.get(class_name))) return ann
def read_mask_labels(mask_path: str, classes_mapping: Dict, obj_classes: sly.ObjClassCollection) -> List[sly.Label]: mask = cv2.imread(mask_path)[:, :, 0] labels_list = [] for cls_name, color in classes_mapping.items(): if color == MATCH_ALL: bool_mask = mask > 0 elif isinstance(color, int): bool_mask = mask == color elif isinstance(color, list): bool_mask = np.isin(mask, color) else: raise ValueError('Wrong color format. It must be integer, list of integers or special key string "__all__".') if bool_mask.sum() == 0: continue bitmap = sly.Bitmap(data=bool_mask) obj_class = obj_classes.get(cls_name) labels_list.append(sly.Label(geometry=bitmap, obj_class=obj_class)) return labels_list
def get_ann(img_path, inst_path, number_class, pixel_color): global classes_dict if inst_path is not None: instance_img = sly.image.read(inst_path) class_mask = cv2.split(instance_img)[0] class_mask = np.where(class_mask != 0, class_mask, 10) current_color2class = {} unique_pixels = np.unique(class_mask) for pixel in unique_pixels: current_color2class[pixel] = number_class[pixel] ann = sly.Annotation.from_img_path(img_path) for pixel, class_name in current_color2class.items(): new_color = pixel_color[pixel] mask = np.where(class_mask == pixel, class_mask, 0) mask = mask.astype(np.bool) bitmap = sly.Bitmap(data=mask) if not classes_dict.has_key(class_name): obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=list(new_color)) classes_dict = classes_dict.add(obj_class) ann = ann.add_label(sly.Label(bitmap, classes_dict.get(class_name))) return ann
def transform_for_segmentation(meta: sly.ProjectMeta, ann: sly.Annotation) -> (sly.ProjectMeta, sly.Annotation): new_classes = {} class_masks = {} for obj_class in meta.obj_classes: obj_class: sly.ObjClass new_class = obj_class.clone(name=obj_class.name + "-mask") new_classes[obj_class.name] = new_class class_masks[obj_class.name] = np.zeros(ann.img_size, np.uint8) new_class_collection = sly.ObjClassCollection(list(new_classes.values())) for label in ann.labels: label.draw(class_masks[label.obj_class.name], color=255) new_labels = [] for class_name, white_mask in class_masks.items(): mask = white_mask == 255 obj_class = new_classes[class_name] bitmap = sly.Bitmap(data=mask) new_labels.append(sly.Label(geometry=bitmap, obj_class=obj_class)) res_meta = meta.clone(obj_classes=new_class_collection) res_ann = ann.clone(labels=new_labels) return (res_meta, res_ann)
def generate_annotation(src_img_path, inst_path, id_to_class, class_to_color, classes_collection): ann = sly.Annotation.from_img_path(src_img_path) if os.path.isfile(inst_path): instance_img = cv2.imread(inst_path, cv2.IMREAD_UNCHANGED) # expect uint16 col2coord = get_color_to_coordinates(instance_img) # Some dirty hack to determine class correctly, low byte is unused. (Low byte describe) current_color_to_class = { color: id_to_class[int(color // 256)] for color in col2coord.keys() } for color, class_name in current_color_to_class.items(): mask = (instance_img == color) # exact match for 1d uint16 bitmap = sly.Bitmap(mask) if not classes_collection.has_key(class_name): obj_class = sly.ObjClass(name=class_name, geometry_type=sly.Bitmap, color=class_to_color.get( class_name, sly.color.random_rgb())) classes_collection = classes_collection.add(obj_class) ann = ann.add_label( sly.Label(bitmap, classes_collection.get(class_name))) instance_img[mask] = 0 # to check missing colors, see below if np.sum(instance_img) > 0: sly.logger.warn( 'Not all objects or classes are captured from source segmentation.', extra={}) return ann, classes_collection
def convert_to_nonoverlapping(src_ann: sly.Annotation) -> sly.Annotation: common_img = np.zeros(src_ann.img_size, np.uint32) # size is (h, w) for idx, lbl in enumerate(src_ann.labels, start=1): if account_label(lbl): lbl.draw(common_img, color=idx) new_labels = [] for idx, lbl in enumerate(src_ann.labels, start=1): new_cls = dst_project_meta.obj_classes.get(lbl.obj_class.name) if not account_label(lbl): new_lbl = lbl.clone(obj_class=new_cls) new_labels.append(new_lbl) else: mask = common_img == idx if np.any(mask): # figure may be entirely covered by others g = lbl.geometry new_bmp = sly.Bitmap(data=mask, labeler_login=g.labeler_login, updated_at=g.updated_at, created_at=g.created_at) new_lbl = lbl.clone(geometry=new_bmp, obj_class=new_cls) new_labels.append(new_lbl) return src_ann.clone(labels=new_labels)
def extract_foreground(): api = sly.Api.from_env() task_id = int(os.getenv("TASK_ID")) try: if DEBUG: sly.fs.mkdir(const.DEBUG_VIS_DIR) sly.fs.clean_dir(const.DEBUG_VIS_DIR) state = api.task.get_data(task_id, field=const.STATE) project = api.task.get_data(task_id, field="{}.projects[{}]".format( const.DATA, state[const.PROJECT_INDEX])) project_id = project["id"] workspace_id = api.project.get_info_by_id(project_id).workspace_id team_id = api.workspace.get_info_by_id(workspace_id).team_id processed_items = [] api.task.set_data(task_id, payload=processed_items, field="{}.{}".format(const.DATA, const.TABLE)) # sample images all_images = [] for dataset in api.dataset.get_list(project_id): images = api.image.get_list(dataset.id) image_dataset = [dataset] * len(images) all_images.extend(zip(images, image_dataset)) # read sample count if state[const.SAMPLE_FLAG]: cnt_images = state[const.SAMPLE_COUNT] assert cnt_images <= len(all_images) random.shuffle(all_images) all_images = all_images[:cnt_images] fg_class, st_class = set_project_meta(api, project_id, state) sly.fs.mkdir(const.CACHE_DIR) for idx, (image_info, dataset_info) in enumerate(all_images): table_row = {} image_id = image_info.id table_row['id'] = image_id sly.logger.debug("---> image_id = {}".format(image_id)) if DEBUG: debug_img_dir = os.path.join(const.DEBUG_VIS_DIR, str(image_id)) sly.fs.mkdir(debug_img_dir) image_url = api.image.url(team_id, workspace_id, project_id, dataset_info.id, image_id) table_row['name'] = '<a href="{0}" rel="noopener noreferrer" target="_blank">{1}</a>' \ .format(image_url, image_info.name) image_path = os.path.join(const.CACHE_DIR, "{}.png".format(image_id)) if not sly.fs.file_exists(image_path): api.image.download_path( image_id, image_path, ) image = sly.image.read(image_path, remove_alpha_channel=False) if image.shape[2] != 4: sly.logger.warning( "Image (id = {}) is skipped: it does not have alpha channel" .format(image_id)) continue if DEBUG: sly.image.write(os.path.join(debug_img_dir, '000_image.png'), image, remove_alpha_channel=False) alpha = image[:, :, 3] if DEBUG: sly.image.write(os.path.join(debug_img_dir, '001_alpha.png'), alpha) # extract foreground pixels mask = (alpha >= state[const.ALPHA_THRESHOLD]).astype( np.uint8) * 255 if DEBUG: sly.image.write(os.path.join(debug_img_dir, '002_mask.png'), mask) # create mask for all connected components mask_instances, num_cc = skimage.measure.label(mask, background=0, return_num=True) if DEBUG: vis = skimage.color.label2rgb(mask_instances, bg_label=0) sly.image.write(os.path.join(debug_img_dir, '003_mask_cc.png'), vis * 255) table_row['total objects'] = num_cc # remove small objects area_pixels = int(mask_instances.shape[0] * mask_instances.shape[1] / 100 * state[const.AREA_THRESHOLD]) mask_cleaned = skimage.morphology.remove_small_objects( mask_instances, area_pixels) mask_cleaned, num_cc = skimage.measure.label(mask_cleaned, background=0, return_num=True) if DEBUG: vis = skimage.color.label2rgb(mask_cleaned, bg_label=0) sly.image.write( os.path.join(debug_img_dir, '004_mask_cleaned.png'), vis * 255) cc_area = count_instances_area(mask_cleaned, num_cc) cc_area = cc_area[:state[const.MAX_NUMBER_OF_OBJECTS]] table_row['final objects'] = len(cc_area) labels = [] sly.logger.debug( "image_id = {}, number of extracted objects: {}".format( image_id, len(cc_area))) for cc_color, area in cc_area: object_mask = (mask_cleaned == cc_color) geometry = sly.Bitmap(data=object_mask) label = sly.Label(geometry, fg_class) labels.append(label) #find gray zone gray_zone = np.logical_and(alpha != 0, alpha != 255) if np.sum(gray_zone) != 0: #gray_zone is not empty gray_geometry = sly.Bitmap(data=gray_zone) gray_label = sly.Label(gray_geometry, st_class) labels.append(gray_label) table_row['gray area (%)'] = round( np.sum(gray_zone) * 100 / (gray_zone.shape[0] * gray_zone.shape[1]), 2) ann = sly.Annotation(mask.shape[:2], labels=labels) if DEBUG: render = np.zeros(ann.img_size + (3, ), dtype=np.uint8) ann.draw(render) sly.image.write(os.path.join(debug_img_dir, '005_ann.png'), render) api.annotation.upload_ann(image_id, ann) processed_items.append(table_row) #time.sleep(2) if (idx % const.NOTIFY_EVERY == 0 and idx != 0) or idx == len(all_images) - 1: api.task.set_data(task_id, payload=processed_items, field="{}.{}".format(const.DATA, const.TABLE), append=True) processed_items = [] update_progress(api, task_id, (idx + 1) * 100 / len(all_images)) need_stop = api.task.get_data(task_id, field="{}.{}".format( const.STATE, const.STOP_CLICKED)) if need_stop is True: reset_buttons_and_progress(api, task_id) sly.logger.info("SCRIPT IS STOPPED") exit(0) except Exception as e: sly.logger.critical('Unexpected exception', exc_info=True, extra={ 'event_type': sly.EventType.TASK_CRASHED, 'exc_str': str(e), }) sly.logger.debug('Script finished: ERROR') else: sly.logger.debug('Script finished: OK') finally: reset_buttons_and_progress(api, task_id) pass
def synthesize(api: sly.Api, task_id, state, meta: sly.ProjectMeta, image_infos, labels, bg_images, cache_dir, preview=True): progress_cb = refresh_progress_preview if preview is False: progress_cb = refresh_progress augs = yaml.safe_load(state["augs"]) sly.logger.info("Init augs from yaml file") aug.init_fg_augs(augs) visibility_threshold = augs['objects'].get('visibility', 0.8) classes = state["selectedClasses"] bg_info = random.choice(bg_images) sly.logger.info("Download background") bg = api.image.download_np(bg_info.id) sly.logger.debug(f"BG shape: {bg.shape}") res_image = bg.copy() res_labels = [] # sequence of objects that will be generated res_classes = [] to_generate = [] for class_name in classes: original_class: sly.ObjClass = meta.get_obj_class(class_name) res_classes.append(original_class.clone(geometry_type=sly.Bitmap)) count_range = augs["objects"]["count"] count = random.randint(*count_range) for i in range(count): to_generate.append(class_name) random.shuffle(to_generate) res_meta = sly.ProjectMeta(obj_classes=sly.ObjClassCollection(res_classes)) progress = sly.Progress("Processing foregrounds", len(to_generate)) progress_cb(api, task_id, progress) progress_every = max(10, int(len(to_generate) / 20)) cover_img = np.zeros(res_image.shape[:2], np.int32) # size is (h, w) objects_area = defaultdict(lambda: defaultdict(float)) cached_images = {} # generate objects for idx, class_name in enumerate(to_generate, start=1): if class_name not in labels: progress.iter_done_report() continue image_id = random.choice(list(labels[class_name].keys())) label: sly.Label = random.choice(labels[class_name][image_id]) if image_id in cached_images: source_image = cached_images[image_id] else: image_info = image_infos[image_id] source_image = _get_image_using_cache(api, cache_dir, image_id, image_info) cached_images[image_id] = source_image label_img, label_mask = get_label_foreground(source_image, label) #sly.image.write(os.path.join(cache_dir, f"{index}_label_img.png"), label_img) #sly.image.write(os.path.join(cache_dir, f"{index}_label_mask.png"), label_mask) label_img, label_mask = aug.apply_to_foreground(label_img, label_mask) #sly.image.write(os.path.join(cache_dir, f"{index}_aug_label_img.png"), label_img) #sly.image.write(os.path.join(cache_dir, f"{index}_aug_label_mask.png"), label_mask) label_img, label_mask = aug.resize_foreground_to_fit_into_image( res_image, label_img, label_mask) #label_area = g.area find_place = False for attempt in range(3): origin = aug.find_origin(res_image.shape, label_mask.shape) g = sly.Bitmap(label_mask[:, :, 0].astype(bool), origin=sly.PointLocation(row=origin[1], col=origin[0])) difference = count_visibility(cover_img, g, idx, origin[0], origin[1]) allow_placement = True for object_idx, diff in difference.items(): new_area = objects_area[object_idx]['current'] - diff visibility_portion = new_area / objects_area[object_idx][ 'original'] if visibility_portion < visibility_threshold: #sly.logger.warn(f"Object '{idx}', attempt {attempt + 1}: " # f"visible portion ({visibility_portion}) < threshold ({visibility_threshold})") allow_placement = False break if allow_placement is True: find_place = True break else: continue if find_place is False: sly.logger.warn( f"Object '{idx}' is skipped: can not be placed to satisfy visibility threshold" ) continue try: aug.place_fg_to_bg(label_img, label_mask, res_image, origin[0], origin[1]) g.draw(cover_img, color=idx) for object_idx, diff in difference.items(): objects_area[object_idx]['current'] -= diff current_obj_area = g.area objects_area[idx]['current'] = current_obj_area objects_area[idx]['original'] = current_obj_area res_labels.append(sly.Label(g, res_meta.get_obj_class(class_name))) except Exception as e: #sly.logger.warn(repr(e)) sly.logger.warn( f"FG placement error:: label shape: {label_img.shape}; mask shape: {label_mask.shape}", extra={"error": repr(e)}) progress.iter_done_report() if idx % progress_every == 0: # progress.need_report(): progress_cb(api, task_id, progress) progress_cb(api, task_id, progress) res_ann = sly.Annotation(img_size=bg.shape[:2], labels=res_labels) # debug visualization # sly.image.write(os.path.join(cache_dir, "__res_img.png"), res_image) #res_ann.draw(res_image) #sly.image.write(os.path.join(cache_dir, "__res_ann.png"), res_image) res_meta, res_ann = rasterize.convert_to_nonoverlapping(res_meta, res_ann) return res_image, res_ann, res_meta