Source code for visiannot.tools.ToolsAnnotation

# -*- coding: utf-8 -*-
#
# Copyright Université Rennes 1 / INSERM
# Contributor: Raphael Weber
#
# Under CeCILL license
# http://www.cecill.info

"""
Module with functions for loading ViSiAnnoT event annotation files
"""


import numpy as np
from os.path import isfile
from .ToolsData import convertIntervalsToTimeSeries


[docs]def readAnnotation(path, delimiter=" - "): """ Reads an annotation file :param path: path of the annotation file :type path: str :param delimiter: delimiter used to split each line of the annotation file in columns :type delimiter: str :returns: array of shape :math:`(n,2)` where the first column is the start time of the annotation and the second column is the end time of the annotation, or shape :math:`(0,2)` if empty annotation :rtype: numpy array """ annot_array = np.loadtxt(path, dtype=str, delimiter=delimiter, ndmin=2) if annot_array.shape[0] == 0: annot_array = np.empty((0, 2), dtype=str) return annot_array
[docs]def addElement(dic, key, element): """ Appends an element to a list in a dictionary where each value is a list :param dic: input dictionary :type dic: dict :param key: key to the list to append :type key: any type that the key might be :param element: element to append If ``key`` does not exist in ``dic``, then it is created and the value is initialized with ``[element]``. """ if key not in dic.keys(): dic[key] = [] dic[key].append(element)
[docs]def readAnnotFrames(path, nb_files=-1, delimiter=" - "): """ Reads an annotation file in format vid-id_frame-id as a list of lists of intervals in frame number Each element of the output list corresponds to one video (or signal) file. This element is a list of lists with the annotation intervals in frame number contained in this file (it can be an empty list if there are no annotations in this file). If an annotation interval spans several files, then the last end frame is set to -1 to specify that the annotation interval continues after the file. :param path: path to the annotation file in the format vid-id_frame-id :type path: str :param nb_files: number of files in the annotated recording, set to ``-1`` to ignore :type nb_files: int :param delimiter: delimiter used to split each line of the annotation file in columns :type delimiter: str :returns: list of lists of lists or empty list if file does not exist :rtype: list Example:: nb_files = 12 Annotation file 1_40 - 1_150 1_151 - 2_300 5_2 - 5_230 5_250 - 5_300 5_305 - 5_600 6_10 - 8_50 Output list [[], [[40, 150], [151, -1]], [[0, 300]], [], [], [[2, 230], [250, 300], [305, 600]], [[10, -1]], [[0, -1]], [[0, 50]], [], [], []] """ # initialize output dictionary result_dict = {} # check if file exists if isfile(path): # read file line-wise annot_array = readAnnotation(path, delimiter=delimiter) # loop on annotation lines for annot_0, annot_1 in annot_array: # read line vid_0 = int(annot_0.split("_")[0]) frame_0 = int(annot_0.split("_")[1]) vid_1 = int(annot_1.split("_")[0]) frame_1 = int(annot_1.split("_")[1]) # check if annotation spans several if vid_1 > vid_0: addElement(result_dict, vid_0, [frame_0, -1]) for vid_id in range(vid_0 + 1, vid_1): addElement(result_dict, vid_id, [0, -1]) addElement(result_dict, vid_1, [0, frame_1]) else: addElement(result_dict, vid_0, [frame_0, frame_1]) # get maximum video id if len(result_dict) > 0: max_vid_id = max(result_dict.keys()) else: max_vid_id = -1 # convert output dictionary to list result_list = [] for vid_id in range(max_vid_id + 1): if vid_id in result_dict.keys(): result_list.append(result_dict[vid_id]) else: result_list.append([]) # check number of files in the annotated recording if nb_files > 0: result_list += [[] for i in range(nb_files - len(result_list))] return result_list
[docs]def convertAnnotArray( annot_path, nb_frames_list, fps, ref_fps=25, flag_invert=False ): """ Loads an annotation file as a time series of 0 and 1 :param annot_path: path to the annotation file :type annot_path: str :param nb_frames_list: list with number of frames in each file of the annotated recording :type nb_frames_list: list :param fps: output frequency, must be below or equal to ``ref_fps`` :type fps: int or float :param ref_fps: frequency of the annotated signal :type ref_fps: int or float :param flag_invert: Specify if 0 and 1 must be inverted in the output signal :type flag_invert: bool :returns: 1D numpy array with the annotation as a time series of 0 and 1 :rtype: numpy array """ # compute factor between predictions frame rate and video frame rate factor = int(ref_fps / fps) # initialize annotation array output_array = np.array([]) # get annotation intervals annot_list_list = readAnnotFrames(annot_path, nb_files=len(nb_frames_list)) # loop on intervals for inter_list, nb_frames in zip(annot_list_list, nb_frames_list): # get annotation as a time series annot = convertIntervalsToTimeSeries(inter_list, nb_frames) # downsample to output fps output_array = np.concatenate((output_array, annot[::factor])) # invert 0 and 1 if flag_invert: output_array = -output_array + 1 return output_array