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,111 @@
|
|
|
1
|
+
"""Example of how to register operators."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any
|
|
7
|
+
from uuid import UUID
|
|
8
|
+
|
|
9
|
+
from environs import Env
|
|
10
|
+
from sqlmodel import Session
|
|
11
|
+
|
|
12
|
+
import lightly_studio as ls
|
|
13
|
+
from lightly_studio import db_manager
|
|
14
|
+
from lightly_studio.plugins.base_operator import BaseOperator, OperatorResult
|
|
15
|
+
from lightly_studio.plugins.operator_registry import operator_registry
|
|
16
|
+
from lightly_studio.plugins.parameter import (
|
|
17
|
+
BaseParameter,
|
|
18
|
+
BoolParameter,
|
|
19
|
+
FloatParameter,
|
|
20
|
+
IntParameter,
|
|
21
|
+
StringParameter,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class TestOperator(BaseOperator):
|
|
27
|
+
"""Dummy Operator for demo purpose."""
|
|
28
|
+
|
|
29
|
+
name: str = "test operator"
|
|
30
|
+
description: str = "used to test the operator and registry system"
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def parameters(self) -> list[BaseParameter]:
|
|
34
|
+
"""Return the list of parameters this operator expects."""
|
|
35
|
+
return [
|
|
36
|
+
BoolParameter(name="test flag", required=True),
|
|
37
|
+
StringParameter(name="test str", required=True, default="Good Morning"),
|
|
38
|
+
StringParameter(
|
|
39
|
+
name="test str 2", required=True, default="Another", description="Test Description"
|
|
40
|
+
),
|
|
41
|
+
BoolParameter(
|
|
42
|
+
name="test flag 2", required=True, description="Test Description", default=True
|
|
43
|
+
),
|
|
44
|
+
FloatParameter(name="test float", required=False, default=2.0, description="abc"),
|
|
45
|
+
IntParameter(name="test int", required=False, default=2),
|
|
46
|
+
IntParameter(name="test int 2", required=True, description="Yet another int"),
|
|
47
|
+
IntParameter(
|
|
48
|
+
name="test int 3",
|
|
49
|
+
required=True,
|
|
50
|
+
description=(
|
|
51
|
+
"Yet another int with a very long description. this will show how we will "
|
|
52
|
+
"overflow or what soever is happening to this text in the GUI. maybe it "
|
|
53
|
+
"exceeds maybe not. only time will tell"
|
|
54
|
+
),
|
|
55
|
+
),
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
def execute(
|
|
59
|
+
self,
|
|
60
|
+
*,
|
|
61
|
+
session: Session,
|
|
62
|
+
dataset_id: UUID,
|
|
63
|
+
parameters: dict[str, Any],
|
|
64
|
+
) -> OperatorResult:
|
|
65
|
+
"""Execute the operator with the given parameters.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
session: Database session.
|
|
69
|
+
dataset_id: ID of the dataset to operate on.
|
|
70
|
+
parameters: Parameters passed to the operator.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Dictionary with 'success' (bool) and 'message' (str) keys.
|
|
74
|
+
"""
|
|
75
|
+
return OperatorResult(
|
|
76
|
+
success=bool(parameters.get("test flag")),
|
|
77
|
+
message=str(parameters.get("test str"))
|
|
78
|
+
+ " "
|
|
79
|
+
+ str(parameters.get("test str 2"))
|
|
80
|
+
+ " "
|
|
81
|
+
+ str(parameters.get("test flag 2"))
|
|
82
|
+
+ " "
|
|
83
|
+
+ str(parameters.get("test float"))
|
|
84
|
+
+ " "
|
|
85
|
+
+ str(parameters.get("test int"))
|
|
86
|
+
+ " "
|
|
87
|
+
+ str(dataset_id)
|
|
88
|
+
+ str(session),
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# Read environment variables
|
|
93
|
+
env = Env()
|
|
94
|
+
env.read_env()
|
|
95
|
+
|
|
96
|
+
# Cleanup an existing database
|
|
97
|
+
db_manager.connect(cleanup_existing=True)
|
|
98
|
+
|
|
99
|
+
# Setup dummy operators
|
|
100
|
+
test = TestOperator()
|
|
101
|
+
for i in range(20):
|
|
102
|
+
operator_registry.register(operator=TestOperator(name=f"test_{i}"))
|
|
103
|
+
|
|
104
|
+
# Define data path
|
|
105
|
+
dataset_path = env.path("EXAMPLES_DATASET_PATH", "/path/to/your/dataset")
|
|
106
|
+
|
|
107
|
+
# Create a DatasetLoader from a path
|
|
108
|
+
dataset = ls.Dataset.create()
|
|
109
|
+
dataset.add_images_from_path(path=dataset_path)
|
|
110
|
+
|
|
111
|
+
ls.start_gui()
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Example of how to run selection class."""
|
|
2
|
+
|
|
3
|
+
from environs import Env
|
|
4
|
+
|
|
5
|
+
import lightly_studio as ls
|
|
6
|
+
from lightly_studio import db_manager
|
|
7
|
+
|
|
8
|
+
# Read environment variables
|
|
9
|
+
env = Env()
|
|
10
|
+
env.read_env()
|
|
11
|
+
|
|
12
|
+
# Cleanup an existing database
|
|
13
|
+
db_manager.connect(cleanup_existing=True)
|
|
14
|
+
|
|
15
|
+
# Define the path to the dataset directory
|
|
16
|
+
dataset_path = env.path("EXAMPLES_DATASET_PATH", "/path/to/your/dataset")
|
|
17
|
+
|
|
18
|
+
# Create a Dataset from a path
|
|
19
|
+
dataset = ls.Dataset.create()
|
|
20
|
+
dataset.add_images_from_path(path=str(dataset_path))
|
|
21
|
+
|
|
22
|
+
# Run selection via the dataset query
|
|
23
|
+
dataset.query().selection().diverse(
|
|
24
|
+
n_samples_to_select=10,
|
|
25
|
+
selection_result_tag_name="diverse_selection",
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
ls.start_gui()
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Example of how to add tags to samples to set up a split review workflow."""
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
|
|
5
|
+
from environs import Env
|
|
6
|
+
|
|
7
|
+
import lightly_studio as ls
|
|
8
|
+
from lightly_studio import db_manager
|
|
9
|
+
|
|
10
|
+
# Read environment variables
|
|
11
|
+
env = Env()
|
|
12
|
+
env.read_env()
|
|
13
|
+
|
|
14
|
+
# Cleanup an existing database
|
|
15
|
+
db_manager.connect(cleanup_existing=True)
|
|
16
|
+
|
|
17
|
+
# Create a Dataset instance
|
|
18
|
+
dataset = ls.Dataset.create()
|
|
19
|
+
|
|
20
|
+
# Define the path to the dataset (folder containing data.yaml)
|
|
21
|
+
dataset_path = env.path("EXAMPLES_YOLO_YAML_PATH", "/path/to/your/yolo/dataset/data.yaml")
|
|
22
|
+
input_split = env.str("EXAMPLES_YOLO_SPLIT", "test")
|
|
23
|
+
|
|
24
|
+
# Load YOLO dataset using data.yaml path
|
|
25
|
+
dataset.add_samples_from_yolo(
|
|
26
|
+
data_yaml=dataset_path,
|
|
27
|
+
input_split=input_split,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# Define the reviewers
|
|
31
|
+
# This should be a comma-separated list of reviewers
|
|
32
|
+
# we will then create a tag for each reviewer and assign them samples
|
|
33
|
+
# to work on.
|
|
34
|
+
reviewers = env.str("DATASET_REVIEWERS", "Alice, Bob, Charlie, David")
|
|
35
|
+
|
|
36
|
+
# Create a tag for each reviewer to work on
|
|
37
|
+
tags = [reviewer.strip() for reviewer in reviewers.split(",")]
|
|
38
|
+
|
|
39
|
+
# Get all samples from the db
|
|
40
|
+
samples = dataset.query().to_list()
|
|
41
|
+
|
|
42
|
+
# Chunk the samples into portions equally divided among the reviewers.
|
|
43
|
+
chunk_size = math.ceil(len(samples) / len(tags))
|
|
44
|
+
for i, sample in enumerate(samples):
|
|
45
|
+
sample.add_tag(tags[i // chunk_size])
|
|
46
|
+
|
|
47
|
+
# Launch the server to load data
|
|
48
|
+
ls.start_gui()
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Example of how to load videos from path with the dataset class."""
|
|
2
|
+
|
|
3
|
+
from environs import Env
|
|
4
|
+
|
|
5
|
+
import lightly_studio as ls
|
|
6
|
+
from lightly_studio import db_manager
|
|
7
|
+
|
|
8
|
+
# Read environment variables
|
|
9
|
+
env = Env()
|
|
10
|
+
env.read_env()
|
|
11
|
+
|
|
12
|
+
# Cleanup an existing database
|
|
13
|
+
db_manager.connect(cleanup_existing=True)
|
|
14
|
+
|
|
15
|
+
# Define the path to the dataset directory
|
|
16
|
+
dataset_path = env.path("EXAMPLES_VIDEO_DATASET_PATH", "/path/to/your/dataset")
|
|
17
|
+
|
|
18
|
+
# Create a Dataset from a path
|
|
19
|
+
dataset = ls.Dataset.create(sample_type=ls.SampleType.VIDEO)
|
|
20
|
+
dataset.add_videos_from_path(path=dataset_path)
|
|
21
|
+
|
|
22
|
+
ls.start_gui()
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""Example of how to load videos with annotations in YouTube-VIS format."""
|
|
2
|
+
# ruff: noqa: D102, D107
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
from argparse import ArgumentParser
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Iterable
|
|
10
|
+
from uuid import UUID
|
|
11
|
+
|
|
12
|
+
import tqdm
|
|
13
|
+
from environs import Env
|
|
14
|
+
from labelformat.model.bounding_box import BoundingBox, BoundingBoxFormat
|
|
15
|
+
from labelformat.model.category import Category
|
|
16
|
+
from labelformat.model.image import Image
|
|
17
|
+
from labelformat.model.object_detection import (
|
|
18
|
+
ImageObjectDetection,
|
|
19
|
+
ObjectDetectionInput,
|
|
20
|
+
SingleObjectDetection,
|
|
21
|
+
)
|
|
22
|
+
from sqlmodel import Session
|
|
23
|
+
|
|
24
|
+
import lightly_studio as ls
|
|
25
|
+
from lightly_studio import db_manager
|
|
26
|
+
from lightly_studio.core import add_samples
|
|
27
|
+
from lightly_studio.resolvers import video_resolver
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class YouTubeVISObjectDetectionInput(ObjectDetectionInput):
|
|
31
|
+
"""Loads object detections from a modified YouTube-VIS format.
|
|
32
|
+
|
|
33
|
+
The annotation json format is without modification, but the images are loaded as videos.
|
|
34
|
+
|
|
35
|
+
This is a temporary hack until YouTubeVIS is supported natively in labelformat. The code
|
|
36
|
+
is adapted from labelformat's COCOObjectDetectionInput.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
@staticmethod
|
|
40
|
+
def add_cli_arguments(parser: ArgumentParser) -> None:
|
|
41
|
+
raise NotImplementedError()
|
|
42
|
+
|
|
43
|
+
def __init__(self, input_file: Path) -> None:
|
|
44
|
+
with input_file.open() as file:
|
|
45
|
+
self._data = json.load(file)
|
|
46
|
+
|
|
47
|
+
def get_categories(self) -> Iterable[Category]:
|
|
48
|
+
for category in self._data["categories"]:
|
|
49
|
+
yield Category(
|
|
50
|
+
id=category["id"],
|
|
51
|
+
name=category["name"],
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
def get_images(self) -> Iterable[Image]:
|
|
55
|
+
for video in self._data["videos"]:
|
|
56
|
+
yield Image(
|
|
57
|
+
id=video["id"],
|
|
58
|
+
# The video name is <video_folder>.mp4
|
|
59
|
+
filename=Path(video["file_names"][0]).parent.name + ".mp4",
|
|
60
|
+
width=int(video["width"]),
|
|
61
|
+
height=int(video["height"]),
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
def get_labels(self) -> Iterable[ImageObjectDetection]:
|
|
65
|
+
video_id_to_video = {video.id: video for video in self.get_images()}
|
|
66
|
+
category_id_to_category = {category.id: category for category in self.get_categories()}
|
|
67
|
+
|
|
68
|
+
for annotation_json in self._data["annotations"]:
|
|
69
|
+
# Only extract bounding boxes, not segmentations. Every element in "bboxes"
|
|
70
|
+
# corresponds to one frame in the video.
|
|
71
|
+
frame_detections: list[SingleObjectDetection] = [
|
|
72
|
+
SingleObjectDetection(
|
|
73
|
+
category=category_id_to_category[annotation_json["category_id"]],
|
|
74
|
+
box=BoundingBox.from_format(bbox=bbox, format=BoundingBoxFormat.XYWH),
|
|
75
|
+
)
|
|
76
|
+
if bbox is not None
|
|
77
|
+
else SingleObjectDetection(
|
|
78
|
+
category=Category(-1, "no segmentation"),
|
|
79
|
+
box=BoundingBox.from_format(bbox=[0, 0, 0, 0], format=BoundingBoxFormat.XYWH),
|
|
80
|
+
)
|
|
81
|
+
for bbox in annotation_json["bboxes"]
|
|
82
|
+
]
|
|
83
|
+
yield ImageObjectDetection(
|
|
84
|
+
image=video_id_to_video[annotation_json["video_id"]],
|
|
85
|
+
objects=frame_detections,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def load_annotations(session: Session, dataset_id: UUID, annotations_path: Path) -> None:
|
|
90
|
+
"""Loads video annotations from a YouTube-VIS format.
|
|
91
|
+
|
|
92
|
+
Temporarily use internal add_samples API until labelformat supports videos natively.
|
|
93
|
+
"""
|
|
94
|
+
print("Loading video annotations...")
|
|
95
|
+
videos = video_resolver.get_all_by_dataset_id_with_frames(
|
|
96
|
+
session=session, dataset_id=dataset_id
|
|
97
|
+
)
|
|
98
|
+
video_name_to_video = {video.file_name: video for video in videos}
|
|
99
|
+
yvis_input = YouTubeVISObjectDetectionInput(input_file=annotations_path)
|
|
100
|
+
label_map = add_samples._create_label_map( # noqa: SLF001
|
|
101
|
+
session=session,
|
|
102
|
+
input_labels=yvis_input,
|
|
103
|
+
)
|
|
104
|
+
for label in tqdm.tqdm(yvis_input.get_labels(), desc="Adding annotations", unit=" objects"):
|
|
105
|
+
video = video_name_to_video[label.image.filename]
|
|
106
|
+
assert len(label.objects) == len(video.frames), (
|
|
107
|
+
f"Number of frames in annotation ({len(label.objects)}) does not match "
|
|
108
|
+
f"number of frames in video ({len(video.frames)}) for video {label.image.filename}"
|
|
109
|
+
)
|
|
110
|
+
# Use frame index as path to match frames with annotations
|
|
111
|
+
path_to_id = {str(idx): frame.sample_id for idx, frame in enumerate(video.frames)}
|
|
112
|
+
path_to_anno_data = {
|
|
113
|
+
str(idx): ImageObjectDetection(
|
|
114
|
+
image=label.image,
|
|
115
|
+
objects=[obj],
|
|
116
|
+
)
|
|
117
|
+
if obj.category.id != -1
|
|
118
|
+
else ImageObjectDetection(
|
|
119
|
+
image=label.image,
|
|
120
|
+
objects=[],
|
|
121
|
+
)
|
|
122
|
+
for idx, obj in enumerate(label.objects)
|
|
123
|
+
}
|
|
124
|
+
add_samples._process_batch_annotations( # noqa: SLF001
|
|
125
|
+
session=session,
|
|
126
|
+
created_path_to_id=path_to_id,
|
|
127
|
+
path_to_anno_data=path_to_anno_data,
|
|
128
|
+
dataset_id=dataset_id,
|
|
129
|
+
label_map=label_map,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
if __name__ == "__main__":
|
|
134
|
+
# Read environment variables
|
|
135
|
+
env = Env()
|
|
136
|
+
env.read_env()
|
|
137
|
+
|
|
138
|
+
# Cleanup an existing database
|
|
139
|
+
db_manager.connect(cleanup_existing=True)
|
|
140
|
+
|
|
141
|
+
# Define the path to the dataset directory
|
|
142
|
+
dataset_path = env.path("EXAMPLES_VIDEO_DATASET_PATH", "/path/to/your/dataset")
|
|
143
|
+
annotations_path = env.path(
|
|
144
|
+
"EXAMPLES_VIDEO_YVIS_JSON_PATH", "/path/to/your/dataset/instances.json"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# Create a Dataset from a path
|
|
148
|
+
dataset = ls.Dataset.create(sample_type=ls.SampleType.VIDEO)
|
|
149
|
+
dataset.add_videos_from_path(path=dataset_path)
|
|
150
|
+
|
|
151
|
+
# Load annotations
|
|
152
|
+
load_annotations(
|
|
153
|
+
session=dataset.session, dataset_id=dataset.dataset_id, annotations_path=annotations_path
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
# Start the GUI
|
|
157
|
+
ls.start_gui()
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Example of how to add samples in yolo format to a dataset."""
|
|
2
|
+
|
|
3
|
+
from environs import Env
|
|
4
|
+
|
|
5
|
+
import lightly_studio as ls
|
|
6
|
+
from lightly_studio import db_manager
|
|
7
|
+
|
|
8
|
+
# Read environment variables
|
|
9
|
+
env = Env()
|
|
10
|
+
env.read_env()
|
|
11
|
+
|
|
12
|
+
# Cleanup an existing database
|
|
13
|
+
db_manager.connect(cleanup_existing=True)
|
|
14
|
+
|
|
15
|
+
# Define the path to the dataset directory
|
|
16
|
+
dataset_path = env.path("EXAMPLES_YOLO_YAML_PATH", "/path/to/your/dataset/data.yaml")
|
|
17
|
+
input_split = env.str("EXAMPLES_YOLO_SPLIT", "train")
|
|
18
|
+
|
|
19
|
+
# Create a DatasetLoader from a path
|
|
20
|
+
dataset = ls.Dataset.create()
|
|
21
|
+
dataset.add_samples_from_yolo(data_yaml=dataset_path, input_split=input_split)
|
|
22
|
+
ls.start_gui()
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Helper module for exporting datasets in COCO captions format."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Iterable, TypedDict
|
|
6
|
+
|
|
7
|
+
from lightly_studio.core.image_sample import ImageSample
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CocoCaptionImage(TypedDict):
|
|
11
|
+
"""Image schema for COCO captions format."""
|
|
12
|
+
|
|
13
|
+
id: int
|
|
14
|
+
file_name: str
|
|
15
|
+
width: int
|
|
16
|
+
height: int
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class CocoCaptionAnnotation(TypedDict):
|
|
20
|
+
"""Annotation schema for COCO captions format."""
|
|
21
|
+
|
|
22
|
+
id: int
|
|
23
|
+
image_id: int
|
|
24
|
+
caption: str
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class CocoCaptionsJson(TypedDict):
|
|
28
|
+
"""COCO captions JSON schema."""
|
|
29
|
+
|
|
30
|
+
images: list[CocoCaptionImage]
|
|
31
|
+
annotations: list[CocoCaptionAnnotation]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def to_coco_captions_dict(samples: Iterable[ImageSample]) -> CocoCaptionsJson:
|
|
35
|
+
"""Convert samples with captions to a COCO captions dictionary.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
samples: The samples to export.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
A dictionary in COCO captions format.
|
|
42
|
+
"""
|
|
43
|
+
coco_images: list[CocoCaptionImage] = []
|
|
44
|
+
coco_annotations: list[CocoCaptionAnnotation] = []
|
|
45
|
+
annotation_id = 0
|
|
46
|
+
|
|
47
|
+
for image_id, image in enumerate(samples):
|
|
48
|
+
coco_images.append(
|
|
49
|
+
{
|
|
50
|
+
"id": image_id,
|
|
51
|
+
"file_name": image.file_path_abs,
|
|
52
|
+
"width": image.width,
|
|
53
|
+
"height": image.height,
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
for caption in image.captions:
|
|
57
|
+
coco_annotations.append(
|
|
58
|
+
{
|
|
59
|
+
"id": annotation_id,
|
|
60
|
+
"image_id": image_id,
|
|
61
|
+
"caption": caption,
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
annotation_id += 1
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
"images": coco_images,
|
|
68
|
+
"annotations": coco_annotations,
|
|
69
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""Exports datasets from Lightly Studio into various formats."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Iterable
|
|
8
|
+
|
|
9
|
+
from labelformat.formats import COCOObjectDetectionOutput
|
|
10
|
+
from sqlmodel import Session
|
|
11
|
+
|
|
12
|
+
from lightly_studio.core.image_sample import ImageSample
|
|
13
|
+
from lightly_studio.export import coco_captions
|
|
14
|
+
from lightly_studio.export.lightly_studio_label_input import LightlyStudioObjectDetectionInput
|
|
15
|
+
from lightly_studio.type_definitions import PathLike
|
|
16
|
+
|
|
17
|
+
DEFAULT_EXPORT_FILENAME = "coco_export.json"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class DatasetExport:
|
|
21
|
+
"""Provides methods to export a dataset or a subset of it.
|
|
22
|
+
|
|
23
|
+
This class is typically not instantiated directly but returned by `Dataset.export()`.
|
|
24
|
+
It allows exporting data in various formats.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, session: Session, samples: Iterable[ImageSample]):
|
|
28
|
+
"""Initializes the DatasetExport object.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
session: The database session.
|
|
32
|
+
samples: Samples to export.
|
|
33
|
+
"""
|
|
34
|
+
self.session = session
|
|
35
|
+
self.samples = samples
|
|
36
|
+
|
|
37
|
+
def to_coco_object_detections(self, output_json: PathLike | None = None) -> None:
|
|
38
|
+
"""Exports object detection annotations to a COCO format JSON file.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
output_json: The path to the output COCO JSON file. If not provided,
|
|
42
|
+
defaults to "coco_export.json" in the current working directory.
|
|
43
|
+
|
|
44
|
+
Raises:
|
|
45
|
+
ValueError: If the annotation task with the given name does not exist.
|
|
46
|
+
"""
|
|
47
|
+
if output_json is None:
|
|
48
|
+
output_json = DEFAULT_EXPORT_FILENAME
|
|
49
|
+
to_coco_object_detections(
|
|
50
|
+
session=self.session,
|
|
51
|
+
samples=self.samples,
|
|
52
|
+
output_json=Path(output_json),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def to_coco_captions(self, output_json: PathLike | None = None) -> None:
|
|
56
|
+
"""Exports captions to a COCO format JSON file.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
output_json: The path to the output COCO JSON file. If not provided,
|
|
60
|
+
defaults to "coco_export.json" in the current working directory.
|
|
61
|
+
"""
|
|
62
|
+
if output_json is None:
|
|
63
|
+
output_json = DEFAULT_EXPORT_FILENAME
|
|
64
|
+
to_coco_captions(samples=self.samples, output_json=Path(output_json))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def to_coco_object_detections(
|
|
68
|
+
session: Session,
|
|
69
|
+
samples: Iterable[ImageSample],
|
|
70
|
+
output_json: Path,
|
|
71
|
+
) -> None:
|
|
72
|
+
"""Exports object detection annotations to a COCO format JSON file.
|
|
73
|
+
|
|
74
|
+
This function is for internal use. Use `Dataset.query().export().to_coco_object_detections()`
|
|
75
|
+
instead.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
session: The database session.
|
|
79
|
+
samples: The samples to export.
|
|
80
|
+
output_json: The path to save the output JSON file.
|
|
81
|
+
"""
|
|
82
|
+
export_input = LightlyStudioObjectDetectionInput(
|
|
83
|
+
session=session,
|
|
84
|
+
samples=samples,
|
|
85
|
+
)
|
|
86
|
+
COCOObjectDetectionOutput(output_file=output_json).save(label_input=export_input)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def to_coco_captions(
|
|
90
|
+
samples: Iterable[ImageSample],
|
|
91
|
+
output_json: Path,
|
|
92
|
+
) -> None:
|
|
93
|
+
"""Exports captions to a COCO format JSON file.
|
|
94
|
+
|
|
95
|
+
This function is for internal use. Use `Dataset.query().export().to_coco_captions()`
|
|
96
|
+
instead.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
samples: The samples to export.
|
|
100
|
+
output_json: The path to save the output JSON file.
|
|
101
|
+
"""
|
|
102
|
+
coco_captions_dict = coco_captions.to_coco_captions_dict(samples=samples)
|
|
103
|
+
with output_json.open("w") as f:
|
|
104
|
+
json.dump(coco_captions_dict, f, indent=2)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""Converts annotations from Lightly Studio to Labelformat format."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from argparse import ArgumentParser
|
|
6
|
+
from typing import Iterable
|
|
7
|
+
from uuid import UUID
|
|
8
|
+
|
|
9
|
+
from labelformat.model.bounding_box import BoundingBox
|
|
10
|
+
from labelformat.model.category import Category
|
|
11
|
+
from labelformat.model.image import Image
|
|
12
|
+
from labelformat.model.object_detection import (
|
|
13
|
+
ImageObjectDetection,
|
|
14
|
+
ObjectDetectionInput,
|
|
15
|
+
SingleObjectDetection,
|
|
16
|
+
)
|
|
17
|
+
from sqlmodel import Session
|
|
18
|
+
|
|
19
|
+
from lightly_studio.core.image_sample import ImageSample
|
|
20
|
+
from lightly_studio.models.annotation.annotation_base import AnnotationBaseTable, AnnotationType
|
|
21
|
+
from lightly_studio.resolvers import annotation_label_resolver
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class LightlyStudioObjectDetectionInput(ObjectDetectionInput):
|
|
25
|
+
"""Labelformat adapter backed by dataset samples and annotations."""
|
|
26
|
+
|
|
27
|
+
def __init__(self, session: Session, samples: Iterable[ImageSample]) -> None:
|
|
28
|
+
"""Initializes the LightlyStudioObjectDetectionInput.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
session: The SQLModel session to use for database access. Used only in the
|
|
32
|
+
constructor to fetch the labels for the given annotation task.
|
|
33
|
+
samples: Dataset samples.
|
|
34
|
+
"""
|
|
35
|
+
self._samples = list(samples)
|
|
36
|
+
self._label_id_to_category = _build_label_id_to_category(session=session)
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def add_cli_arguments(parser: ArgumentParser) -> None:
|
|
40
|
+
"""Adds CLI arguments."""
|
|
41
|
+
# Add CLI arguments implementation is not needed for this class. We need it only
|
|
42
|
+
# to satisfy the interface.
|
|
43
|
+
raise NotImplementedError()
|
|
44
|
+
|
|
45
|
+
def get_categories(self) -> Iterable[Category]:
|
|
46
|
+
"""Returns the categories for export."""
|
|
47
|
+
return self._label_id_to_category.values()
|
|
48
|
+
|
|
49
|
+
def get_images(self) -> Iterable[Image]:
|
|
50
|
+
"""Returns the images for export."""
|
|
51
|
+
for idx, sample in enumerate(self._samples):
|
|
52
|
+
yield _sample_to_image(sample=sample, image_id=idx)
|
|
53
|
+
|
|
54
|
+
def get_labels(self) -> Iterable[ImageObjectDetection]:
|
|
55
|
+
"""Returns the labels for export."""
|
|
56
|
+
for idx, sample in enumerate(self._samples):
|
|
57
|
+
yield _sample_to_image_obj_det(
|
|
58
|
+
sample=sample,
|
|
59
|
+
image_id=idx,
|
|
60
|
+
label_id_to_category=self._label_id_to_category,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _build_label_id_to_category(session: Session) -> dict[UUID, Category]:
|
|
65
|
+
labels = annotation_label_resolver.get_all_sorted_alphabetically(
|
|
66
|
+
session=session,
|
|
67
|
+
)
|
|
68
|
+
# TODO(Horatiu, 09/2025): We should get only labels that are attached to Object Detection
|
|
69
|
+
# annotations.
|
|
70
|
+
return {
|
|
71
|
+
label.annotation_label_id: Category(id=idx, name=label.annotation_label_name)
|
|
72
|
+
for idx, label in enumerate(labels)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _sample_to_image(sample: ImageSample, image_id: int) -> Image:
|
|
77
|
+
return Image(
|
|
78
|
+
id=image_id,
|
|
79
|
+
filename=sample.file_path_abs,
|
|
80
|
+
width=sample.width,
|
|
81
|
+
height=sample.height,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _sample_to_image_obj_det(
|
|
86
|
+
sample: ImageSample,
|
|
87
|
+
image_id: int,
|
|
88
|
+
label_id_to_category: dict[UUID, Category],
|
|
89
|
+
) -> ImageObjectDetection:
|
|
90
|
+
# TODO(Michal, 09/2025): We can optimise in the future to filter annotations in a DB query.
|
|
91
|
+
objects = [
|
|
92
|
+
_annotation_to_single_obj_det(
|
|
93
|
+
annotation=annotation,
|
|
94
|
+
label_id_to_category=label_id_to_category,
|
|
95
|
+
)
|
|
96
|
+
for annotation in sample.sample_table.annotations
|
|
97
|
+
if annotation.annotation_type == AnnotationType.OBJECT_DETECTION
|
|
98
|
+
]
|
|
99
|
+
return ImageObjectDetection(
|
|
100
|
+
image=_sample_to_image(sample=sample, image_id=image_id),
|
|
101
|
+
objects=objects,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _annotation_to_single_obj_det(
|
|
106
|
+
annotation: AnnotationBaseTable, label_id_to_category: dict[UUID, Category]
|
|
107
|
+
) -> SingleObjectDetection:
|
|
108
|
+
assert annotation.object_detection_details is not None
|
|
109
|
+
box = BoundingBox(
|
|
110
|
+
xmin=annotation.object_detection_details.x,
|
|
111
|
+
ymin=annotation.object_detection_details.y,
|
|
112
|
+
xmax=annotation.object_detection_details.x + annotation.object_detection_details.width,
|
|
113
|
+
ymax=annotation.object_detection_details.y + annotation.object_detection_details.height,
|
|
114
|
+
)
|
|
115
|
+
category = label_id_to_category[annotation.annotation_label.annotation_label_id]
|
|
116
|
+
return SingleObjectDetection(
|
|
117
|
+
category=category,
|
|
118
|
+
box=box,
|
|
119
|
+
confidence=annotation.confidence,
|
|
120
|
+
)
|