def __init__(self, name, image, annos=None, meta=None): for anno in annos: assert isinstance(anno, Anno) assert meta is None or isinstance(meta, SampleMeta) assert is_file(image) self.name = name self.path = image _, self.ext = os.path.splitext(os.path.split(self.path)[1]) self.image = imread(image) self.meta = meta self.annos = [] if annos is None else annos
def is_fully_within_image(self, image): """ Estimate whether the bounding box is fully inside the image area. Parameters ---------- image : (H,W,...) ndarray or tuple of int Image dimensions to use. If an ndarray, its shape will be used. If a tuple, it is assumed to represent the image shape and must contain at least two integers. Returns ------- bool True if the bounding box is fully inside the image area. False otherwise. """ shape = imread(image).shape height, width = shape[0:2] return self.xmin >= 0 and self.xmax < width and self.ymin >= 0 and self.ymax < height
def _parse_anno_from_attach(attach): annos = [] if attach is not None and "file_name" in attach: mask_path = os.path.join(self.id2attachpath[id], attach["file_name"]) img_mask = imread(mask_path, 0) bboxes = self._get_bboxes_from_mask(img_mask) for bbox in bboxes: in_others = False for _bbox in bboxes: if BBox.init_from(bbox).is_in(_bbox): in_others = True break if in_others: continue xmin, ymin, xmax, ymax = bbox if xmax - xmin <= 2 or ymax - ymin <= 2: continue anno = Anno(bbox=BBox(xmin=xmin, ymin=ymin, xmax=xmax, ymax=ymax, label=label), label=label, color=self.color_map[label], meta=AnnoMeta()) bin_mask = np.zeros_like(img_mask, np.uint8) bin_mask[ymin:ymax + 1, xmin:xmax + 1] = img_mask[ymin:ymax + 1, xmin:xmax + 1] if np.where(bin_mask != 0)[0].size == 0: continue bin_mask[np.where(bin_mask != 0)] = 1 anno.mask = Mask(bin_mask) annos.append(anno) return annos
def is_partly_within_image(self, image): """ Estimate whether the bounding box is at least partially inside the image area. Parameters ---------- image : (H,W,...) ndarray or tuple of int Image dimensions to use. If an ndarray, its shape will be used. If a tuple, it is assumed to represent the image shape and must contain at least two integers. Returns ------- bool True if the bounding box is at least partially inside the image area. False otherwise. """ shape = imread(image).shape height, width = shape[0:2] eps = np.finfo(np.float32).eps img_bb = BBox(xmin=0, xmax=width - eps, ymin=0, ymax=height - eps) return self.intersection(img_bb) is not None
def _get_bboxes_from_mask(self, mask_or_path): mask = imread(mask_or_path, 0) contours = measure.find_contours(mask, 0.5) reshaped_contour = [] for contour in contours: contour = np.flip(contour, axis=1) s = contour.ravel().tolist() assert len(s) % 2 == 0 s = [(s[i], s[i + 1]) for i in range(len(s)) if i % 2 == 0] reshaped_contour.append(s) bboxes = [] for i in range(len(reshaped_contour)): contour = np.array(reshaped_contour[i]) xmin, xmax = int(np.min(contour[:, 0])) + 1, int( np.max(contour[:, 0])) + 1 ymin, ymax = int(np.min(contour[:, 1])) + 1, int( np.max(contour[:, 1])) + 1 bboxes.append([xmin, ymin, xmax, ymax]) return bboxes