From 340e1be94ccacd9c2432f33a9376a36c02e4db5c Mon Sep 17 00:00:00 2001 From: Ziv Lazarov Date: Sun, 19 Apr 2026 06:12:10 -0400 Subject: [PATCH 1/2] chore: simplify dependency constraints --- pyproject.toml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 98987a5..544cc1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ readme = "README.md" requires-python = ">=3.11" dependencies = [ "pose-format>=0.8.1", - "numpy<2", + "numpy", "pympi-ling", "torch", "pose-anonymization", @@ -20,12 +20,7 @@ dependencies = [ [project.optional-dependencies] dgs = [ - "sign_language_datasets", - "tensorflow<2.19", - "tensorflow-datasets==4.9.2", - "pyarrow", # transitive: tensorflow-datasets needs it at import time "lxml", - "webvtt-py", # transitive: sign_language_datasets eagerly imports mediapi_skel ] platform = [ "httpx", From e25e6019006281952e0426026b6447e45fef9bc4 Mon Sep 17 00:00:00 2001 From: Ziv Lazarov Date: Sun, 19 Apr 2026 06:14:02 -0400 Subject: [PATCH 2/2] refactor: replace DGS dataset helper imports --- .../datasets/dgs/dataset.py | 18 +---- .../datasets/dgs/utils.py | 78 +++++++++++++++++++ 2 files changed, 82 insertions(+), 14 deletions(-) create mode 100644 sign_language_segmentation/datasets/dgs/utils.py diff --git a/sign_language_segmentation/datasets/dgs/dataset.py b/sign_language_segmentation/datasets/dgs/dataset.py index b576efb..74cf9ee 100644 --- a/sign_language_segmentation/datasets/dgs/dataset.py +++ b/sign_language_segmentation/datasets/dgs/dataset.py @@ -7,25 +7,15 @@ from pose_format import Pose from pose_format.pose_body import EmptyPoseBody -# shim: sign_language_datasets imports get_dl_dirname which was renamed in tfds >=4.9 -import tensorflow_datasets.core.download.resource as _tfds_resource -if not hasattr(_tfds_resource, "get_dl_dirname"): - _tfds_resource.get_dl_dirname = _tfds_resource.get_dl_fname - -from sign_language_datasets.datasets.dgs_corpus.dgs_utils import get_elan_sentences - +from sign_language_segmentation.datasets.dgs.utils import ( + get_elan_sentences, + is_joke, +) from sign_language_segmentation.datasets.common import CACHE_DIR, BaseSegmentationDataset, Split, md5sum EXCLUDED_IDS: set[str] = {"1289910", "1245887", "1289868", "1246064", "1584617"} -def is_joke(corpus_dir: Path, doc_id: str) -> bool: - cmdi_path = corpus_dir / "videos" / doc_id / "data.cmdi" - if not cmdi_path.exists(): - return False - return "Joke" in cmdi_path.read_text() - - class DGSSegmentationDataset(BaseSegmentationDataset): """reads DGS corpus poses on the fly with efficient partial reading.""" diff --git a/sign_language_segmentation/datasets/dgs/utils.py b/sign_language_segmentation/datasets/dgs/utils.py new file mode 100644 index 0000000..3041281 --- /dev/null +++ b/sign_language_segmentation/datasets/dgs/utils.py @@ -0,0 +1,78 @@ +import pympi +from pathlib import Path + +def is_joke(corpus_dir: Path, doc_id: str) -> bool: + cmdi_path = corpus_dir / "videos" / doc_id / "data.cmdi" + if not cmdi_path.exists(): + return False + return "Joke" in cmdi_path.read_text() + +def get_elan_sentences(elan_path: str): + eaf = pympi.Elan.Eaf(elan_path) # TODO add "suppress_version_warning=True" when pympi 1.7 is released + + timeslots = eaf.timeslots + + for participant in ["A", "B"]: + german_tier_name = "Deutsche_Übersetzung_" + participant + if german_tier_name not in eaf.tiers: + continue + + german_text = eaf.tiers[german_tier_name][0] + + english_tier_name = "Translation_into_English_" + participant + english_text = list(eaf.tiers[english_tier_name][0].values()) if english_tier_name in eaf.tiers else [] + + all_glosses = [] + for hand in ["r", "l"]: + hand_tier = "Lexem_Gebärde_" + hand + "_" + participant + if hand_tier not in eaf.tiers: + continue + + gloss = { + _id: {"start": timeslots[s], "end": timeslots[e], "gloss": val, "hand": hand} + for _id, (s, e, val, _) in eaf.tiers[hand_tier][0].items() + } + for tier in ["Lexeme_Sign", "Gebärde", "Sign"]: + items = eaf.tiers[tier + "_" + hand + "_" + participant][1] + for ref, val, _1, _2 in items.values(): + if ref in gloss: # 2 files have a missing reference + gloss[ref][tier] = val + + all_glosses += list(gloss.values()) + + all_mouthings = [] + + tier_name = "Mundbild_Mundgestik_" + participant + items = eaf.tiers[tier_name][0] + + # structure of entries: + # {'a2768296': ('ts42', 'ts43', 'tochter', None), ... } + + for s, e, val, _ in items.values(): + mouthing_entry = {"start": timeslots[s], "end": timeslots[e], "mouthing": val} + all_mouthings.append(mouthing_entry) + + for _id, (s, e, val, _) in german_text.items(): + sentence = {"id": _id, "participant": participant, "start": timeslots[s], "end": timeslots[e], "german": val} + + # Add English sentence + english_sentence = [val2 for (s2, e2, val2, _) in english_text if s == s2 and e == e2] + sentence["english"] = english_sentence[0] if len(english_sentence) > 0 else None + + # Add glosses + sentence["glosses"] = list( + sorted( + [item for item in all_glosses if item["start"] >= sentence["start"] and item["end"] <= sentence["end"]], + key=lambda d: d["start"], + ) + ) + + # add mouthings + sentence["mouthings"] = list( + sorted( + [item for item in all_mouthings if item["start"] >= sentence["start"] and item["end"] <= sentence["end"]], + key=lambda d: d["start"], + ) + ) + + yield sentence \ No newline at end of file