def get_segment_mask(self, seq_id: str, query_segmentid: int, fname_stem: str, split: str) -> Optional[np.ndarray]: """ Uses the raw version of the dataset (as originally distributed) to get a mask. Args: - seq_id: sequence ID, parent of file name in file system tree. - query_segmentid - fname_stem: RGB image file name stem, e.g. 'aachen_000015_000019_leftImg8bit' - split: 'train' or 'val' Returns: - obj_mask: Numpy array of shape (H,W) of type uint8, should consist of 0s and 1s """ label_fname_stem = fname_stem.replace('_leftImg8bit', '') gt_fpath = f'{self.dataroot}/gtFine/{split}/{seq_id}/{label_fname_stem}_gtFine_polygons.json' img_gt_dict = read_json_file(gt_fpath) img_gt_objs = img_gt_dict['objects'] img_h = img_gt_dict['imgHeight'] img_w = img_gt_dict['imgWidth'] for obj_idx, gt_obj in enumerate(img_gt_objs): if 'id' in gt_obj.keys(): segment_id = gt_obj['id'] else: segment_id = obj_idx if segment_id == query_segmentid: obj_poly = gt_obj['polygon'] # first arg is tuple_verts: Iterable with elements of size 2 (list of 2-tuples, or Nx2 numpy array) obj_mask = get_mask_from_polygon(obj_poly, img_h, img_w) obj_mask = obj_mask.astype(np.uint8) return obj_mask return None
def write_class_masks(self, required_class_names: List[str], highlight_classname: str, condition: str, folder_prefix: str): """ Each path resembles: gt_fpath = '/export/work/johnlamb/MTURK_IDD_COPY/IDD_Segmentation/gtFine/val/119/638495_gtFine_polygons.json' """ for split in ['train', 'val']: gt_fpaths = glob.glob(f'{self.dataroot}/gtFine/{split}/**/*.json', recursive=True) num_split_imgs = len(gt_fpaths) for i, gt_fpath in enumerate(gt_fpaths): print(f'On image {i} / {num_split_imgs-1}') img_gt_dict = read_json_file(gt_fpath) img_gt_objs = img_gt_dict['objects'] img_h = img_gt_dict['imgHeight'] img_w = img_gt_dict['imgWidth'] present_classnames = [ gt_obj['label'] for gt_obj in img_gt_objs ] if highlight_classname not in present_classnames: print(f'\tSkip {i}') continue seq_id = Path(gt_fpath).parts[-2] fname_stem = Path(gt_fpath).stem rgb_img = self.get_rgb_img(seq_id, fname_stem, split) segment_ids = set() for obj_idx, gt_obj in enumerate(img_gt_objs): if 'id' in gt_obj.keys(): segment_id = gt_obj['id'] else: segment_id = obj_idx # each segment ID must be unique for this image. assert segment_id not in segment_ids segment_ids.add(segment_id) obj_label = gt_obj['label'] if obj_label == highlight_classname: obj_poly = gt_obj['polygon'] # first arg is tuple_verts: Iteratable with elements of size 2 (list of 2-tuples, or Nx2 numpy array) obj_mask = get_mask_from_polygon( obj_poly, img_h, img_w) obj_mask = obj_mask.astype(np.uint8) # not adding {obj_idx} to filename path now. save_fpath = f'temp_files/{folder_prefix}_{split}_2020_03_10/seq{seq_id}_{fname_stem}_{segment_id}.jpg' save_binary_mask_double(rgb_img, obj_mask, save_fpath, save_to_disk=True)
def test_polygon_to_mask2(): """ """ h = 6 w = 6 # define (x,y) tuples polygon = [[2, 0], [5, 3], [0, 5]] mask = get_mask_from_polygon(polygon, h, w) gt_mask = np.array([[0, 0, 1, 0, 0, 0], [0, 0, 1, 1, 0, 0], [0, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1], [1, 1, 1, 0, 0, 0], [1, 0, 0, 0, 0, 0]]) assert np.allclose(mask, gt_mask)
def test_get_mask_from_polygon(visualize=False): """ """ img_w = 16 img_h = 8 tuple_verts = [ (2, 6), (6, 2), (6, 4), (10, 4), (10, 6), (2, 6) # may be ignored ] mask = get_mask_from_polygon(tuple_verts, img_h, img_w) gt_mask = np.array( [[ False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False ], [ False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False ], [ False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False ], [ False, False, False, False, False, True, True, False, False, False, False, False, False, False, False, False ], [ False, False, False, False, True, True, True, False, False, False, False, False, False, False, False, False ], [ False, False, False, True, True, True, True, True, True, True, True, False, False, False, False, False ], [ False, False, True, True, True, True, True, True, True, True, True, False, False, False, False, False ], [ False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False ]]) assert np.allclose(mask, gt_mask) if visualize: plt.imshow(mask) plt.show()
def test_get_mask_from_polygon(): """ Test PIL rasterization correctness on a simple 2x2 square pattern. """ # define (x,y) tuples polygon = [[0, 0], [2, 0], [2, 2], [0, 2]] img_h = 4 img_w = 4 mask = get_mask_from_polygon(polygon, img_h, img_w) gt_mask = np.array( [[1, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0]], dtype=np.uint8) assert np.allclose(mask, gt_mask)
def test_polygon_to_mask_hline(): """ Many thanks to jmsteitz for noting this case. horizontal line https://github.com/mseg-dataset/mseg-api/issues/7 """ h, w = 8, 8 polygon = [(2, 2), (8, 2)] mask = get_mask_from_polygon(polygon, h, w) gt_mask = np.array([[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]], dtype=np.uint8) assert np.allclose(gt_mask, mask)
def overlay_instances( self, label_map, id_to_class_name_map, alpha=0.5 ): """ Args: boxes (Boxes, RotatedBoxes or ndarray): either a :class:`Boxes`, or an Nx4 numpy array of XYXY_ABS format for the N objects in a single image, or a :class:`RotatedBoxes`, or an Nx5 numpy array of (x_center, y_center, width, height, angle_degrees) format for the N objects in a single image, labels (list[str]): the text to be displayed for each instance. masks (masks-like object): Supported types are: * `structures.masks.PolygonMasks`, `structures.masks.BitMasks`. * list[list[ndarray]]: contains the segmentation masks for all objects in one image. The first level of the list corresponds to individual instances. The second level to all the polygon that compose the instance, and the third level to the polygon coordinates. The third level should have the format of [x0, y0, x1, y1, ..., xn, yn] (n >= 3). * list[ndarray]: each ndarray is a binary mask of shape (H, W). * list[dict]: each dict is a COCO-style RLE. keypoints (Keypoint or array like): an array-like object of shape (N, K, 3), where the N is the number of instances and K is the number of keypoints. The last dimension corresponds to (x, y, visibility or score). assigned_colors (list[matplotlib.colors]): a list of colors, where each color corresponds to each mask or box in the image. Refer to 'matplotlib.colors' for full list of formats that the colors are accepted in. Returns: output (VisImage): image object with visualizations. """ for label_idx in np.unique(label_map): color = fixed_color(rgb=True, maximum=1, idx=label_idx) text = id_to_class_name_map[label_idx] segment = label_map == label_idx #import pdb; pdb.set_trace() mask_obj = GenericMask(segment, self.output.height, self.output.width) polygons, _ = mask_obj.mask_to_polygons(segment) for polygon_verts in polygons: #print('Polygon verts: ', polygon_verts) # rasterize this specific polygon segment_mask = get_mask_from_polygon(polygon_verts, self.output.height, self.output.width) class_mode_idx = get_most_populous_class(segment_mask, label_map) if class_mode_idx != label_idx: continue self.draw_polygon(polygon_verts, color, alpha=alpha) # import matplotlib.pyplot as plt # plt.imshow(segment_mask) # plt.show() # draw text in the center (defined by median) when box is not drawn # median is less sensitive to outliers. text_pos = np.median(segment_mask.nonzero(), axis=1)[::-1] horiz_align = "center" x0 = np.amin(polygon_verts[:,0]) x1 = np.amax(polygon_verts[:,0]) y0 = np.amin(polygon_verts[:,1]) y1 = np.amax(polygon_verts[:,1]) # else: # continue # drawing the box confidence for keypoints isn't very useful. # # for small objects, draw text at the side to avoid occlusion # instance_area = (y1 - y0) * (x1 - x0) # if ( # instance_area < _SMALL_OBJECT_AREA_THRESH * self.output.scale # or y1 - y0 < 40 * self.output.scale # ): # if y1 >= self.output.height - 5: # text_pos = (x1, y0) # else: # text_pos = (x0, y1) height_ratio = (y1 - y0) / np.sqrt(self.output.height * self.output.width) lighter_color = self._change_color_brightness(color, brightness_factor=0.7) font_size = ( np.clip((height_ratio - 0.02) / 0.08 + 1, 1.2, 2) * 0.5 * self._default_font_size ) self.draw_text( text, text_pos, color=lighter_color, horizontal_alignment=horiz_align, font_size=font_size, ) # import matplotlib.pyplot as plt # plt.imshow(self.output.get_image()) # plt.show() return self.output.get_image()