annotation.py 3.2 KB

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