def load_from_csv(self, csv_file, reset_save_required=True): # type: (File [r], Optional[bool] -> int """ Load From CSV: Loads all metrics stored in a CSV file into the StatsManager instance. Arguments: csv_file: A file handle opened in read mode (e.g. open('...', 'r')). reset_save_required: If True, clears the flag indicating that a save is required. Returns: int or None: Number of frames/rows read from the CSV file, or None if the input file was blank. Raises: StatsFileCorrupt: Stats file is corrupt and can't be loaded, or wrong file was specified. """ csv_reader = get_csv_reader(csv_file) num_cols = None num_metrics = None num_frames = None # First Row: Frame Num, Timecode, [metrics...] try: row = next(csv_reader) # Backwards compatibility for previous versions of statsfile # which included an additional header row. if not self.valid_header(row): row = next(csv_reader) except StopIteration: # If the file is blank or we couldn't decode anything, assume the file was empty. return None if not self.valid_header(row): raise StatsFileCorrupt() num_cols = len(row) num_metrics = num_cols - 2 if not num_metrics > 0: raise StatsFileCorrupt('No metrics defined in CSV file.') self._loaded_metrics = row[2:] num_frames = 0 for row in csv_reader: metric_dict = {} if not len(row) == num_cols: raise StatsFileCorrupt( 'Wrong number of columns detected in stats file row.') for i, metric_str in enumerate(row[2:]): if metric_str and metric_str != 'None': try: metric_dict[self._loaded_metrics[i]] = float( metric_str) except ValueError: raise StatsFileCorrupt( 'Corrupted value in stats file: %s' % metric_str) self.set_metrics(int(row[0]), metric_dict) num_frames += 1 logger.info('Loaded %d metrics for %d frames.', num_metrics, num_frames) if reset_save_required: self._metrics_updated = False return num_frames
def test_load_empty_stats(): """ Test loading an empty stats file, ensuring it results in no errors. """ open(TEST_STATS_FILES[0], 'w').close() with open(TEST_STATS_FILES[0], 'r') as stats_file: stats_manager = StatsManager() stats_reader = get_csv_reader(stats_file) stats_manager.load_from_csv(stats_reader)
def test_load_empty_stats(test_video_file): """ Test loading an empty stats file, ensuring it results in no errors. """ try: stats_file = open(TEST_STATS_FILES[0], 'w') stats_file.close() stats_file = open(TEST_STATS_FILES[0], 'r') stats_manager = StatsManager() stats_reader = get_csv_reader(stats_file) stats_manager.load_from_csv(stats_reader) finally: stats_file.close() os.remove(TEST_STATS_FILES[0])
def load_from_csv(self, csv_file, base_timecode=None, reset_save_required=True): # type: (File [r], FrameTimecode, Optional[bool] -> int """ Load From CSV: Loads all metrics stored in a CSV file into the StatsManager instance. Arguments: csv_file: A file handle opened in read mode (e.g. open('...', 'r')). base_timecode: The base_timecode obtained from the frame source VideoManager. If using an OpenCV VideoCapture, create one using the video framerate by setting base_timecode=FrameTimecode(0, fps=video_framerate). If base_timecode is not set (i.e. is None), the framerate is not validated. reset_save_required: If True, clears the flag indicating that a save is required. Returns: int or None: Number of frames/rows read from the CSV file, or None if the input file was blank. Raises: StatsFileCorrupt: Stats file is corrupt and can't be loaded, or wrong file was specified. StatsFileFramerateMismatch: Framerate does not match the loaded stats file, indicating either the wrong video or wrong stats file was specified. """ csv_reader = get_csv_reader(csv_file) num_cols = None num_metrics = None num_frames = None # First row: Framerate, [video_framerate] try: row = next(csv_reader) except StopIteration: # If the file is blank or we couldn't decode anything, assume the file was empty. return num_frames # First Row (FPS = [...]) and ensure framerate equals base_timecode if set. if not len(row) == 2 or not row[0] == COLUMN_NAME_FPS: raise StatsFileCorrupt() stats_file_framerate = float(row[1]) if stats_file_framerate < MINIMUM_FRAMES_PER_SECOND_FLOAT: raise StatsFileCorrupt( "Invalid framerate detected in CSV stats file " "(decoded FPS: %f)." % stats_file_framerate) if base_timecode is not None and not base_timecode.equal_framerate( stats_file_framerate): raise StatsFileFramerateMismatch(base_timecode.get_framerate(), stats_file_framerate) # Second Row: Frame Num, Timecode, [metrics...] try: row = next(csv_reader) except StopIteration: raise StatsFileCorrupt("Header row(s) missing.") if not row or not len(row) >= 2: raise StatsFileCorrupt() if row[0] != COLUMN_NAME_FRAME_NUMBER or row[1] != COLUMN_NAME_TIMECODE: raise StatsFileCorrupt() num_cols = len(row) num_metrics = num_cols - 2 if not num_metrics > 0: raise StatsFileCorrupt('No metrics defined in CSV file.') metric_keys = row[2:] num_frames = 0 for row in csv_reader: metric_dict = {} if not len(row) == num_cols: raise StatsFileCorrupt( 'Wrong number of columns detected in stats file row.') for i, metric_str in enumerate(row[2:]): if metric_str and metric_str != 'None': try: metric_dict[metric_keys[i]] = float(metric_str) except ValueError: raise StatsFileCorrupt( 'Corrupted value in stats file: %s' % metric_str) self.set_metrics(int(row[0]), metric_dict) num_frames += 1 logging.info('Loaded %d metrics for %d frames.', num_metrics, num_frames) if reset_save_required: self._metrics_updated = False return num_frames
def load_from_csv(self, csv_file, base_timecode=None, reset_save_required=True): # type: (File [r], FrameTimecode, Optional[bool] -> int """ Load From CSV: Loads all metrics stored in a CSV file into the StatsManager instance. Arguments: csv_file: A file handle opened in read mode (e.g. open('...', 'r')). base_timecode: The base_timecode obtained from the frame source VideoManager. If using an OpenCV VideoCapture, create one using the video framerate by setting base_timecode=FrameTimecode(0, fps=video_framerate). If base_timecode is not set (i.e. is None), the framerate is not validated. reset_save_required: If True, clears the flag indicating that a save is required. Returns: int or None: Number of frames/rows read from the CSV file, or None if the input file was blank. Raises: StatsFileCorrupt: Stats file is corrupt and can't be loaded, or wrong file was specified. StatsFileFramerateMismatch: Framerate does not match the loaded stats file, indicating either the wrong video or wrong stats file was specified. """ csv_reader = get_csv_reader(csv_file) num_cols = None num_metrics = None num_frames = None # First row: Framerate, [video_framerate] try: row = next(csv_reader) except StopIteration: # If the file is blank or we couldn't decode anything, assume the file was empty. return num_frames # First Row (FPS = [...]) and ensure framerate equals base_timecode if set. if not len(row) == 2 or not row[0] == COLUMN_NAME_FPS: raise StatsFileCorrupt() stats_file_framerate = float(row[1]) if stats_file_framerate < MINIMUM_FRAMES_PER_SECOND_FLOAT: raise StatsFileCorrupt("Invalid framerate detected in CSV stats file " "(decoded FPS: %f)." % stats_file_framerate) if base_timecode is not None and not base_timecode.equal_framerate(stats_file_framerate): raise StatsFileFramerateMismatch(base_timecode.get_framerate(), stats_file_framerate) # Second Row: Frame Num, Timecode, [metrics...] try: row = next(csv_reader) except StopIteration: raise StatsFileCorrupt("Header row(s) missing.") if not row or not len(row) >= 2: raise StatsFileCorrupt() if row[0] != COLUMN_NAME_FRAME_NUMBER or row[1] != COLUMN_NAME_TIMECODE: raise StatsFileCorrupt() num_cols = len(row) num_metrics = num_cols - 2 if not num_metrics > 0: raise StatsFileCorrupt('No metrics defined in CSV file.') metric_keys = row[2:] num_frames = 0 for row in csv_reader: metric_dict = {} if not len(row) == num_cols: raise StatsFileCorrupt('Wrong number of columns detected in stats file row.') for i, metric_str in enumerate(row[2:]): if metric_str and metric_str != 'None': try: metric_dict[metric_keys[i]] = float(metric_str) except ValueError: raise StatsFileCorrupt('Corrupted value in stats file: %s' % metric_str) self.set_metrics(int(row[0]), metric_dict) num_frames += 1 logging.info('Loaded %d metrics for %d frames.', num_metrics, num_frames) if reset_save_required: self._metrics_updated = False return num_frames
def load_from_csv(self, csv_file, base_timecode=None, reset_save_required=True): # type: (File [r], Optional[FrameTimecode]) -> int csv_reader = get_csv_reader(csv_file) num_cols = None num_metrics = None num_frames = None # First row: Framerate, [video_framerate] try: row = next(csv_reader) except StopIteration: # If the file is blank or we couldn't decode anything, assume the file was empty. return # First Row (FPS = [...]) and ensure framerate equals base_timecode if set. if not len(row) == 2 or not row[0] == COLUMN_NAME_FPS: raise StatsFileCorrupt() stats_file_framerate = float(row[1]) if stats_file_framerate < MINIMUM_FRAMES_PER_SECOND_FLOAT: raise StatsFileCorrupt( "Invalid framerate detected in CSV stats file " "(decoded FPS: %f)." % stats_file_framerate) if base_timecode is not None and not base_timecode.equal_framerate( stats_file_framerate): raise StatsFileFramerateMismatch(base_timecode.get_framerate(), stats_file_framerate) # Second Row: Frame Num, Timecode, [metrics...] try: row = next(csv_reader) except StopIteration: raise StatsFileCorrupt("Header row(s) missing.") if not row or not len(row) >= 2: raise StatsFileCorrupt() if row[0] != COLUMN_NAME_FRAME_NUMBER or row[1] != COLUMN_NAME_TIMECODE: raise StatsFileCorrupt() num_cols = len(row) num_metrics = num_cols - 2 if not num_metrics > 0: raise StatsFileCorrupt('No metrics defined in CSV file.') metric_keys = row[2:] num_frames = 0 for row in csv_reader: metric_dict = {} if not len(row) == num_cols: raise StatsFileCorrupt( 'Wrong number of columns detected in stats file row.') for i, metric_str in enumerate(row[2:]): if metric_str and metric_str != 'None': try: metric_dict[metric_keys[i]] = float(metric_str) except ValueError: raise StatsFileCorrupt( 'Corrupted value in stats file: %s' % metric_str) self.set_metrics(int(row[0]), metric_dict) num_frames += 1 logging.info('Loaded %d metrics for %d frames.', num_metrics, num_frames) if reset_save_required: self._metrics_updated = False return num_frames