Skip to content
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

Fix sam2 #662

Closed
wants to merge 47 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
f3f3854
feat: RND-118: YOLO with Timeline classification
makseq Sep 7, 2024
3128f75
tmp
makseq Sep 8, 2024
b94a881
Merge branch 'master' of github.com:heartexlabs/label-studio-ml-backe…
makseq Sep 8, 2024
c056aa5
model names refactor
makseq Sep 8, 2024
1aef349
NN model
makseq Sep 10, 2024
e8b7443
Test passed
makseq Sep 11, 2024
b5b74cd
Some
makseq Sep 11, 2024
abcbd4e
Working lstm
makseq Sep 12, 2024
032ecd2
Fixes in lstm
makseq Sep 12, 2024
da04c8d
Last layer working lstm
makseq Sep 13, 2024
dce178f
Cleanup and accuracy
makseq Sep 13, 2024
224ea66
Fixes in training
makseq Sep 14, 2024
444698c
Fix converters
makseq Sep 16, 2024
1d2748b
Add readme
makseq Sep 16, 2024
f77c8d1
Fixes
makseq Sep 17, 2024
c016f8b
Docs fixes
makseq Sep 17, 2024
f204d75
Fix docs
makseq Sep 17, 2024
df01c30
Add link docs
makseq Sep 17, 2024
fa18c4e
Fix
makseq Sep 17, 2024
d36fd14
Adjust desc
makseq Sep 17, 2024
9bdde47
Fix mermaid
makseq Sep 17, 2024
cbb48d4
Fix
makseq Sep 17, 2024
0b78114
Fix
makseq Sep 17, 2024
16f8d40
Docs
makseq Sep 17, 2024
b386aac
Docs
makseq Sep 17, 2024
67c05d9
Add simple mode test
makseq Sep 17, 2024
f0ac4bf
Fix streaming in obj tracking
makseq Sep 17, 2024
f448881
fix tests
makseq Sep 17, 2024
ba78b2c
Merge branch 'master' of github.com:heartexlabs/label-studio-ml-backe…
makseq Sep 17, 2024
541bfe8
Modify API
makseq Sep 17, 2024
b9dbc38
Fix api
makseq Sep 17, 2024
1d2b30d
Remove model_ from protected
makseq Sep 17, 2024
2ee27d5
Fix path model, timeout in tests
makseq Sep 17, 2024
8a35e17
Update README_TIMELINE_LABELS.md
micaelakaplan Sep 17, 2024
ec3877a
Update README_TIMELINE_LABELS.md
micaelakaplan Sep 17, 2024
88b5a1a
Fix dockerignore
makseq Sep 17, 2024
fd944be
Merge branch 'feat/rnd-118' of github.com:heartexlabs/label-studio-ml…
makseq Sep 17, 2024
1cfd1b9
Fix tests
makseq Sep 17, 2024
1f636b0
Fix get bool
makseq Sep 17, 2024
2b138b2
Fix
makseq Sep 17, 2024
1efcf79
Fix
makseq Sep 17, 2024
ef2c175
Fix
makseq Sep 17, 2024
1242e9f
Fix in docs
makseq Sep 18, 2024
750a426
Update README_TIMELINE_LABELS.md
micaelakaplan Sep 18, 2024
27fc10f
Fix from_name in converter
makseq Sep 18, 2024
581fa6d
Merge branch 'feat/rnd-118' of github.com:heartexlabs/label-studio-ml…
makseq Sep 18, 2024
186fb22
update for meta changes
micaelakaplan Nov 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ jobs:
run: docker compose -f label_studio_ml/examples/${{ matrix.backend_dir_name }}/docker-compose.yml up -d --build

