Source code for ethoscope.trackers.trackers

__author__ = 'quentin'

from collections import deque

from ethoscope.utils.description  import DescribedObject
from ethoscope.core.variables import *


[docs]class NoPositionError(Exception): """ Used to abort tracking. When it is raised within the ``_find_position`` method, data is inferred from previous position. """ pass
[docs]class BaseTracker(DescribedObject): # data_point = None def __init__(self, roi,data=None): """ Template class for video trackers. A video tracker locate animal in a ROI. Derived class must implement the ``_find_position`` method. :param roi: The Region Of Interest the the tracker will use to locate the animal. :type roi: :class:`~ethoscope.rois.roi_builders.ROI` :param data: An optional data set. For instance, it can be used for pre-trained algorithms :return: """ self._positions = deque() self._times =deque() self._data = data self._roi = roi self._last_non_inferred_time = 0 self._last_time_point = 0 self._max_history_length = 250 * 1000 # in milliseconds # self._max_history_length = 500 # in milliseconds # if self.data_point is None: # raise NotImplementedError("Trackers must have a DataPoint object.")
[docs] def track(self, t, img): """ Locate the animal in a image, at a given time. :param t: time in ms :type t: int :param img: the whole frame. :type img: :class:`~numpy.ndarray` :return: The position of the animal at time ``t`` :rtype: :class:`~ethoscope.core.data_point.DataPoint` """ sub_img, mask = self._roi.apply(img) self._last_time_point = t try: points = self._find_position(sub_img,mask,t) if not isinstance(points, list): raise Exception("tracking algorithms are expected to return a LIST of DataPoints") if len(points) ==0: return [] # point = self.normalise_position(point) self._last_non_inferred_time = t for p in points: p.append(IsInferredVariable(False)) except NoPositionError: if len(self._positions) == 0: return [] else: points = self._infer_position(t) if len(points) ==0: return [] for p in points: p.append(IsInferredVariable(True)) self._positions.append(points) self._times.append(t) if len(self._times) > 2 and (self._times[-1] - self._times[0]) > self._max_history_length: self._positions.popleft() self._times.popleft() return points
def _infer_position(self, t, max_time=30 * 1000): if len(self._times) == 0: return [] if t - self._last_non_inferred_time > max_time: return [] return self._positions[-1] @property def positions(self): """ :return: The last few positions found by the tracker.\ Positions are kept for a certain duration defined by the ``_max_history_length`` attribute. :rtype: :class:`~collection.deque` """ return self._positions
[docs] def xy_pos(self, i): return self._positions[i][0]
@property def last_time_point(self): """ :return: The last time point that the tracker used.\ This is updated even when position is inferred/no animal is found :rtype: int """ return self._last_time_point @property def times(self): """ :return: The last few time points corresponding to :class:`~ethoscope.trackers.trackers.BaseTracker.positions`. :rtype: :class:`~collection.deque` """ return self._times def _find_position(self,img, mask,t): raise NotImplementedError