-
Notifications
You must be signed in to change notification settings - Fork 30
Edit video events in the timeline #1677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 41 commits
Commits
Show all changes
44 commits
Select commit
Hold shift + click to select a range
d211bce
Add TemporalSpan model
horatiualmasan 0c66a38
update
horatiualmasan 3e04899
fix
horatiualmasan bd48016
try eager load
horatiualmasan f668678
fix warning
horatiualmasan f3956d1
Add video annotation from activitynet
horatiualmasan 07ddf00
remove not needed joins
horatiualmasan 37441f5
Merge branch 'horatiu-lig-9805-import-activitynet-style-event-annotat…
horatiualmasan ebe86db
simplify
horatiualmasan 84a4063
Merge branch 'main' into horatiu-lig-9805-import-activitynet-style-ev…
horatiualmasan 47ec651
fix merge
horatiualmasan 9f97a84
add example sctipt
horatiualmasan d95200c
format
horatiualmasan 6a243bd
update
horatiualmasan 1a24532
Merge branch 'main' into horatiu-lig-9805-import-activitynet-style-ev…
horatiualmasan d32cbe4
Consider also own annotations for video filter
horatiualmasan 3acc186
Merge branch 'horatiu-lig-9805-import-activitynet-style-event-annotat…
horatiualmasan bdc02d2
fix merge error
horatiualmasan a9d31fd
Add useVideoPlayback hook with tests
horatiualmasan 5a07a5b
Wire custom control bar into VideoPlayer
horatiualmasan ebad55a
Use custom player in VideoDetails with deep-link start time
horatiualmasan 1d6d5ae
Add presentation-only VideoControls component
horatiualmasan 2cdba41
format
horatiualmasan 9f287db
Add Storybook stories for VideoControls
horatiualmasan 2dc2a47
Add useVideoPlayback hook with tests
horatiualmasan 7dede03
Wire custom control bar into VideoPlayer
horatiualmasan ecef795
Use custom player in VideoDetails with deep-link start time
horatiualmasan e2a18ce
format
horatiualmasan 8395952
fix error in test stub
horatiualmasan f8ef40d
Merge branch 'horatiu-lig-9807-show-event-bars-on-the-timeline.d' of …
horatiualmasan 0f2b999
Add video event model (toVideoEvents, assignEventLanes)
horatiualmasan 8e2426e
Add VideoEventTimeline component
horatiualmasan cdbf3e5
Wire event bar into VideoPlayer, VideoControls and VideoDetails
horatiualmasan 717ebf2
add AnnotationType.CLASSIFICATION
horatiualmasan b8ada23
Merge branch 'horatiu-lig-9807-show-event-bars-on-the-timeline-3-even…
horatiualmasan becf8d5
Merge branch 'horatiu-lig-9807-show-event-bars-on-the-timeline-3-even…
horatiualmasan 21d02b9
update
horatiualmasan c56018e
Merge branch 'horatiu-lig-9807-show-event-bars-on-the-timeline-3-even…
horatiualmasan 78259f4
Edit video events in the timeline
horatiualmasan 52da034
fix
horatiualmasan d80d259
Merge branch 'main' into horatiu-lig-10189-edit-events
LeonardoRosaa 9196b5f
log and show error message
LeonardoRosaa 6a7bdfa
raise value error if start_time_s or end_time_s are not provided
LeonardoRosaa 3ed9e89
format files
LeonardoRosaa File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
lightly_studio/src/lightly_studio/resolvers/annotation_resolver/update_temporal_span.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| """Module for updating the temporal span (start/end time) of an annotation.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from uuid import UUID | ||
|
|
||
| from sqlmodel import Session | ||
|
|
||
| from lightly_studio.models.annotation.annotation_base import AnnotationBaseTable | ||
| from lightly_studio.resolvers import annotation_resolver | ||
|
|
||
|
|
||
| def update_temporal_span( | ||
| session: Session, | ||
| annotation_id: UUID, | ||
| start_time_s: float, | ||
| end_time_s: float, | ||
| ) -> AnnotationBaseTable: | ||
| """Update the temporal span of an annotation. | ||
|
|
||
| Args: | ||
| session: Database session for executing the operation. | ||
| annotation_id: UUID of the annotation to update. | ||
| start_time_s: New start time in seconds. | ||
| end_time_s: New end time in seconds. | ||
|
|
||
| Returns: | ||
| The updated annotation with the new temporal span. | ||
|
|
||
| Raises: | ||
| ValueError: If the annotation is not found, has no temporal span, or the | ||
| span is invalid. | ||
| """ | ||
| if start_time_s < 0: | ||
| raise ValueError("start_time_s must be non-negative.") | ||
| if start_time_s >= end_time_s: | ||
| raise ValueError("start_time_s must be less than end_time_s.") | ||
|
|
||
| annotation = annotation_resolver.get_by_id(session=session, annotation_id=annotation_id) | ||
| if not annotation: | ||
| raise ValueError(f"Annotation with ID {annotation_id} not found.") | ||
| if annotation.temporal_span_details is None: | ||
| raise ValueError("Annotation does not have a temporal span to update.") | ||
|
|
||
| try: | ||
| annotation.temporal_span_details.start_time_s = start_time_s | ||
| annotation.temporal_span_details.end_time_s = end_time_s | ||
| session.add(annotation.temporal_span_details) | ||
| session.commit() | ||
| session.refresh(annotation) | ||
| return annotation | ||
| except Exception: | ||
| session.rollback() | ||
| raise |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
lightly_studio/src/lightly_studio/services/annotations_service/update_temporal_span.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| """Update the temporal span (start/end time) of an annotation.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from uuid import UUID | ||
|
|
||
| from sqlmodel import Session | ||
|
|
||
| from lightly_studio.models.annotation.annotation_base import AnnotationBaseTable | ||
| from lightly_studio.resolvers import annotation_resolver | ||
|
|
||
|
|
||
| def update_temporal_span( | ||
| session: Session, | ||
| annotation_id: UUID, | ||
| start_time_s: float, | ||
| end_time_s: float, | ||
| ) -> AnnotationBaseTable: | ||
| """Retrieve an annotation by its ID and update its temporal span. | ||
|
|
||
| Args: | ||
| session: Database session. | ||
| annotation_id: The annotation ID to update. | ||
| start_time_s: The new start time in seconds. | ||
| end_time_s: The new end time in seconds. | ||
|
|
||
| Returns: | ||
| The updated AnnotationBaseTable instance. | ||
| """ | ||
| return annotation_resolver.update_temporal_span( | ||
| session=session, | ||
| annotation_id=annotation_id, | ||
| start_time_s=start_time_s, | ||
| end_time_s=end_time_s, | ||
| ) |
118 changes: 118 additions & 0 deletions
118
lightly_studio/tests/resolvers/annotations/test_update_temporal_span.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| """Tests for updating the temporal span of an annotation.""" | ||
|
|
||
| from uuid import UUID | ||
|
|
||
| import pytest | ||
| from sqlmodel import Session | ||
|
|
||
| from lightly_studio.models.annotation.annotation_base import ( | ||
| AnnotationCreate, | ||
| AnnotationType, | ||
| ) | ||
| from lightly_studio.models.collection import SampleType | ||
| from lightly_studio.resolvers import annotation_resolver | ||
| from tests.helpers_resolvers import create_annotation_label, create_collection, create_image | ||
|
|
||
|
|
||
| def _create_event_annotation( | ||
| db_session: Session, | ||
| collection_id: UUID, | ||
| start_time_s: float, | ||
| end_time_s: float, | ||
| ) -> UUID: | ||
| label = create_annotation_label( | ||
| session=db_session, root_collection_id=collection_id, label_name="event" | ||
| ) | ||
| image = create_image( | ||
| session=db_session, | ||
| collection_id=collection_id, | ||
| file_path_abs="/path/to/sample.png", | ||
| ) | ||
| return annotation_resolver.create_many( | ||
| session=db_session, | ||
| parent_collection_id=collection_id, | ||
| annotations=[ | ||
| AnnotationCreate( | ||
| parent_sample_id=image.sample_id, | ||
| annotation_label_id=label.annotation_label_id, | ||
| annotation_type=AnnotationType.CLASSIFICATION, | ||
| start_time_s=start_time_s, | ||
| end_time_s=end_time_s, | ||
| ) | ||
| ], | ||
| )[0] | ||
|
|
||
|
|
||
| def test_update_temporal_span(db_session: Session) -> None: | ||
| collection = create_collection(session=db_session, sample_type=SampleType.IMAGE) | ||
| collection_id = collection.collection_id | ||
|
|
||
| annotation_id = _create_event_annotation( | ||
| db_session, collection_id, start_time_s=1.0, end_time_s=5.0 | ||
| ) | ||
|
|
||
| annotation = annotation_resolver.update_temporal_span( | ||
| session=db_session, | ||
| annotation_id=annotation_id, | ||
| start_time_s=2.5, | ||
| end_time_s=8.0, | ||
| ) | ||
|
|
||
| assert annotation.sample_id == annotation_id | ||
| assert annotation.temporal_span_details is not None | ||
| assert annotation.temporal_span_details.start_time_s == 2.5 | ||
| assert annotation.temporal_span_details.end_time_s == 8.0 | ||
|
|
||
|
|
||
| def test_update_temporal_span__rejects_inverted_span(db_session: Session) -> None: | ||
| collection = create_collection(session=db_session, sample_type=SampleType.IMAGE) | ||
| collection_id = collection.collection_id | ||
|
|
||
| annotation_id = _create_event_annotation( | ||
| db_session, collection_id, start_time_s=1.0, end_time_s=5.0 | ||
| ) | ||
|
|
||
| with pytest.raises(ValueError, match=r"start_time_s must be less than end_time_s."): | ||
| annotation_resolver.update_temporal_span( | ||
| session=db_session, | ||
| annotation_id=annotation_id, | ||
| start_time_s=6.0, | ||
| end_time_s=5.0, | ||
| ) | ||
|
|
||
|
|
||
| def test_update_temporal_span__annotation_without_span(db_session: Session) -> None: | ||
| collection = create_collection(session=db_session, sample_type=SampleType.IMAGE) | ||
| collection_id = collection.collection_id | ||
|
|
||
| label = create_annotation_label( | ||
| session=db_session, root_collection_id=collection_id, label_name="car" | ||
| ) | ||
| image = create_image( | ||
| session=db_session, | ||
| collection_id=collection_id, | ||
| file_path_abs="/path/to/sample.png", | ||
| ) | ||
| annotation_id = annotation_resolver.create_many( | ||
| session=db_session, | ||
| parent_collection_id=collection_id, | ||
| annotations=[ | ||
| AnnotationCreate( | ||
| parent_sample_id=image.sample_id, | ||
| annotation_label_id=label.annotation_label_id, | ||
| annotation_type=AnnotationType.OBJECT_DETECTION, | ||
| x=10, | ||
| y=10, | ||
| width=20, | ||
| height=20, | ||
| ) | ||
| ], | ||
| )[0] | ||
|
|
||
| with pytest.raises(ValueError, match=r"does not have a temporal span"): | ||
| annotation_resolver.update_temporal_span( | ||
| session=db_session, | ||
| annotation_id=annotation_id, | ||
| start_time_s=1.0, | ||
| end_time_s=2.0, | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.