- name: Wait for stack
timeout-minutes: 10
timeout-minutes: 20
run: |
while [ "$(curl -s -o /dev/null -L -w ''%{http_code}'' "http://localhost:9090/health")" != "200" ]; do
echo "=> Waiting for service to become available" && sleep 2s
Expand Down
12 changes: 9 additions & 3 deletions label_studio_ml/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def _predict():
data = request.json
tasks = data.get('tasks')
label_config = data.get('label_config')
project = data.get('project')
project = str(data.get('project'))
project_id = project.split('.', 1)[0] if project else None
params = data.get('params', {})
context = params.pop('context', {})
Expand Down Expand Up @@ -123,8 +123,14 @@ def webhook():
project_id = str(data['project']['id'])
label_config = data['project']['label_config']
model = MODEL_CLASS(project_id, label_config=label_config)
model.fit(event, data)
return jsonify({}), 201
result = model.fit(event, data)

try:
response = jsonify({'result': result, 'status': 'ok'})
except Exception as e:
response = jsonify({'error': str(e), 'status': 'error'})

return response, 201


@_server.route('/health', methods=['GET'])
Expand Down
52 changes: 28 additions & 24 deletions label_studio_ml/default_configs/_wsgi.py.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,33 @@ import json
import logging
import logging.config

logging.config.dictConfig({{
"version": 1,
"formatters": {{
"standard": {{
"format": "[%(asctime)s] [%(levelname)s] [%(name)s::%(funcName)s::%(lineno)d] %(message)s"
}}
}},
"handlers": {{
"console": {{
"class": "logging.StreamHandler",
"level": os.getenv('LOG_LEVEL'),
"stream": "ext://sys.stdout",
"formatter": "standard"
}}
}},
"root": {{
"level": os.getenv('LOG_LEVEL'),
"handlers": [
"console"
],
"propagate": True
}}
}})
# Set a default log level if LOG_LEVEL is not defined
log_level = os.getenv("LOG_LEVEL", "INFO")

logging.config.dictConfig(
{
"version": 1,
"disable_existing_loggers": False, # Prevent overriding existing loggers
"formatters": {
"standard": {
"format": "[%(asctime)s] [%(levelname)s] [%(name)s::%(funcName)s::%(lineno)d] %(message)s"
}
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": log_level,
"stream": "ext://sys.stdout",
"formatter": "standard",
}
},
"root": {
"level": log_level,
"handlers": ["console"],
"propagate": True,
},
}
)

from label_studio_ml.api import init_app
from {script} import {model_class}
Expand Down Expand Up @@ -59,7 +63,7 @@ if __name__ == "__main__":
'-d', '--debug', dest='debug', action='store_true',
help='Switch debug mode')
parser.add_argument(
'--log-level', dest='log_level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'], default=None,
'--log-level', dest='log_level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'], default=log_level,
help='Logging level')
parser.add_argument(
'--model-dir', dest='model_dir', default=os.path.dirname(__file__),
Expand Down
20 changes: 17 additions & 3 deletions label_studio_ml/examples/segment_anything_2_image/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,29 @@ cd label_studio_ml/examples/segment_anything_2_image
pip install -r requirements.txt
```

2. Download [`segment-anything-2` repo](https://github.com/facebookresearch/segment-anything-2) into the root directory. Install SegmentAnything model and download checkpoints using [the official Meta documentation](https://github.com/facebookresearch/segment-anything-2?tab=readme-ov-file#installation)
2. Download [`segment-anything-2` repo](https://github.com/facebookresearch/segment-anything-2) into the ROOT directory. Install SegmentAnything model and download checkpoints using [the official Meta documentation](https://github.com/facebookresearch/segment-anything-2?tab=readme-ov-file#installation)

You should now have the following folder structure:

ROOT_DIR (i.e. ~)

| label-studio-ml-backend
| label-studio-ml
| examples
| segment_anything_2_image
| sam2
| sam2
| checkpoints

3. Then you can start the ML backend on the default port `9090`:

```bash
cd ../
label-studio-ml start ./segment_anything_2_image
cd ~/sam2
label-studio-ml start ../label-studio-ml-backend/label-studio-ml/examples/segement_anything_2_image
```
Make sure that you run this code from the sam2 directory in your root directory, as Meta has added a check that makes other folder structures break. Additionally, we rely on a `os.getcwd()` command to get the rest of the code working properly.

To change the port that you're running on, simply add `--p <port number>` to the end of the above command.

4. Connect running ML backend server to Label Studio: go to your project `Settings -> Machine Learning -> Add Model` and specify `http://localhost:9090` as a URL. Read more in the official [Label Studio documentation](https://labelstud.io/guide/ml#Connect-the-model-to-Label-Studio).

Expand Down
9 changes: 7 additions & 2 deletions label_studio_ml/examples/segment_anything_2_image/model.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import torch
import numpy as np
import os
import sys
import pathlib
from typing import List, Dict, Optional
from uuid import uuid4
Expand All @@ -9,6 +10,10 @@
from label_studio_sdk.converter import brush
from label_studio_sdk._extensions.label_studio_tools.core.utils.io import get_local_path
from PIL import Image

ROOT_DIR = os.getcwd()
sys.path.insert(0, ROOT_DIR)

from sam2.build_sam import build_sam2
from sam2.sam2_image_predictor import SAM2ImagePredictor

Expand All @@ -29,7 +34,7 @@


# build path to the model checkpoint
sam2_checkpoint = str(pathlib.Path(__file__).parent / SEGMENT_ANYTHING_2_REPO_PATH / "checkpoints" / MODEL_CHECKPOINT)
sam2_checkpoint = str(os.path.join(ROOT_DIR, "checkpoints", MODEL_CHECKPOINT))

sam2_model = build_sam2(MODEL_CONFIG, sam2_checkpoint, device=DEVICE)

Expand Down Expand Up @@ -152,5 +157,5 @@ def predict(self, tasks: List[Dict], context: Optional[Dict] = None, **kwargs) -
from_name=from_name,
to_name=to_name,
label=selected_label)

