def _create_file_and_symlinks(self, begin, end, cam_id, extension=''): begin_dt = to_datetime(begin) end_dt = to_datetime(end) def spans_multiple_directories(first_ts, end_dt): return self._path_for_dt(first_ts) != \ self._path_for_dt(end_dt) fname = self._get_filename(begin_dt, end_dt, cam_id, extension) _mkdir_p(os.path.dirname(fname)) if not os.path.exists(fname): open(fname, 'a').close() iter_ts = end symlinks = [] while spans_multiple_directories(begin_dt, iter_ts): path = self._path_for_dt(iter_ts) link_fname = self._get_filename(begin_dt, end, cam_id, extension, path) symlinks.append(link_fname) link_dir = os.path.dirname(link_fname) _mkdir_p(link_dir) rel_goal = os.path.relpath(fname, start=link_dir) os.symlink(rel_goal, link_fname) iter_path = self._step_one_directory(iter_ts, 'backward') iter_ts = self._get_time_from_path(iter_path) return fname, symlinks
def find_by_ts(self, ts, cam_id=None): """Return all video file paths that belong to the `ts`. Args: ts (datetime): timestamp to search for. cam_id (int): camera id to search for. Returns: list(string): paths of video files. """ # TODO(gitmirgut): Check if 20min is to big and if its also needed for time near 23:59.. dt = bbb_p.to_datetime(ts) paths = self._paths_for_dt_cam(dt, cam_id, abs=True) # check if time is near 0 hour, to get paths from the day before. time_delta = datetime.timedelta(minutes=20) shift_time = dt - time_delta if shift_time.day != dt.day: # TODO(gitmirgut): Change it to append. paths = paths + self._paths_for_dt_cam(shift_time, cam_id, abs=True) video_paths = [] for path in paths: fnames = self._all_videos_in(path) fname_parts = [(f, bbb_p.parse_video_fname(f)) for f in fnames] for fname, (camId, begin, end) in fname_parts: if begin <= dt < end: video_paths.append(os.path.join(path, fname)) # TODO(gitmirgut): insert breake return video_paths
def find_closest_videos(self, ts, cam_id, abs=False): """Return closest videos to the given timestamp. If the timestamp is contained in a video interval, then the returned list consists only of this video. If the timestamp is outside of video intervals, the list contains two videos, which are around that timestamp. Args: ts (datetime): timestamp to search for. cam_id (int): camera id to search for. Returns: list(string): paths of video files. """ # TODO(gitmirgut): Check if 20min is to big and if its also needed for time near 23:59.. dt = bbb_p.to_datetime(ts) paths = [self._path_for_dt_cam(dt, cam_id, abs=True)] # check if time is near 0 hour, to get paths from the day before. time_delta = datetime.timedelta(minutes=20) shift_time = dt - time_delta print('time') print(dt) print(shift_time) if shift_time.day != dt.day: paths.append(self._path_for_dt_cam(shift_time, cam_id, abs)) shift_time = dt + time_delta if shift_time.day != dt.day: paths.append(self._path_for_dt_cam(shift_time, cam_id, abs)) paths.sort() prev = None succ = None for path in paths: fnames = self._all_videos_in(path) fnames.sort() fnames_parts = [(f, bbb_p.parse_video_fname(f)) for f in fnames] for fname, (camId, begin, end) in fnames_parts: if begin <= ts < end: ret = fname if abs: return [os.path.join(path, ret)] else: return [ret] elif end < ts: prev = fname elif ts < begin: succ = fname if abs: return [os.path.join(path, prev), os.path.join(path, succ)] else: return [prev, succ]
def _path_for_dt(self, time, abs=False): dt = to_datetime(time) minutes = int( math.floor(dt.minute / self.minute_step) * self.minute_step) values = (dt.year, dt.month, dt.day, dt.hour, minutes) format_parts = list( map(lambda t: t[0].format(t[1]), zip(self._DIR_FORMAT_PARTS, values))) if abs: return self._join_with_repo_dir(*format_parts) else: return os.path.join(*format_parts)
def _step_one_directory(self, path, direction='forward'): if type(path) == str: dt = self._get_time_from_path(path) else: dt = to_datetime(path) offset = timedelta(minutes=self.minute_step) if direction == 'forward': dt += offset elif direction == 'backward': dt -= offset else: raise ValueError("Unknown direction {}.".format(direction)) return self._path_for_dt(dt)
def find(self, ts, cam=None): """ Returns all files that includes detections to the given timestamp `ts`. TODO: UTC timestamps! Generall """ dt = to_datetime(ts) path = self._path_for_dt(dt) if not os.path.exists(self._join_with_repo_dir(path)): return [] fnames = self._all_files_in(path) fnames_parts = [(f, self._parse_repo_fname(f)) for f in fnames] if cam is not None: fnames_parts = list( filter(lambda f, p: p[CAM_IDX] == cam, fnames_parts)) found_files = [] for fname, (camId, begin, end) in fnames_parts: if begin <= dt < end: found_files.append(self._join_with_repo_dir(path, fname)) return found_files
def _path_for_dt_cam(self, ts, cam_id, abs=False): """Return the directory path of videos to the given timestamp. Args: ts (datetime): Timestamp to search for. cam_id (int): Camera id to search for. abs (bool): If *True* returns the absolute path to the directory. Returns: string: path of the directory """ dt = bbb_p.to_datetime(ts) if cam_id not in self.valid_cam_ids: raise ValueError("Unknown camera id {cam_id}.".format(cam_id=cam_id)) # TODO(gitmirgut) is this possible for videos of 2015? Mabye the day folders are in Berlin # style and not in ISO8601 style format = self.dir_format.format(dt=dt, cam_id=cam_id) if abs: return os.path.join(self.root_dir, format) else: return format
def iter_fnames(self, begin=None, end=None, cam=None): """ Returns a generator that yields filenames in sorted order. From `begin` to `end`. Args: begin (Optional timestamp): The first filename contains at least one frame with a timestamp greater or equal to `begin`. If `begin` is not set, it will start with the earliest file. end (Optional timestamp): The last filename contains at least one frame with a timestamp smaller then `end`. If not set, it will continue until the last file. cam (Optional int): Only yield filenames with this cam id. Example: .. code:: Files: A B C D E Frames: |-----|-----|-----| |-----|-----| ⬆ ⬆ begin end This should return the files A, B and C. If `begin` and `end` are `None`, then all will be yield. """ def remove_links(directory, fnames): assert os.path.isdir(directory) assert os.path.isabs(directory) return list( filter( lambda f: not os.path.islink(os.path.join(directory, f)), fnames)) if begin is None: current_path = self._get_earliest_path() begin = pytz.utc.localize(datetime.min) else: begin = to_datetime(begin) current_path = self._path_for_dt(begin, abs=True) # if the repository is empty, current_path is the root_dir if current_path == self.root_dir: return if end is None: end_dir = self._get_latest_path() end = pytz.utc.localize(datetime.max) else: end = to_datetime(end) end_dir = self._path_for_dt(end, abs=True) iter_range = TimeInterval(begin, end) first_directory = True while True: fnames = self._all_files_in(current_path) if not first_directory: fnames = remove_links(current_path, fnames) else: first_directory = False parsed_fname = [self._parse_repo_fname(f) for f in fnames] cam_id_begin_end_fnames = [ (c, b, e, f) for (c, b, e), f in zip(parsed_fname, fnames) ] if cam is not None: cam_id_begin_end_fnames = list( filter(lambda p: p[CAM_IDX] == cam, cam_id_begin_end_fnames)) cam_id_begin_end_fnames.sort(key=lambda p: p[BEGIN_IDX]) for cam_idx, begin_ts, end_ts, fname in cam_id_begin_end_fnames: if iter_range.in_interval(begin_ts) or iter_range.in_interval( end_ts): yield self._join_with_repo_dir(current_path, fname) if end_dir == current_path: break else: current_path = self._step_to_next_directory( current_path, direction='forward') current_path = self._join_with_repo_dir(current_path)