import numpy as np from matplotlib.patches import Rectangle from nabirds import utils from .base import BasePart class LocationPart(BasePart): DEFAULT_RATIO = np.sqrt(49 / 400) # 0.35 def __init__(self, image, annotation, rescale_size=None): super(LocationPart, self).__init__() annotation = self.rescale(image, annotation, rescale_size) # here x,y are the center of the part self._id, self.x, self.y, self.is_visible = annotation self._ratio = LocationPart.DEFAULT_RATIO def as_annotation(self): return np.array([self._id, self.x, self.y, self.is_visible]) def crop(self, image, ratio=None, padding_mode="edge", *args, **kwargs): ratio = ratio or self._ratio _h, _w, c = utils.dimensions(image) w, h = int(_w * ratio), int(_h * ratio) return super(LocationPart, self).crop(image, w, h, padding_mode, is_location=True) def reveal(self, im, ratio=None, *args, **kwargs): _h, _w, c = utils.dimensions(im) w, h = int(_w * ratio), int(_h * ratio) x,y = self.xy x, y = max(x - w // 2, 0), max(y - h // 2, 0) return x, y, im[y:y+h, x:x+w] def plot(self, im, ax, ratio, fill=False, linestyle="--", **kwargs): if not self.is_visible: return x, y = self.xy _h, _w, c = utils.dimensions(im) w, h = int(_w * ratio), int(_h * ratio) ax.add_patch(Rectangle( (x-w//2, y-h//2), w, h, fill=fill, linestyle=linestyle, **kwargs )) ax.scatter(*self.middle, marker="x", color="white", alpha=0.8) @property def middle(self): return np.array([self.x, self.y]) class BBoxPart(BasePart): def __init__(self, image, annotation, rescale_size=None): super(BBoxPart, self).__init__() annotation = self.rescale(image, annotation, rescale_size) # here x,y are top left corner of the part self._id, self.x, self.y, self.w, self.h = annotation self.is_visible = True @property def as_annotation(self): return np.array([self._id, self.x, self.y, self.w, self.h]) def rescale(self, image, annotation, rescale_size): if rescale_size is not None and rescale_size > 0: annotation = super(BBoxPart, self).rescale(image, annotation, rescale_size) h, w, c = utils.dimensions(image) scale = np.array([w, h]) / rescale_size wh = annotation[3:5] wh = wh * scale annotation[3:5] = wh return annotation @property def middle(self): return np.array([self.x + self.w // 2, self.y + self.h // 2]) def crop(self, image, padding_mode="edge", *args, **kwargs): return super(BBoxPart, self).crop(image, self.w, self.h, padding_mode, is_location=False) def reveal(self, im, ratio, *args, **kwargs): _h, _w, c = utils.dimensions(im) x,y = self.xy return x, y, im[y:y+self.h, x:x+self.w] def plot(self, im, ax, ratio, fill=False, linestyle="--", **kwargs): ax.add_patch(Rectangle( (self.x, self.y), self.w, self.h, fill=fill, linestyle=linestyle, **kwargs )) ax.scatter(*self.middle, marker="x", color="white", alpha=0.8)