annotation.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import numpy as np
  2. from matplotlib.patches import Rectangle
  3. from nabirds import utils
  4. from .base import BasePart
  5. class LocationPart(BasePart):
  6. DEFAULT_RATIO = np.sqrt(49 / 400) # 0.35
  7. def __init__(self, image, annotation, rescale_size=None):
  8. super(LocationPart, self).__init__()
  9. annotation = self.rescale(image, annotation, rescale_size)
  10. # here x,y are the center of the part
  11. self._id, self.x, self.y, self.is_visible = annotation
  12. self._ratio = LocationPart.DEFAULT_RATIO
  13. def as_annotation(self):
  14. return np.array([self._id, self.x, self.y, self.is_visible])
  15. def crop(self, image, ratio=None, padding_mode="edge", *args, **kwargs):
  16. ratio = ratio or self._ratio
  17. _h, _w, c = utils.dimensions(image)
  18. w, h = int(_w * ratio), int(_h * ratio)
  19. return super(LocationPart, self).crop(image, w, h,
  20. padding_mode, is_location=True)
  21. def reveal(self, im, ratio=None, *args, **kwargs):
  22. _h, _w, c = utils.dimensions(im)
  23. w, h = int(_w * ratio), int(_h * ratio)
  24. x,y = self.xy
  25. x, y = max(x - w // 2, 0), max(y - h // 2, 0)
  26. return x, y, im[y:y+h, x:x+w]
  27. def plot(self, im, ax, ratio, fill=False, linestyle="--", **kwargs):
  28. if not self.is_visible: return
  29. x, y = self.xy
  30. _h, _w, c = utils.dimensions(im)
  31. w, h = int(_w * ratio), int(_h * ratio)
  32. ax.add_patch(Rectangle(
  33. (x-w//2, y-h//2), w, h,
  34. fill=fill, linestyle=linestyle,
  35. **kwargs
  36. ))
  37. ax.scatter(*self.middle, marker="x", color="white", alpha=0.8)
  38. @property
  39. def middle(self):
  40. return np.array([self.x, self.y])
  41. class BBoxPart(BasePart):
  42. def __init__(self, image, annotation, rescale_size=None):
  43. super(BBoxPart, self).__init__()
  44. annotation = self.rescale(image, annotation, rescale_size)
  45. # here x,y are top left corner of the part
  46. self._id, self.x, self.y, self.w, self.h = annotation
  47. self.is_visible = True
  48. @property
  49. def as_annotation(self):
  50. return np.array([self._id, self.x, self.y, self.w, self.h])
  51. def rescale(self, image, annotation, rescale_size):
  52. if rescale_size is not None and rescale_size > 0:
  53. annotation = super(BBoxPart, self).rescale(image, annotation, rescale_size)
  54. h, w, c = utils.dimensions(image)
  55. scale = np.array([w, h]) / rescale_size
  56. wh = annotation[3:5]
  57. wh = wh * scale
  58. annotation[3:5] = wh
  59. return annotation
  60. @property
  61. def middle(self):
  62. return np.array([self.x + self.w // 2, self.y + self.h // 2])
  63. def crop(self, image, padding_mode="edge", *args, **kwargs):
  64. return super(BBoxPart, self).crop(image, self.w, self.h,
  65. padding_mode, is_location=False)
  66. def reveal(self, im, ratio, *args, **kwargs):
  67. _h, _w, c = utils.dimensions(im)
  68. x,y = self.xy
  69. return x, y, im[y:y+self.h, x:x+self.w]
  70. def plot(self, im, ax, ratio, fill=False, linestyle="--", **kwargs):
  71. ax.add_patch(Rectangle(
  72. (self.x, self.y), self.w, self.h,
  73. fill=fill, linestyle=linestyle,
  74. **kwargs
  75. ))
  76. ax.scatter(*self.middle, marker="x", color="white", alpha=0.8)