idl_rois.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import typing
  2. import numpy as np
  3. from skimage.draw import rectangle
  4. from .base_classes import BaseROIData
  5. from .iltis_rois.text_based import BaseTextROIData
  6. class SquareIDLROIData(BaseTextROIData):
  7. def __init__(self, label: str, center_x: int, center_y: int, half_width: int,
  8. basic_text_description="A square IDL ROI"):
  9. """
  10. Initialize a square ROI object
  11. :param label: str, unique identifier for the ROI
  12. :param center_x: int, X coordinate of the center of the square, as written in .coor file
  13. :param center_y: int, Y coordinate of the center of the square, as written in .coor file
  14. :param half_width: int, half of the side of the square
  15. """
  16. super().__init__(label, basic_text_description)
  17. self.center_x = int(center_x)
  18. self.center_y = int(center_y)
  19. self.half_width = int(half_width)
  20. @classmethod
  21. def read_from_text_line(cls, text_line):
  22. """
  23. Initialize a square ROI object from a line of text. Note: Only information about the center of the square,
  24. i.e., <self.center_x> and <self.center_y> are set. Half width <self.half_width> is set to zero and
  25. needs to be manually set before the ROI object can be used.
  26. :param text_line: str, possibly ending with a '\n'
  27. :return: SquareIDLROIData object
  28. """
  29. text_line = text_line.rstrip("\n")
  30. text_parts = cls.split_line(text_line)
  31. label = text_parts[2].lstrip("\t ")
  32. x, y = (int(temp) for temp in text_parts[:2])
  33. return cls(label=label, center_x=x, center_y=y, half_width=0, basic_text_description=text_line)
  34. def write_to_text_line(self) -> str:
  35. raise NotImplementedError # TODO
  36. def get_boolean_mask(self, frame_size: typing.Iterable[int]) -> np.ndarray:
  37. """
  38. Returns a boolean numpy array with pixels on the the perimeter of the polygon set to True and all else to False.
  39. :param frame_size: 2-member tuple of ints
  40. :return: numpy.ndarray
  41. """
  42. mask = np.zeros(frame_size, dtype=bool)
  43. # clip to within frame, in case values extend outside
  44. x_start, x_end = np.clip([self.center_x - self.half_width, self.center_x + self.half_width], 0, frame_size[0])
  45. y_start, y_end = np.clip([self.center_y - self.half_width, self.center_y + self.half_width], 0, frame_size[1])
  46. # function rectangle draws a rectangle that includes both start and end points
  47. rr, cc = rectangle(start=(x_start, y_start), end=(x_end, y_end))
  48. rr, cc = rr.astype(int), cc.astype(int)
  49. mask[rr, cc] = True
  50. return np.flip(mask, axis=1)
  51. class TIFFIDLROIData(BaseROIData):
  52. def __init__(
  53. self, label: str, idl_tiff_frame: np.ndarray, basic_text_description="AREA TIFF IDL ROI"):
  54. super().__init__(label, basic_text_description)
  55. self.idl_tiff_frame = idl_tiff_frame
  56. def get_boolean_mask(self, frame_size: typing.Iterable[int]) -> np.ndarray:
  57. """
  58. Returns a boolen array with all pixels belonging to the ROI set to True and False otherwise.
  59. :param frame_size: two member iterable of ints. Output mask will have this shape
  60. :return: numpy.ndarray
  61. """
  62. return self.idl_tiff_frame > 0