lightly-studio 0.4.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lightly_studio/__init__.py +12 -0
- lightly_studio/api/__init__.py +0 -0
- lightly_studio/api/app.py +131 -0
- lightly_studio/api/cache.py +77 -0
- lightly_studio/api/db_tables.py +35 -0
- lightly_studio/api/features.py +5 -0
- lightly_studio/api/routes/api/annotation.py +305 -0
- lightly_studio/api/routes/api/annotation_label.py +87 -0
- lightly_studio/api/routes/api/annotations/__init__.py +7 -0
- lightly_studio/api/routes/api/annotations/create_annotation.py +52 -0
- lightly_studio/api/routes/api/caption.py +100 -0
- lightly_studio/api/routes/api/classifier.py +384 -0
- lightly_studio/api/routes/api/dataset.py +191 -0
- lightly_studio/api/routes/api/dataset_tag.py +266 -0
- lightly_studio/api/routes/api/embeddings2d.py +90 -0
- lightly_studio/api/routes/api/exceptions.py +114 -0
- lightly_studio/api/routes/api/export.py +114 -0
- lightly_studio/api/routes/api/features.py +17 -0
- lightly_studio/api/routes/api/frame.py +241 -0
- lightly_studio/api/routes/api/image.py +155 -0
- lightly_studio/api/routes/api/metadata.py +161 -0
- lightly_studio/api/routes/api/operator.py +75 -0
- lightly_studio/api/routes/api/sample.py +103 -0
- lightly_studio/api/routes/api/selection.py +87 -0
- lightly_studio/api/routes/api/settings.py +41 -0
- lightly_studio/api/routes/api/status.py +19 -0
- lightly_studio/api/routes/api/text_embedding.py +50 -0
- lightly_studio/api/routes/api/validators.py +17 -0
- lightly_studio/api/routes/api/video.py +133 -0
- lightly_studio/api/routes/healthz.py +13 -0
- lightly_studio/api/routes/images.py +104 -0
- lightly_studio/api/routes/video_frames_media.py +116 -0
- lightly_studio/api/routes/video_media.py +223 -0
- lightly_studio/api/routes/webapp.py +51 -0
- lightly_studio/api/server.py +94 -0
- lightly_studio/core/__init__.py +0 -0
- lightly_studio/core/add_samples.py +533 -0
- lightly_studio/core/add_videos.py +294 -0
- lightly_studio/core/dataset.py +780 -0
- lightly_studio/core/dataset_query/__init__.py +14 -0
- lightly_studio/core/dataset_query/boolean_expression.py +67 -0
- lightly_studio/core/dataset_query/dataset_query.py +317 -0
- lightly_studio/core/dataset_query/field.py +113 -0
- lightly_studio/core/dataset_query/field_expression.py +79 -0
- lightly_studio/core/dataset_query/match_expression.py +23 -0
- lightly_studio/core/dataset_query/order_by.py +79 -0
- lightly_studio/core/dataset_query/sample_field.py +37 -0
- lightly_studio/core/dataset_query/tags_expression.py +46 -0
- lightly_studio/core/image_sample.py +36 -0
- lightly_studio/core/loading_log.py +56 -0
- lightly_studio/core/sample.py +291 -0
- lightly_studio/core/start_gui.py +54 -0
- lightly_studio/core/video_sample.py +38 -0
- lightly_studio/dataset/__init__.py +0 -0
- lightly_studio/dataset/edge_embedding_generator.py +155 -0
- lightly_studio/dataset/embedding_generator.py +129 -0
- lightly_studio/dataset/embedding_manager.py +349 -0
- lightly_studio/dataset/env.py +20 -0
- lightly_studio/dataset/file_utils.py +49 -0
- lightly_studio/dataset/fsspec_lister.py +275 -0
- lightly_studio/dataset/mobileclip_embedding_generator.py +158 -0
- lightly_studio/dataset/perception_encoder_embedding_generator.py +260 -0
- lightly_studio/db_manager.py +166 -0
- lightly_studio/dist_lightly_studio_view_app/_app/env.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/0.GcXvs2l7.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/12.Dx6SXgAb.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/17.9X9_k6TP.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/18.BxiimdIO.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/2.CkOblLn7.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/ClassifierSamplesGrid.BJbCDlvs.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/LightlyLogo.BNjCIww-.png +0 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Bold.DGvYQtcs.ttf +0 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Italic-VariableFont_wdth_wght.B4AZ-wl6.ttf +0 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Medium.DVUZMR_6.ttf +0 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-Regular.DxJTClRG.ttf +0 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-SemiBold.D3TTYgdB.ttf +0 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/OpenSans-VariableFont_wdth_wght.BZBpG5Iz.ttf +0 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_layout.CefECEWA.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_layout.D5tDcjY-.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_page.9X9_k6TP.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_page.BxiimdIO.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_page.Dx6SXgAb.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/transform._-1mPSEI.css +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/0dDyq72A.js +20 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/69_IOA4Y.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BK4An2kI.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BRmB-kJ9.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/B_1cpokE.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BiqpDEr0.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BpLiSKgx.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BscxbINH.js +39 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/C1FmrZbK.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/C80h3dJx.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/C8mfFM-u.js +2 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CGY1p9L4.js +517 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/COfLknXM.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CWj6FrbW.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CYgJF_JY.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CmLg0ys7.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CvGjimpO.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D3RDXHoj.js +39 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D4y7iiT3.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D9SC3jBb.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DCuAdx1Q.js +20 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DDBy-_jD.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DIeogL5L.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DL9a7v5o.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DSKECuqX.js +39 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/D_FFv0Oe.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DiZ5o5vz.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DkbXUtyG.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DmK2hulV.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DqnHaLTj.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DtWZc_tl.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DuUalyFS.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DwIonDAZ.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/Il-mSPmK.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/KNLP4aJU.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/KjYeVjkE.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/MErlcOXj.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/VRI4prUD.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/VYb2dkNs.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/VqWvU2yF.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/dHC3otuL.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/da7Oy_lO.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/eAy8rZzC.js +2 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/erjNR5MX.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/f1oG3eFE.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/rsLi1iKv.js +20 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/rwuuBP9f.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/xGHZQ1pe.js +3 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/entry/app.DrTRUgT3.js +2 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/entry/start.BK5EOJl2.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/0.CIvTuljF.js +4 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/1.UBvSzxdA.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/10.CQ_tiLJa.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/11.KqkAcaxW.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/12.DoYsmxQc.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/13.571n2LZA.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/14.DGs689M-.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/15.CWG1ehzT.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/16.Dpq6jbSh.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/17.B5AZbHUU.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/18.CBga8cnq.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/2.D2HXgz-8.js +1090 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/3.f4HAg-y3.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/4.BKF4xuKQ.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/5.BAE0Pm_f.js +39 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/6.CouWWpzA.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/7.UBHT0ktp.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/8.FiYNElcc.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/9.B3-UaT23.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/workers/clustering.worker-DKqeLtG0.js +2 -0
- lightly_studio/dist_lightly_studio_view_app/_app/immutable/workers/search.worker-vNSty3B0.js +1 -0
- lightly_studio/dist_lightly_studio_view_app/_app/version.json +1 -0
- lightly_studio/dist_lightly_studio_view_app/apple-touch-icon-precomposed.png +0 -0
- lightly_studio/dist_lightly_studio_view_app/apple-touch-icon.png +0 -0
- lightly_studio/dist_lightly_studio_view_app/favicon.png +0 -0
- lightly_studio/dist_lightly_studio_view_app/index.html +45 -0
- lightly_studio/errors.py +5 -0
- lightly_studio/examples/example.py +25 -0
- lightly_studio/examples/example_coco.py +27 -0
- lightly_studio/examples/example_coco_caption.py +29 -0
- lightly_studio/examples/example_metadata.py +369 -0
- lightly_studio/examples/example_operators.py +111 -0
- lightly_studio/examples/example_selection.py +28 -0
- lightly_studio/examples/example_split_work.py +48 -0
- lightly_studio/examples/example_video.py +22 -0
- lightly_studio/examples/example_video_annotations.py +157 -0
- lightly_studio/examples/example_yolo.py +22 -0
- lightly_studio/export/coco_captions.py +69 -0
- lightly_studio/export/export_dataset.py +104 -0
- lightly_studio/export/lightly_studio_label_input.py +120 -0
- lightly_studio/export_schema.py +18 -0
- lightly_studio/export_version.py +57 -0
- lightly_studio/few_shot_classifier/__init__.py +0 -0
- lightly_studio/few_shot_classifier/classifier.py +80 -0
- lightly_studio/few_shot_classifier/classifier_manager.py +644 -0
- lightly_studio/few_shot_classifier/random_forest_classifier.py +495 -0
- lightly_studio/metadata/complex_metadata.py +47 -0
- lightly_studio/metadata/compute_similarity.py +84 -0
- lightly_studio/metadata/compute_typicality.py +67 -0
- lightly_studio/metadata/gps_coordinate.py +41 -0
- lightly_studio/metadata/metadata_protocol.py +17 -0
- lightly_studio/models/__init__.py +1 -0
- lightly_studio/models/annotation/__init__.py +0 -0
- lightly_studio/models/annotation/annotation_base.py +303 -0
- lightly_studio/models/annotation/instance_segmentation.py +56 -0
- lightly_studio/models/annotation/links.py +17 -0
- lightly_studio/models/annotation/object_detection.py +47 -0
- lightly_studio/models/annotation/semantic_segmentation.py +44 -0
- lightly_studio/models/annotation_label.py +47 -0
- lightly_studio/models/caption.py +49 -0
- lightly_studio/models/classifier.py +20 -0
- lightly_studio/models/dataset.py +70 -0
- lightly_studio/models/embedding_model.py +30 -0
- lightly_studio/models/image.py +96 -0
- lightly_studio/models/metadata.py +208 -0
- lightly_studio/models/range.py +17 -0
- lightly_studio/models/sample.py +154 -0
- lightly_studio/models/sample_embedding.py +36 -0
- lightly_studio/models/settings.py +69 -0
- lightly_studio/models/tag.py +96 -0
- lightly_studio/models/two_dim_embedding.py +16 -0
- lightly_studio/models/video.py +161 -0
- lightly_studio/plugins/__init__.py +0 -0
- lightly_studio/plugins/base_operator.py +60 -0
- lightly_studio/plugins/operator_registry.py +47 -0
- lightly_studio/plugins/parameter.py +70 -0
- lightly_studio/py.typed +0 -0
- lightly_studio/resolvers/__init__.py +0 -0
- lightly_studio/resolvers/annotation_label_resolver/__init__.py +22 -0
- lightly_studio/resolvers/annotation_label_resolver/create.py +27 -0
- lightly_studio/resolvers/annotation_label_resolver/delete.py +28 -0
- lightly_studio/resolvers/annotation_label_resolver/get_all.py +37 -0
- lightly_studio/resolvers/annotation_label_resolver/get_by_id.py +24 -0
- lightly_studio/resolvers/annotation_label_resolver/get_by_ids.py +25 -0
- lightly_studio/resolvers/annotation_label_resolver/get_by_label_name.py +24 -0
- lightly_studio/resolvers/annotation_label_resolver/names_by_ids.py +25 -0
- lightly_studio/resolvers/annotation_label_resolver/update.py +38 -0
- lightly_studio/resolvers/annotation_resolver/__init__.py +40 -0
- lightly_studio/resolvers/annotation_resolver/count_annotations_by_dataset.py +129 -0
- lightly_studio/resolvers/annotation_resolver/create_many.py +124 -0
- lightly_studio/resolvers/annotation_resolver/delete_annotation.py +87 -0
- lightly_studio/resolvers/annotation_resolver/delete_annotations.py +60 -0
- lightly_studio/resolvers/annotation_resolver/get_all.py +85 -0
- lightly_studio/resolvers/annotation_resolver/get_all_with_payload.py +179 -0
- lightly_studio/resolvers/annotation_resolver/get_by_id.py +34 -0
- lightly_studio/resolvers/annotation_resolver/get_by_id_with_payload.py +130 -0
- lightly_studio/resolvers/annotation_resolver/update_annotation_label.py +142 -0
- lightly_studio/resolvers/annotation_resolver/update_bounding_box.py +68 -0
- lightly_studio/resolvers/annotations/__init__.py +1 -0
- lightly_studio/resolvers/annotations/annotations_filter.py +88 -0
- lightly_studio/resolvers/caption_resolver.py +129 -0
- lightly_studio/resolvers/dataset_resolver/__init__.py +55 -0
- lightly_studio/resolvers/dataset_resolver/check_dataset_type.py +29 -0
- lightly_studio/resolvers/dataset_resolver/create.py +20 -0
- lightly_studio/resolvers/dataset_resolver/delete.py +20 -0
- lightly_studio/resolvers/dataset_resolver/export.py +267 -0
- lightly_studio/resolvers/dataset_resolver/get_all.py +19 -0
- lightly_studio/resolvers/dataset_resolver/get_by_id.py +16 -0
- lightly_studio/resolvers/dataset_resolver/get_by_name.py +12 -0
- lightly_studio/resolvers/dataset_resolver/get_dataset_details.py +27 -0
- lightly_studio/resolvers/dataset_resolver/get_hierarchy.py +31 -0
- lightly_studio/resolvers/dataset_resolver/get_or_create_child_dataset.py +58 -0
- lightly_studio/resolvers/dataset_resolver/get_parent_dataset_by_sample_id.py +27 -0
- lightly_studio/resolvers/dataset_resolver/get_parent_dataset_id.py +22 -0
- lightly_studio/resolvers/dataset_resolver/get_root_dataset.py +61 -0
- lightly_studio/resolvers/dataset_resolver/get_root_datasets_overview.py +41 -0
- lightly_studio/resolvers/dataset_resolver/update.py +25 -0
- lightly_studio/resolvers/embedding_model_resolver.py +120 -0
- lightly_studio/resolvers/image_filter.py +50 -0
- lightly_studio/resolvers/image_resolver/__init__.py +21 -0
- lightly_studio/resolvers/image_resolver/create_many.py +52 -0
- lightly_studio/resolvers/image_resolver/delete.py +20 -0
- lightly_studio/resolvers/image_resolver/filter_new_paths.py +23 -0
- lightly_studio/resolvers/image_resolver/get_all_by_dataset_id.py +117 -0
- lightly_studio/resolvers/image_resolver/get_by_id.py +14 -0
- lightly_studio/resolvers/image_resolver/get_dimension_bounds.py +75 -0
- lightly_studio/resolvers/image_resolver/get_many_by_id.py +22 -0
- lightly_studio/resolvers/image_resolver/get_samples_excluding.py +43 -0
- lightly_studio/resolvers/metadata_resolver/__init__.py +15 -0
- lightly_studio/resolvers/metadata_resolver/metadata_filter.py +163 -0
- lightly_studio/resolvers/metadata_resolver/sample/__init__.py +21 -0
- lightly_studio/resolvers/metadata_resolver/sample/bulk_update_metadata.py +46 -0
- lightly_studio/resolvers/metadata_resolver/sample/get_by_sample_id.py +24 -0
- lightly_studio/resolvers/metadata_resolver/sample/get_metadata_info.py +104 -0
- lightly_studio/resolvers/metadata_resolver/sample/get_value_for_sample.py +27 -0
- lightly_studio/resolvers/metadata_resolver/sample/set_value_for_sample.py +53 -0
- lightly_studio/resolvers/sample_embedding_resolver.py +132 -0
- lightly_studio/resolvers/sample_resolver/__init__.py +17 -0
- lightly_studio/resolvers/sample_resolver/count_by_dataset_id.py +16 -0
- lightly_studio/resolvers/sample_resolver/create.py +16 -0
- lightly_studio/resolvers/sample_resolver/create_many.py +25 -0
- lightly_studio/resolvers/sample_resolver/get_by_id.py +14 -0
- lightly_studio/resolvers/sample_resolver/get_filtered_samples.py +56 -0
- lightly_studio/resolvers/sample_resolver/get_many_by_id.py +22 -0
- lightly_studio/resolvers/sample_resolver/sample_filter.py +74 -0
- lightly_studio/resolvers/settings_resolver.py +62 -0
- lightly_studio/resolvers/tag_resolver.py +299 -0
- lightly_studio/resolvers/twodim_embedding_resolver.py +119 -0
- lightly_studio/resolvers/video_frame_resolver/__init__.py +23 -0
- lightly_studio/resolvers/video_frame_resolver/count_video_frames_annotations.py +83 -0
- lightly_studio/resolvers/video_frame_resolver/create_many.py +57 -0
- lightly_studio/resolvers/video_frame_resolver/get_all_by_dataset_id.py +63 -0
- lightly_studio/resolvers/video_frame_resolver/get_by_id.py +13 -0
- lightly_studio/resolvers/video_frame_resolver/get_table_fields_bounds.py +44 -0
- lightly_studio/resolvers/video_frame_resolver/video_frame_annotations_counter_filter.py +47 -0
- lightly_studio/resolvers/video_frame_resolver/video_frame_filter.py +57 -0
- lightly_studio/resolvers/video_resolver/__init__.py +27 -0
- lightly_studio/resolvers/video_resolver/count_video_frame_annotations_by_video_dataset.py +86 -0
- lightly_studio/resolvers/video_resolver/create_many.py +58 -0
- lightly_studio/resolvers/video_resolver/filter_new_paths.py +33 -0
- lightly_studio/resolvers/video_resolver/get_all_by_dataset_id.py +181 -0
- lightly_studio/resolvers/video_resolver/get_by_id.py +22 -0
- lightly_studio/resolvers/video_resolver/get_table_fields_bounds.py +72 -0
- lightly_studio/resolvers/video_resolver/get_view_by_id.py +52 -0
- lightly_studio/resolvers/video_resolver/video_count_annotations_filter.py +50 -0
- lightly_studio/resolvers/video_resolver/video_filter.py +98 -0
- lightly_studio/selection/__init__.py +1 -0
- lightly_studio/selection/mundig.py +143 -0
- lightly_studio/selection/select.py +203 -0
- lightly_studio/selection/select_via_db.py +273 -0
- lightly_studio/selection/selection_config.py +49 -0
- lightly_studio/services/annotations_service/__init__.py +33 -0
- lightly_studio/services/annotations_service/create_annotation.py +64 -0
- lightly_studio/services/annotations_service/delete_annotation.py +22 -0
- lightly_studio/services/annotations_service/get_annotation_by_id.py +31 -0
- lightly_studio/services/annotations_service/update_annotation.py +54 -0
- lightly_studio/services/annotations_service/update_annotation_bounding_box.py +36 -0
- lightly_studio/services/annotations_service/update_annotation_label.py +48 -0
- lightly_studio/services/annotations_service/update_annotations.py +29 -0
- lightly_studio/setup_logging.py +59 -0
- lightly_studio/type_definitions.py +31 -0
- lightly_studio/utils/__init__.py +3 -0
- lightly_studio/utils/download.py +94 -0
- lightly_studio/vendor/__init__.py +1 -0
- lightly_studio/vendor/mobileclip/ACKNOWLEDGEMENTS +422 -0
- lightly_studio/vendor/mobileclip/LICENSE +31 -0
- lightly_studio/vendor/mobileclip/LICENSE_weights_data +50 -0
- lightly_studio/vendor/mobileclip/README.md +5 -0
- lightly_studio/vendor/mobileclip/__init__.py +96 -0
- lightly_studio/vendor/mobileclip/clip.py +77 -0
- lightly_studio/vendor/mobileclip/configs/mobileclip_b.json +18 -0
- lightly_studio/vendor/mobileclip/configs/mobileclip_s0.json +18 -0
- lightly_studio/vendor/mobileclip/configs/mobileclip_s1.json +18 -0
- lightly_studio/vendor/mobileclip/configs/mobileclip_s2.json +18 -0
- lightly_studio/vendor/mobileclip/image_encoder.py +67 -0
- lightly_studio/vendor/mobileclip/logger.py +154 -0
- lightly_studio/vendor/mobileclip/models/__init__.py +10 -0
- lightly_studio/vendor/mobileclip/models/mci.py +933 -0
- lightly_studio/vendor/mobileclip/models/vit.py +433 -0
- lightly_studio/vendor/mobileclip/modules/__init__.py +4 -0
- lightly_studio/vendor/mobileclip/modules/common/__init__.py +4 -0
- lightly_studio/vendor/mobileclip/modules/common/mobileone.py +341 -0
- lightly_studio/vendor/mobileclip/modules/common/transformer.py +451 -0
- lightly_studio/vendor/mobileclip/modules/image/__init__.py +4 -0
- lightly_studio/vendor/mobileclip/modules/image/image_projection.py +113 -0
- lightly_studio/vendor/mobileclip/modules/image/replknet.py +188 -0
- lightly_studio/vendor/mobileclip/modules/text/__init__.py +4 -0
- lightly_studio/vendor/mobileclip/modules/text/repmixer.py +281 -0
- lightly_studio/vendor/mobileclip/modules/text/tokenizer.py +38 -0
- lightly_studio/vendor/mobileclip/text_encoder.py +245 -0
- lightly_studio/vendor/perception_encoder/LICENSE.PE +201 -0
- lightly_studio/vendor/perception_encoder/README.md +11 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/__init__.py +0 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/bpe_simple_vocab_16e6.txt.gz +0 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/config.py +205 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/config_src.py +264 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/pe.py +766 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/rope.py +352 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/tokenizer.py +347 -0
- lightly_studio/vendor/perception_encoder/vision_encoder/transforms.py +36 -0
- lightly_studio-0.4.6.dist-info/METADATA +88 -0
- lightly_studio-0.4.6.dist-info/RECORD +356 -0
- lightly_studio-0.4.6.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
"""Functions to add videos to a dataset in the database."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import os
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Iterable, cast
|
|
10
|
+
from uuid import UUID
|
|
11
|
+
|
|
12
|
+
import av
|
|
13
|
+
import fsspec
|
|
14
|
+
import numpy as np
|
|
15
|
+
from av import FFmpegError, container
|
|
16
|
+
from av.codec.context import ThreadType
|
|
17
|
+
from av.container import InputContainer
|
|
18
|
+
from av.video.frame import VideoFrame as AVVideoFrame
|
|
19
|
+
from av.video.stream import VideoStream
|
|
20
|
+
from sqlmodel import Session
|
|
21
|
+
from tqdm import tqdm
|
|
22
|
+
|
|
23
|
+
from lightly_studio.core import loading_log
|
|
24
|
+
from lightly_studio.models.dataset import SampleType
|
|
25
|
+
from lightly_studio.models.video import VideoCreate, VideoFrameCreate
|
|
26
|
+
from lightly_studio.resolvers import (
|
|
27
|
+
dataset_resolver,
|
|
28
|
+
sample_resolver,
|
|
29
|
+
video_frame_resolver,
|
|
30
|
+
video_resolver,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
logger = logging.getLogger(__name__)
|
|
34
|
+
|
|
35
|
+
DEFAULT_VIDEO_CHANNEL = 0
|
|
36
|
+
# Number of samples to process in a single batch
|
|
37
|
+
SAMPLE_BATCH_SIZE = 128
|
|
38
|
+
|
|
39
|
+
# Video file extensions
|
|
40
|
+
# These are commonly supported by PyAV/FFmpeg.
|
|
41
|
+
VIDEO_EXTENSIONS = {
|
|
42
|
+
".mp4",
|
|
43
|
+
".mov",
|
|
44
|
+
".avi",
|
|
45
|
+
".mkv",
|
|
46
|
+
".webm",
|
|
47
|
+
".flv",
|
|
48
|
+
".wmv",
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class FrameExtractionContext:
|
|
54
|
+
"""Lightweight container for the metadata needed during frame extraction."""
|
|
55
|
+
|
|
56
|
+
session: Session
|
|
57
|
+
dataset_id: UUID
|
|
58
|
+
video_sample_id: UUID
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def load_into_dataset_from_paths(
|
|
62
|
+
session: Session,
|
|
63
|
+
dataset_id: UUID,
|
|
64
|
+
video_paths: Iterable[str],
|
|
65
|
+
video_channel: int = DEFAULT_VIDEO_CHANNEL,
|
|
66
|
+
num_decode_threads: int | None = None,
|
|
67
|
+
) -> tuple[list[UUID], list[UUID]]:
|
|
68
|
+
"""Load video samples from file paths into the dataset using PyAV.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
session: The database session.
|
|
72
|
+
dataset_id: The ID of the dataset to load video samples into. It should have
|
|
73
|
+
sample_type == SampleType.VIDEO.
|
|
74
|
+
video_paths: An iterable of file paths to the videos to load.
|
|
75
|
+
video_channel: The video channel from which frames are loaded.
|
|
76
|
+
num_decode_threads: Optional override for the number of FFmpeg decode threads.
|
|
77
|
+
If omitted, the available CPU cores - 1 (max 16) are used.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
A tuple containing:
|
|
81
|
+
- List of UUIDs of the created video samples
|
|
82
|
+
- List of UUIDs of the created video frame samples
|
|
83
|
+
"""
|
|
84
|
+
created_video_sample_ids: list[UUID] = []
|
|
85
|
+
created_video_frame_sample_ids: list[UUID] = []
|
|
86
|
+
video_paths_list = list(video_paths)
|
|
87
|
+
file_paths_new, file_paths_exist = video_resolver.filter_new_paths(
|
|
88
|
+
session=session, file_paths_abs=video_paths_list
|
|
89
|
+
)
|
|
90
|
+
video_logging_context = loading_log.LoadingLoggingContext(
|
|
91
|
+
n_samples_to_be_inserted=len(video_paths_list),
|
|
92
|
+
n_samples_before_loading=sample_resolver.count_by_dataset_id(
|
|
93
|
+
session=session, dataset_id=dataset_id
|
|
94
|
+
),
|
|
95
|
+
)
|
|
96
|
+
video_logging_context.update_example_paths(file_paths_exist)
|
|
97
|
+
# Get the video frames dataset ID
|
|
98
|
+
video_frames_dataset_id = dataset_resolver.get_or_create_child_dataset(
|
|
99
|
+
session=session, dataset_id=dataset_id, sample_type=SampleType.VIDEO_FRAME
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
for video_path in tqdm(
|
|
103
|
+
file_paths_new,
|
|
104
|
+
desc="Loading frames from videos",
|
|
105
|
+
unit=" video",
|
|
106
|
+
):
|
|
107
|
+
try:
|
|
108
|
+
# Open video and extract metadata
|
|
109
|
+
fs, fs_path = fsspec.core.url_to_fs(url=video_path)
|
|
110
|
+
video_file = fs.open(path=fs_path, mode="rb")
|
|
111
|
+
try:
|
|
112
|
+
# Open video container for reading (returns InputContainer)
|
|
113
|
+
video_container = container.open(file=video_file)
|
|
114
|
+
video_stream = video_container.streams.video[video_channel]
|
|
115
|
+
|
|
116
|
+
# Get video metadata
|
|
117
|
+
framerate = float(video_stream.average_rate) or 0.0
|
|
118
|
+
video_width = video_stream.width or 0
|
|
119
|
+
video_height = video_stream.height or 0
|
|
120
|
+
if video_stream.duration and video_stream.time_base:
|
|
121
|
+
video_duration = float(video_stream.duration * video_stream.time_base)
|
|
122
|
+
else:
|
|
123
|
+
video_duration = None
|
|
124
|
+
|
|
125
|
+
# Create video sample
|
|
126
|
+
video_sample_ids = video_resolver.create_many(
|
|
127
|
+
session=session,
|
|
128
|
+
dataset_id=dataset_id,
|
|
129
|
+
samples=[
|
|
130
|
+
VideoCreate(
|
|
131
|
+
file_path_abs=video_path,
|
|
132
|
+
width=video_width,
|
|
133
|
+
height=video_height,
|
|
134
|
+
duration_s=video_duration,
|
|
135
|
+
fps=framerate,
|
|
136
|
+
file_name=Path(video_path).name,
|
|
137
|
+
)
|
|
138
|
+
],
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
if len(video_sample_ids) != 1:
|
|
142
|
+
video_container.close()
|
|
143
|
+
raise (RuntimeError(f"There was an error adding {video_path} to the dataset."))
|
|
144
|
+
created_video_sample_ids.append(video_sample_ids[0])
|
|
145
|
+
|
|
146
|
+
# Create video frame samples by parsing all frames
|
|
147
|
+
extraction_context = FrameExtractionContext(
|
|
148
|
+
session=session,
|
|
149
|
+
dataset_id=video_frames_dataset_id,
|
|
150
|
+
video_sample_id=video_sample_ids[0],
|
|
151
|
+
)
|
|
152
|
+
frame_sample_ids = _create_video_frame_samples(
|
|
153
|
+
context=extraction_context,
|
|
154
|
+
video_container=video_container,
|
|
155
|
+
video_channel=video_channel,
|
|
156
|
+
num_decode_threads=num_decode_threads,
|
|
157
|
+
)
|
|
158
|
+
created_video_frame_sample_ids.extend(frame_sample_ids)
|
|
159
|
+
|
|
160
|
+
video_container.close()
|
|
161
|
+
finally:
|
|
162
|
+
# Ensure file is closed even if container operations fail
|
|
163
|
+
video_file.close()
|
|
164
|
+
|
|
165
|
+
except (FileNotFoundError, OSError, IndexError, FFmpegError) as e:
|
|
166
|
+
logger.error(f"Error processing video {video_path}: {e}")
|
|
167
|
+
continue
|
|
168
|
+
|
|
169
|
+
loading_log.log_loading_results(
|
|
170
|
+
session=session, dataset_id=dataset_id, logging_context=video_logging_context
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
return created_video_sample_ids, created_video_frame_sample_ids
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _create_video_frame_samples(
|
|
177
|
+
context: FrameExtractionContext,
|
|
178
|
+
video_container: InputContainer,
|
|
179
|
+
video_channel: int,
|
|
180
|
+
num_decode_threads: int | None = None,
|
|
181
|
+
) -> list[UUID]:
|
|
182
|
+
"""Create video frame samples for a video by parsing all frames.
|
|
183
|
+
|
|
184
|
+
This function decodes all frames to extract metadata.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
context: Frame extraction context (session, dataset and parent video).
|
|
188
|
+
video_container: The PyAV container with the opened video.
|
|
189
|
+
video_channel: The video channel from which frames are loaded.
|
|
190
|
+
num_decode_threads: Optional override for FFmpeg decode thread count.
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
A list of UUIDs of the created video frame samples.
|
|
194
|
+
"""
|
|
195
|
+
created_sample_ids: list[UUID] = []
|
|
196
|
+
samples_to_create: list[VideoFrameCreate] = []
|
|
197
|
+
video_stream = video_container.streams.video[video_channel]
|
|
198
|
+
_configure_stream_threading(video_stream=video_stream, num_decode_threads=num_decode_threads)
|
|
199
|
+
|
|
200
|
+
# Get time base for converting PTS to seconds
|
|
201
|
+
time_base = video_stream.time_base if video_stream.time_base else None
|
|
202
|
+
|
|
203
|
+
# Decode all frames
|
|
204
|
+
for decoded_index, frame in enumerate(video_container.decode(video_stream)):
|
|
205
|
+
# Get the presentation timestamp in seconds from the frame
|
|
206
|
+
# Convert frame.pts from time base units to seconds
|
|
207
|
+
if frame.pts is not None and time_base is not None:
|
|
208
|
+
frame_timestamp_s = float(frame.pts * time_base)
|
|
209
|
+
else:
|
|
210
|
+
# Fallback to frame.time if pts or time_base is not available
|
|
211
|
+
frame_timestamp_s = frame.time if frame.time is not None else -1.0
|
|
212
|
+
|
|
213
|
+
sample = VideoFrameCreate(
|
|
214
|
+
frame_number=decoded_index,
|
|
215
|
+
frame_timestamp_s=frame_timestamp_s,
|
|
216
|
+
frame_timestamp_pts=frame.pts if frame.pts is not None else -1,
|
|
217
|
+
parent_sample_id=context.video_sample_id,
|
|
218
|
+
rotation_deg=_get_frame_rotation_deg(frame=frame),
|
|
219
|
+
)
|
|
220
|
+
samples_to_create.append(sample)
|
|
221
|
+
|
|
222
|
+
# Process batch when it reaches SAMPLE_BATCH_SIZE
|
|
223
|
+
if len(samples_to_create) >= SAMPLE_BATCH_SIZE:
|
|
224
|
+
created_samples_batch = video_frame_resolver.create_many(
|
|
225
|
+
session=context.session,
|
|
226
|
+
samples=samples_to_create,
|
|
227
|
+
dataset_id=context.dataset_id,
|
|
228
|
+
)
|
|
229
|
+
created_sample_ids.extend(created_samples_batch)
|
|
230
|
+
samples_to_create = []
|
|
231
|
+
|
|
232
|
+
# Handle remaining samples for this video
|
|
233
|
+
if samples_to_create:
|
|
234
|
+
created_samples_batch = video_frame_resolver.create_many(
|
|
235
|
+
session=context.session,
|
|
236
|
+
samples=samples_to_create,
|
|
237
|
+
dataset_id=context.dataset_id,
|
|
238
|
+
)
|
|
239
|
+
created_sample_ids.extend(created_samples_batch)
|
|
240
|
+
|
|
241
|
+
return created_sample_ids
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _configure_stream_threading(video_stream: VideoStream, num_decode_threads: int | None) -> None:
|
|
245
|
+
"""Configure codec-level threading for faster decode when available."""
|
|
246
|
+
codec_context = getattr(video_stream, "codec_context", None)
|
|
247
|
+
if codec_context is None:
|
|
248
|
+
return
|
|
249
|
+
|
|
250
|
+
if num_decode_threads is None:
|
|
251
|
+
cpu_count = os.cpu_count() or 1
|
|
252
|
+
# Use available cores - 1 but at least 1. Cap to prevent runaway usage.
|
|
253
|
+
num_decode_threads = max(1, min(cpu_count - 1 or 1, 16))
|
|
254
|
+
|
|
255
|
+
try:
|
|
256
|
+
codec_context.thread_type = ThreadType.AUTO
|
|
257
|
+
codec_context.thread_count = num_decode_threads
|
|
258
|
+
except av.AVError:
|
|
259
|
+
# Some codecs do not support threading—ignore silently.
|
|
260
|
+
logger.warning(
|
|
261
|
+
"Could not set up multithreading to decode videos, will use a single thread."
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _get_frame_rotation_deg(frame: AVVideoFrame) -> int:
|
|
266
|
+
"""Get the rotation metadata from a video frame.
|
|
267
|
+
|
|
268
|
+
Reads DISPLAYMATRIX side data to determine rotation.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
frame: A decoded video frame.
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
The rotation in degrees. Valid values are 0, 90, 180, 270.
|
|
275
|
+
"""
|
|
276
|
+
matrix_data = frame.side_data.get("DISPLAYMATRIX")
|
|
277
|
+
if matrix_data is None:
|
|
278
|
+
return 0
|
|
279
|
+
buffer = cast(bytes, matrix_data)
|
|
280
|
+
matrix = np.frombuffer(buffer=buffer, dtype=np.int32).reshape((3, 3))
|
|
281
|
+
|
|
282
|
+
# The top left 2x2 sub-matrix has four possible configurations. The rotation can be
|
|
283
|
+
# determined from the first two values.
|
|
284
|
+
#
|
|
285
|
+
# 0 90 180 270
|
|
286
|
+
# x 0 0 -x -x 0 0 x
|
|
287
|
+
# 0 x x 0 0 -x -x 0
|
|
288
|
+
if matrix[0, 0] > 0:
|
|
289
|
+
return 0
|
|
290
|
+
if matrix[0, 0] < 0:
|
|
291
|
+
return 180
|
|
292
|
+
if matrix[0, 1] < 0:
|
|
293
|
+
return 90
|
|
294
|
+
return 270
|