annotation.py 2.9 KB

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