123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- import numpy as np
- import typing
- class Excluder2D(object):
- def __init__(self, cutborder_x=0, cutborder_y=0):
- self.cutborder_x = cutborder_x
- self.cutborder_y = cutborder_y
- def check_if_cutborder_too_large(self, frame_size):
- if self.cutborder_x >= 0.5 * frame_size[0]:
- raise ValueError(
- f"Specified value of cutborder_x={self.cutborder_x} is too large of data of frame size {frame_size}")
- if self.cutborder_y >= 0.5 * frame_size[1]:
- raise ValueError(
- f"Specified value of cutborder_y={self.cutborder_y} is too large of data of frame size {frame_size}")
- def exclude_from_frame(self, frame_data: np.ndarray):
- """
- Returns an XY numpy array with data along X and Y excluded
- :param frame_data: numpy.ndarray, in XY format
- :return: numpy.ndarray
- """
- self.check_if_cutborder_too_large(frame_data.shape)
- return frame_data[
- self.cutborder_x: frame_data.shape[0] - self.cutborder_x,
- self.cutborder_y: frame_data.shape[1] - self.cutborder_y
- ]
- def revise_frame_size(self, frame_size):
- """
- Revises frame size by excluding pixels along X and Y
- :param frame_size: tuple of size 2
- :return: tuple of size 2
- """
- self.check_if_cutborder_too_large(frame_size)
- revised_frame = frame_size[0] - 2 * self.cutborder_x, frame_size[1] - 2 * self.cutborder_y
- return revised_frame
- def get_exclusion_mask_2D(self, frame_size):
- """
- returns a boolean 2D array with True for pixels that are to be retained and False for those that are to be cut
- :param frame_size: tuple of size 2
- :return: boolean numpy ndarray of shape `frame_size`
- """
- mask = np.ones(frame_size, dtype=bool)
- mask[
- self.cutborder_x: frame_size[0] - self.cutborder_x,
- self.cutborder_y: frame_size[1] - self.cutborder_y
- ] = False
- return mask
- class Excluder3D(Excluder2D):
- def __init__(self, mv_FirstFrame=0, mv_LastFrame=0, cutborder_x=0, cutborder_y=0):
- super().__init__(cutborder_x=cutborder_x, cutborder_y=cutborder_y)
- # invalid first frame defaults to first frame
- self.t_slice_start = mv_FirstFrame if mv_FirstFrame >= 0 else 0
- # invalid last frame defaults to None, which will later be interpreted as the last frame of the movie
- self.t_slice_end = mv_LastFrame + 1 if mv_LastFrame > 0 else None
- def check_revise_framecut(self, movie_size):
- # default to end of movie if slice end is None
- t_slice_end = movie_size[2] if self.t_slice_end is None else self.t_slice_end
- t_slice_start = np.clip(self.t_slice_start, 0, movie_size[2])
- t_slice_end = np.clip(t_slice_end, 0, movie_size[2])
- if t_slice_start >= t_slice_end:
- raise ValueError(f"Specified values for mv_FirstFrame and mv_LastFrame are not valid for movie_data of size"
- f"{movie_size}. Please check!")
- return t_slice_start, t_slice_end
- def exclude_from_movie(self, movie_data: np.ndarray):
- """
- Returns an XYT numpy array with data along X, Y and T axes excluded
- :param movie_data: numpy.ndarray, in XYT format
- :return: numpy.ndarray
- """
- self.check_if_cutborder_too_large(movie_data.shape[:2])
- t_slice_start, t_slice_end = self.check_revise_framecut(movie_data.shape)
- return movie_data[self.cutborder_x: movie_data.shape[0] - self.cutborder_x,
- self.cutborder_y: movie_data.shape[1] - self.cutborder_y,
- t_slice_start: t_slice_end]
- def revise_movie_size(self, movie_size):
- """
- Revises frame size by excluding pixels along X, Y and T
- :param movie_size: tuple of size 3
- :return: tuple of size 3
- """
- revised_frame_size = self.revise_frame_size(movie_size[:2])
- revised_frame_start_end = self.revised_frame_start_end(movie_size)
- revised_frame_count = revised_frame_start_end[1] - revised_frame_start_end[0] + 1
- return revised_frame_size[0], revised_frame_size[1], revised_frame_count
- def revised_frame_start_end(self, movie_size):
- """
- Returns the first frame and last frame retained after exclusion as a tuple
- :param movie_size: tuple of size 3
- :return: tuple of size 2
- """
- slice_start, slice_end = self.check_revise_framecut(movie_size)
- return slice_start + 1, slice_end
|