Source code for epic_kitchens.meta

import pandas as pd
import numpy as np
from collections import namedtuple

from epic_kitchens.internal.loading import AnnotationRepository

from pathlib import Path
from typing import Union, Set, List, Tuple, Iterable
from logging import getLogger

_LOG = getLogger(__name__)

_annotation_repositories = {"v1.5.0": AnnotationRepository()}
_annotation_repository = _annotation_repositories["v1.5.0"]

ActionClass = namedtuple("ActionClass", ["verb_class", "noun_class"])
Action = namedtuple("Action", ["verb", "noun"])

_NOUN_CLASS_COUNT = 352


[docs]def set_version(version: str): global _annotation_repository, _annotation_repositories if version not in _annotation_repositories: _annotation_repositories[version] = AnnotationRepository( version=version, local_dir=_annotation_repository.local_dir ) _annotation_repository = _annotation_repositories[version]
[docs]def set_datadir(dir_: Union[str, Path]): """Set download directory Args: dir_: Path to directory in which to store all downloaded metadata files """ _annotation_repository.local_dir = Path(dir_) _LOG.info("Setting data directory to {}".format(dir_))
[docs]def get_datadir() -> Path: """ Returns: Directory under which any downloaded files are stored, defaults to current working directory """ return _annotation_repository.local_dir
[docs]def verb_to_class(verb: str) -> int: """ Args: verb: A noun from a narration Returns: The corresponding numeric class of the verb if it exists Raises: IndexError: If the verb doesn't belong to any of the verb classes """ return _annotation_repository.inverse_verb_lookup()[verb]
[docs]def noun_to_class(noun: str) -> int: """ Args: noun: A noun from a narration Returns: The corresponding numeric class of the noun if it exists Raises: IndexError: If the noun doesn't belong to any of the noun classes """ return _annotation_repository.inverse_noun_lookup()[noun]
[docs]def class_to_verb(cls: int) -> str: """ Args: cls: numeric verb class Returns: Canonical verb representing the class Raises: IndexError: if ``cls`` is an invalid verb class """ return _annotation_repository.verb_classes()["class_key"].loc[cls]
[docs]def class_to_noun(cls: int) -> str: """ Args: cls: numeric noun class Returns: Canonical noun representing the class Raises: IndexError: if ``cls`` is an invalid noun class """ return _annotation_repository.noun_classes()["class_key"].loc[cls]
[docs]def action_tuples_to_ids(action_classes: Iterable[ActionClass]) -> List[int]: """Convert a list of action classes composed of a verb and noun class to a dense action id using the formula: :math:`c_v * 352 + c_n` Args: action_classes: Returns: action_ids """ return [action_id_from_verb_noun(verb, noun) for verb, noun in action_classes]
[docs]def action_id_from_verb_noun( verb: Union[int, np.ndarray], noun: Union[int, np.ndarray] ) -> Union[int, np.ndarray]: """Map a verb and noun id to a dense action id. Examples: >>> action_id_from_verb_noun(0, 0) 0 >>> action_id_from_verb_noun(0, 1) 1 >>> action_id_from_verb_noun(0, 351) 351 >>> action_id_from_verb_noun(1, 0) 352 >>> action_id_from_verb_noun(1, 1) 353 >>> action_id_from_verb_noun(np.array([0, 1, 2]), np.array([0, 1, 2])) array([ 0, 353, 706]) """ return verb * _NOUN_CLASS_COUNT + noun
[docs]def noun_id_from_action_id(action: Union[int, np.ndarray]) -> Union[int, np.ndarray]: """Decode action id to verb id. Examples: >>> noun_id_from_action_id(0) 0 >>> noun_id_from_action_id(1) 1 >>> noun_id_from_action_id(351) 351 >>> noun_id_from_action_id(352) 0 >>> noun_id_from_action_id(353) 1 >>> noun_id_from_action_id(352 + 351) 351 >>> noun_id_from_action_id(np.array([0, 1, 353])) array([0, 1, 1]) """ return np.mod(action, _NOUN_CLASS_COUNT)
[docs]def verb_id_from_action_id(action_id: Union[int, np.ndarray]) -> Union[int, np.ndarray]: """Decode action id to noun id. Args: action_id: Either a single action id, or a :py:class:`np.ndarray` of action ids. Examples: >>> verb_id_from_action_id(0) 0 >>> verb_id_from_action_id(1) 0 >>> verb_id_from_action_id(352) 1 >>> verb_id_from_action_id(353) 1 >>> verb_id_from_action_id(np.array([0, 352, 1, 353])) array([0, 1, 0, 1]) """ return np.floor(action_id / _NOUN_CLASS_COUNT).astype("int")
[docs]def noun_classes() -> pd.DataFrame: """ Get dataframe containing the mapping between numeric noun classes, the canonical noun of that class and nouns clustered into the class. Returns: Dataframe with the columns: .. include:: meta/noun_classes.rst """ return _annotation_repository.noun_classes().copy()
[docs]def verb_classes() -> pd.DataFrame: """ Get dataframe containing the mapping between numeric verb classes, the canonical verb of that class and verbs clustered into the class. Returns: Dataframe with the columns .. include:: meta/verb_classes.rst """ return _annotation_repository.verb_classes().copy()
[docs]def many_shot_verbs() -> Set[int]: """ Returns: The set of verb classes that are many shot (appear more than 100 times in training). """ return set(_annotation_repository.many_shot_verbs())
[docs]def many_shot_nouns() -> Set[int]: """ Returns: The set of noun classes that are many shot (appear more than 100 times in training). """ return set(_annotation_repository.many_shot_nouns())
[docs]def many_shot_actions() -> Set[ActionClass]: """ Returns: The set of actions classes that are many shot (verb_class appears more than 100 times in training, noun_class appears more than 100 times in training, and the action appears at least once in training). """ return set(_annotation_repository.many_shot_actions())
[docs]def is_many_shot_action(action_class: ActionClass) -> bool: """ Args: action_class: ``(verb_class, noun_class)`` tuple Returns: Whether action_class is many shot or not """ return action_class in _annotation_repository.many_shot_actions()
[docs]def is_many_shot_verb(verb_class: int) -> bool: """ Args: verb_class: numeric verb class Returns: Whether verb_class is many shot or not """ return verb_class in _annotation_repository.many_shot_verbs()
[docs]def is_many_shot_noun(noun_class: int) -> bool: """ Args: noun_class: numeric noun class Returns: Whether noun class is many shot or not """ return noun_class in _annotation_repository.many_shot_nouns()
[docs]def training_narrations() -> pd.DataFrame: """ Returns: Dataframe with the columns .. include:: meta/train_action_narrations.rst """ return _annotation_repository.train_action_narrations()
[docs]def training_labels() -> pd.DataFrame: """ Returns: Dataframe with the columns .. include:: meta/train_action_labels.rst """ return _annotation_repository.train_action_labels().copy()
[docs]def training_object_labels() -> pd.DataFrame: """ Returns: Dataframe with the columns .. include:: meta/train_object_labels.rst """ return _annotation_repository.train_object_labels().copy()
[docs]def test_timestamps(split: str) -> pd.DataFrame: """ Args: split: 'seen', 'unseen', or 'all' (loads both with a 'split' Returns: Dataframe with the columns .. include:: meta/test_timestamps.rst """ if split == "all": return pd.concat( [ _annotation_repository.test_seen_timestamps(), _annotation_repository.test_unseen_timestamps(), ] ) if split == "seen": return _annotation_repository.test_seen_timestamps().copy() elif split == "unseen": return _annotation_repository.test_unseen_timestamps() raise ValueError("Unknown split '{}' expected 'seen' or 'unseen'".format(split))
[docs]def video_descriptions() -> pd.DataFrame: """ Returns: High level description of the task trying to be accomplished in a video. .. include:: meta/video_descriptions.rst """ return _annotation_repository.video_descriptions().copy()
[docs]def video_info() -> pd.DataFrame: """ Returns: Technical information stating the resolution, duration and FPS of each video. .. include:: meta/video_info.rst """ return _annotation_repository.video_info().copy()