base_classes.py 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import typing
  2. import numpy as np
  3. from abc import ABC, abstractmethod
  4. from view.python_core.areas import frame_mask2perim
  5. class BaseROIData(ABC):
  6. """
  7. Abstract class to define ROI Data API
  8. """
  9. def __init__(self, label, basic_text_description="A ROI"):
  10. """
  11. Initialize label
  12. :param label: str
  13. """
  14. super().__init__()
  15. self.label = label
  16. self.basic_text_description = basic_text_description
  17. self.roi_file = None
  18. def get_text_description(self, frame_size):
  19. return self.basic_text_description
  20. @abstractmethod
  21. def get_boolean_mask(self, frame_size: typing.Iterable[int]) -> np.ndarray:
  22. """
  23. Returns a boolen array with all pixels belonging to the ROI set to True and False otherwise.
  24. :param frame_size: two member iterable of ints. Output mask will have this shape
  25. :return: numpy.ndarray
  26. """
  27. pass
  28. def get_weighted_mask(self, frame_size: typing.Iterable[int]) -> np.ndarray:
  29. """
  30. Returns a float numpy array whose pixels indicate the extent to which a pixel belongs to the
  31. ROI. Pixel values add up to 1.
  32. :param frame_size: two member iterable of ints. Output array will have this shape
  33. :return: numpy.ndarray
  34. """
  35. float_mask = self.get_boolean_mask(frame_size).astype(float)
  36. return float_mask / np.nansum(float_mask)
  37. def get_weighted_mask_considering_area(self, area_mask: np.ndarray) -> np.ndarray:
  38. """
  39. Returns a numpy.ndarray similar to `get_weighted_mask`, but with values of pixels with `area_mask` is False
  40. set to 0. The returned ndarray adds up to 1 as well.
  41. :param numpy.ndarray area_mask: boolean array with shape
  42. :return: numpy.ndarray
  43. """
  44. weighted_mask = self.get_weighted_mask(area_mask.shape)
  45. weighted_mask[~area_mask] = 0
  46. return weighted_mask / np.nansum(weighted_mask)
  47. def get_perimeter_mask(self, frame_size: typing.Iterable[int]) -> typing.Tuple[np.ndarray, np.ndarray]:
  48. """
  49. Returns a boolean numpy array with pixels on the the perimeter of the ROI set to True and all else to False.
  50. :param frame_size: two member iterable of ints. Output mask will have this shape
  51. :return: numpy.ndarray
  52. """
  53. boolean_mask = self.get_boolean_mask(frame_size)
  54. return frame_mask2perim(boolean_mask), boolean_mask
  55. def get_boolean_mask_without_perimeter(self, frame_size: typing.Iterable[int]) -> np.ndarray:
  56. """
  57. Returns a boolean numpy array with all pixels belonging to the ROI and not on it's perimeter set to True
  58. and False otherwise
  59. :param frame_size: two member iterable of ints. Output mask will have this shape
  60. :return: numpy.ndarray
  61. """
  62. perimeter_mask, boolean_mask = self.get_perimeter_mask(frame_size=frame_size)
  63. mask_without_perimeter = np.logical_and(boolean_mask, np.logical_not(perimeter_mask))
  64. return mask_without_perimeter