return ModelResponse(predictions=predictions)
1 change: 1 addition & 0 deletions label_studio_ml/examples/yolo/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
!tests/*
!control_models/*
!models/*
!utils/*

# Include requirements files
!requirements*.txt
Expand Down
16 changes: 8 additions & 8 deletions label_studio_ml/examples/yolo/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ WORKDIR /app

COPY . ./

WORKDIR /app/models

# Download the YOLO models
RUN yolo predict model=yolov8m.pt source=/app/tests/car.jpg \
&& yolo predict model=yolov8n.pt source=/app/tests/car.jpg \
&& yolo predict model=yolov8n-cls.pt source=/app/tests/car.jpg \
&& yolo predict model=yolov8n-seg.pt source=/app/tests/car.jpg

WORKDIR /app
RUN /bin/sh -c 'if [ ! -f /app/models/yolov8m.pt ]; then \
yolo predict model=/app/models/yolov8m.pt source=/app/tests/car.jpg \
&& yolo predict model=/app/models/yolov8n.pt source=/app/tests/car.jpg \
&& yolo predict model=/app/models/yolov8n-cls.pt source=/app/tests/car.jpg \
&& yolo predict model=/app/models/yolov8n-seg.pt source=/app/tests/car.jpg; \
fi'

ENV PYTHONPATH=/app

CMD ["/app/start.sh"]
70 changes: 57 additions & 13 deletions label_studio_ml/examples/yolo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,17 @@ making it easier to annotate large datasets and ensure high-quality predictions.

**Supported Features**

| YOLO Task Name | LS Control Tag | Prediction Supported | LS Import Supported | LS Export Supported |
|---------------------------------------|--------------------------------------|----------------------|---------------------|---------------------|
| Object Detection | `<RectangleLabels>` | ✅ | YOLO, COCO | YOLO, COCO |
| Oriented Bounding Boxes (OBB) | `<RectangleLabels model_obb="true">` | ✅ | YOLO | YOLO |
| Image Instance Segmentation: Polygons | `<PolygonLabels>` | ✅ | COCO | YOLO, COCO |
| Image Semantic Segmentation: Masks | `<BrushLabels>` | ❌ | Native | Native |
| Image Classification | `<Choices>` | ✅ | Native | Native |
| Pose Detection | `<KeyPoints>` | ✅ | Native | Native |
| Video Object Tracking | `<VideoRectangle>` | ✅ | Native | Native |
| Video Temporal Classification | `<TimelineLabels>` | Coming soon | Native | Native |
| YOLO Task Name | LS Control Tag | Prediction Supported | LS Import Supported | LS Export Supported |
|--------------------------------------------------------------|--------------------------------------|----------------------|---------------------|---------------------|
| Object Detection | `<RectangleLabels>` | ✅ | YOLO, COCO | YOLO, COCO |
| Oriented Bounding Boxes (OBB) | `<RectangleLabels model_obb="true">` | ✅ | YOLO | YOLO |
| Image Instance Segmentation: Polygons | `<PolygonLabels>` | ✅ | COCO | YOLO, COCO |
| Image Semantic Segmentation: Masks | `<BrushLabels>` | ❌ | Native | Native |
| Image Classification | `<Choices>` | ✅ | Native | Native |
| Pose Detection | `<KeyPoints>` | ✅ | Native | Native |
| Video Object Tracking | `<VideoRectangle>` | ✅ | Native | Native |
| [Video Temporal Classification](./README_TIMELINE_LABELS.md) | `<TimelineLabels>` | ✅ | Native | Native |


* **LS Control Tag**: Label Studio [control tag](https://labelstud.io/tags/) from the labeling configuration.
* **LS Import Supported**: Indicates whether Label Studio supports Import from YOLO format to Label Studio (using the LS converter).
Expand Down Expand Up @@ -82,7 +83,7 @@ This tutorial uses the [YOLO example](https://github.com/HumanSignal/label-studi

4. Then from the **Model** page in the project settings, [connect the model](https://labelstud.io/guide/ml#Connect-the-model-to-Label-Studio). The default URL is `http://localhost:9090`.

5. Add images to Label Studio.
5. Add images or video (depending on tasks you are going to solve) to Label Studio.

6. Open any task in the Data Manager and see the predictions from the YOLO model.

Expand All @@ -97,11 +98,13 @@ This tutorial uses the [YOLO example](https://github.com/HumanSignal/label-studi

**Control tags**

- `<Choices>` - [Classification](https://labelstud.io/tags/choices); image classification task
- `<RectangleLabels>` - [Bounding boxes](https://labelstud.io/tags/rectanglelabels); object detection task
- `<PolygonLabels>` - [Polygons](https://labelstud.io/tags/polygonlables); segmentation task
- `<VideoRectangle>` - [Video bounding boxes](https://labelstud.io/tags/videorectangle); video object tracking task
- `<VideoRectangle>` - [Video bounding boxes](https://labelstud.io/tags/videorectangle); object tracking task for videos
- `<KeyPointLabels>` - [Key points](https://labelstud.io/tags/keypointlabels); pose detection task
- `<Choices>` - [Classification](https://labelstud.io/tags/choices)
- `<TimelineLabels>` - [Temporal labels for videos](https://labelstud.io/tags/timelinelabels); multi-label temporal classification task for videos


**How to skip the control tag?**

Expand Down Expand Up @@ -681,6 +684,47 @@ Small models like `yolov8n.pt` are recommended for real-time tracking, however,

<br>


## Video temporal classification using `TimelineLabels`

This ML backend supports temporal multi-label video classification for the `TimelineLabels` control tag in Label Studio.
There are two modes available:
- **Simple:** In the simple mode, the model uses pre-trained YOLO classes to generate predictions without additional training.
- **Trainable:** In the [trainable mode](README_TIMELINE_LABELS.md), the model can be trained on custom labels and annotations submitted in Label Studio like a few shot learning way
when training is performed on a small number of annotations on the fly.

### Labeling config

```xml
<View>
<Video name="video" value="$video"/>
<TimelineLabels
name="label" toName="video"
model_trainable="false" model_score_threshold="0.25">
<Label value="Ball" predicted_values="soccer_ball" />
<Label value="tiger_shark" />
</TimelineLabels>
</View>
```

### Model training

For more details on using the `TimelineLabels` ML backend, including training the model
and adjusting neural network classifier parameters, please refer to
**[README_TIMELINE_LABELS.md](README_TIMELINE_LABELS.md)**.

### Default model

`yolov8n-cls.pt` is the default classification model for simple mode.


<br>

-------------------

<br>


## Run the YOLO ML backend


Expand Down
12 changes: 12 additions & 0 deletions label_studio_ml/examples/yolo/README_DEVELOP.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,19 @@ classDiagram
+create_video_rectangles(results, path) List[Dict]
+update_tracker_params(yaml_path: str, prefix: str) str | None
}

class TimelineLabelsModel {
+predict_regions(path: str) List[Dict]
+fit(event, data)
}

ControlModel <|-- RectangleLabelsModel
ControlModel <|-- RectangleLabelsObbModel
ControlModel <|-- PolygonLabelsModel
ControlModel <|-- ChoicesModel
ControlModel <|-- KeyPointLabelsModel
ControlModel <|-- VideoRectangleModel
ControlModel <|-- TimelineLabelsModel

```

Expand Down Expand Up @@ -122,6 +128,12 @@ The architecture of the project is modular and is primarily centered around inte
- `create_video_rectangles()`: Processes the output of the tracking model to create a sequence of bounding boxes across video frames.
- `update_tracker_params()`: Customizes the tracking parameters based on settings in Label Studio’s configuration.

8. **`control_models/timelinelabels.py` (TimelineLabelsModel)**:
- **Purpose**: Supports the training of a YOLO model on video data incrementally by updating the model with new annotations as they are submitted.
- **Key Functions**:
- `predict_regions()`: Runs YOLO on video frames and returns the predictions.
- `fit()`: Placeholder method for updating the model with new annotations.

### **Module Interaction**

- **Workflow**: The main workflow begins with `model.py`, which reads tasks and the Label Studio configuration to detect and instantiate the appropriate control models. These control models are responsible for making predictions using the YOLO model and converting the results into a format that Label Studio can use for annotations.
Expand Down
Loading