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

feat: RND-116: YOLOv8 ML Backend #607

Merged
merged 99 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
e975181
feat: RND-117: YOLO ML Backend
makseq Aug 14, 2024
a11eb15
Add cude docker
makseq Aug 14, 2024
a1950f9
Fix trailing slash in dockerfile
makseq Aug 14, 2024
2a62aaa
Renaming
makseq Aug 14, 2024
fab7323
Fix rel
makseq Aug 14, 2024
04f28b8
Move build label map to model
makseq Aug 14, 2024
a42e31f
Add classification
makseq Aug 15, 2024
a232834
Change ML backend deps
makseq Aug 15, 2024
1a5bbcd
Deps
makseq Aug 15, 2024
c8b57e8
Readme additions
makseq Aug 15, 2024
afcf194
Before split
makseq Aug 16, 2024
cab6e07
Finish refactoring
makseq Aug 17, 2024
b984a75
Cache models
makseq Aug 17, 2024
7bc46a3
Preloda models in dockerfile
makseq Aug 17, 2024
3afa213
Video object detection
makseq Aug 19, 2024
0976fe2
Fix download
makseq Aug 19, 2024
584790c
Fix download
makseq Aug 19, 2024
e428879
Fix dockerignore
makseq Aug 19, 2024
2e6c06a
Predict cli
makseq Aug 19, 2024
11ca142
Fix tests
makseq Aug 19, 2024
35796e4
Force loglevel
makseq Aug 19, 2024
c3c03cf
Fix dockerignore
makseq Aug 19, 2024
55f3b3c
Fix tests
makseq Aug 19, 2024
ea23eda
Fix tests
makseq Aug 19, 2024
21bf9f6
Try to fix PYTHONPATH
makseq Aug 20, 2024
e7f2ee9
Add polygonlabels
makseq Aug 20, 2024
47b97fe
Add obb (WIP) and mermaid
makseq Aug 21, 2024
2068866
Revert rect labels model back
makseq Aug 21, 2024
397db8c
Add docs
makseq Aug 21, 2024
86c714c
Update README_DEVELOP.md
makseq Aug 21, 2024
cef127f
Update README_DEVELOP.md
makseq Aug 21, 2024
6be7bbe
Add CLI docs
makseq Aug 21, 2024
9414084
Don't trigger on md changes
makseq Aug 21, 2024
60f67c0
Merge branch 'fix/rnd-117' of github.com:heartexlabs/label-studio-ml-…
makseq Aug 21, 2024
22ed275
Readme updates
makseq Aug 22, 2024
1013817
More docs
makseq Aug 22, 2024
d10f147
Docs
makseq Aug 22, 2024
9f4bdff
Fixes
makseq Aug 22, 2024
a12829b
Fixed OBB
makseq Aug 23, 2024
c31f5dc
Fix docs for OBB
makseq Aug 23, 2024
496f0d9
Fix sdk deps in ml backend main lib
makseq Aug 23, 2024
97e556a
Merge branch 'master' of github.com:heartexlabs/label-studio-ml-backe…
makseq Aug 23, 2024
e832c58
Merge branch 'master' of github.com:heartexlabs/label-studio-ml-backe…
makseq Aug 23, 2024
cca8a58
Readme fixes
makseq Aug 23, 2024
14c8ee6
More docs
makseq Aug 23, 2024
be447ca
Fix develop md
makseq Aug 23, 2024
d1eb692
Add more tests
makseq Aug 24, 2024
a5aa9c0
Add deps tests
makseq Aug 24, 2024
8a65c47
Add more tests
makseq Aug 26, 2024
8502a40
Add choice tests
makseq Aug 26, 2024
a22b840
Add readme about multi choices
makseq Aug 26, 2024
daa8089
Readme fix
makseq Aug 26, 2024
ab5b549
Extend table
makseq Aug 26, 2024
69d9fba
Fix readme
makseq Aug 26, 2024
8d3de4d
Fix readme
makseq Aug 26, 2024
bbb92ef
gifs for readme
micaelakaplan Aug 26, 2024
27abb62
gifs for readme
micaelakaplan Aug 26, 2024
4962c44
Readme
makseq Aug 26, 2024
d929b0c
Merge branch 'fix/rnd-117' of github.com:heartexlabs/label-studio-ml-…
makseq Aug 26, 2024
006217a
squash commits
micaelakaplan Aug 28, 2024
00d8df7
General copyediting on README file
Aug 30, 2024
4d46c6b
Add keypoints
makseq Sep 2, 2024
2b604bd
Merge branch 'fix/rnd-117' of github.com:heartexlabs/label-studio-ml-…
makseq Sep 2, 2024
21837b0
Remove gifs
makseq Sep 2, 2024
c270be1
Add keypoint tests
makseq Sep 3, 2024
936592e
Readme updates
makseq Sep 3, 2024
7e6482e
Remove +1 in point index
makseq Sep 3, 2024
8f5d1d2
Readme
makseq Sep 3, 2024
01cb35f
Fix tests
makseq Sep 3, 2024
83165e6
Fixes
makseq Sep 3, 2024
7d38a65
Update README.md
makseq Sep 3, 2024
e3afb5c
Update README.md
makseq Sep 3, 2024
d8ac608
Replave score_threshold to model_score_threshold
makseq Sep 3, 2024
c1ae5d3
Merge branch 'fix/rnd-117' of github.com:heartexlabs/label-studio-ml-…
makseq Sep 3, 2024
26a20c9
Fix model_index
makseq Sep 3, 2024
5e3cabb
Change model_tracker, model_conf, model_iou
makseq Sep 3, 2024
afccf2d
Fix readme
makseq Sep 3, 2024
cd5c879
Update README.md
makseq Sep 4, 2024
814e40c
Update README.md
makseq Sep 4, 2024
5c973d5
Update README.md
makseq Sep 4, 2024
40d9943
Rename
makseq Sep 4, 2024
3dd9b40
Add timelinelabels and format with black
makseq Sep 4, 2024
0b8bb84
Rename tests
makseq Sep 4, 2024
1a65434
Update README.md
micaelakaplan Sep 4, 2024
d23cb99
Update README.md
micaelakaplan Sep 4, 2024
05fff55
Update README.md
micaelakaplan Sep 4, 2024
8f3cf55
Update README.md
micaelakaplan Sep 4, 2024
9706e32
Update README.md
makseq Sep 4, 2024
cf80635
Update README.md
makseq Sep 4, 2024
4d2bb3f
Update README.md
makseq Sep 4, 2024
fba0c6e
Update README.md
makseq Sep 4, 2024
6a5b55b
Update README.md
makseq Sep 4, 2024
241d224
Update README.md
makseq Sep 4, 2024
ef232ee
Update README.md
makseq Sep 4, 2024
a5001ef
Update README.md
makseq Sep 4, 2024
da1a5ff
Update README.md
makseq Sep 4, 2024
d63f472
Fixes
makseq Sep 6, 2024
8d100a9
Merge branch 'fix/rnd-117' of github.com:heartexlabs/label-studio-ml-…
makseq Sep 6, 2024
5f7b240
Copy edits on YOLO readme
Sep 6, 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
4 changes: 4 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ on:
branches:
- master
- 'release/**'
paths-ignore:
- '**/*.md' # Ignore changes to all .md files
pull_request:
types:
- opened
Expand All @@ -14,6 +16,8 @@ on:
branches:
- master
- 'release/**'
paths-ignore:
- '**/*.md' # Ignore changes to all .md files

env:
CACHE_NAME_PREFIX: v1
Expand Down
1 change: 1 addition & 0 deletions label_studio_ml/examples/mmdetection-3/mmdetection.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ def build_labels_from_labeling_config(self, schema):
for ls_label, label_attrs in self.labels_attrs.items():
predicted_values = label_attrs.get("predicted_values", "").split(",")
for predicted_value in predicted_values:
predicted_value = predicted_value.strip() # remove spaces at the beginning and at the end
if predicted_value: # it shouldn't be empty (like '')
if predicted_value not in mmdet_labels:
print(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
gunicorn==22.0.0
label-studio-ml @ git+https://github.com/HumanSignal/label-studio-ml-backend.git
label-studio-ml @ git+https://github.com/HumanSignal/label-studio-ml-backend.git@fix/rnd-117
makseq marked this conversation as resolved.
Show resolved Hide resolved
18 changes: 1 addition & 17 deletions label_studio_ml/examples/mmdetection-3/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from mmdetection import MMDetection

from pytest import approx
from label_studio_ml.utils import compare_nested_structures

label_config = """
<View>
Expand Down Expand Up @@ -41,22 +41,6 @@
]


def compare_nested_structures(a, b, path=""):
"""Compare two dicts or list with approx() for float values"""
if isinstance(a, dict) and isinstance(b, dict):
assert a.keys() == b.keys(), f"Keys mismatch at {path}"
for key in a.keys():
compare_nested_structures(a[key], b[key], path + "." + str(key))
elif isinstance(a, list) and isinstance(b, list):
assert len(a) == len(b), f"List size mismatch at {path}"
for i, (act_item, exp_item) in enumerate(zip(a, b)):
compare_nested_structures(act_item, exp_item, path + f"[{i}]")
elif isinstance(a, float) and isinstance(b, float):
assert a == approx(b), f"Mismatch at {path}"
else:
assert a == b, f"Mismatch at {path}"


def test_mmdetection_model_predict():
model = MMDetection(label_config=label_config)
predictions = model.predict([task])
Expand Down
22 changes: 22 additions & 0 deletions label_studio_ml/examples/yolo/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Exclude everything
**

# Include Dockerfile and docker-compose for reference (optional, decide based on your use case)
!Dockerfile
!docker-compose.yml

# Include Python application files
!*.py
!*.yaml
!tests/*
!control_models/*
!models/*

# Include requirements files
!requirements*.txt

# Include script
!*.sh

# Exclude specific requirements if necessary
# requirements-test.txt (Uncomment if you decide to exclude this)
62 changes: 62 additions & 0 deletions label_studio_ml/examples/yolo/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
FROM pytorch/pytorch:2.1.2-cuda12.1-cudnn8-runtime
ARG DEBIAN_FRONTEND=noninteractive
ARG TEST_ENV

WORKDIR /app

RUN conda update conda -y

RUN --mount=type=cache,target="/var/cache/apt",sharing=locked \
--mount=type=cache,target="/var/lib/apt/lists",sharing=locked \
apt-get -y update \
&& apt-get install -y git \
&& apt-get install -y wget \
&& apt-get install -y g++ freeglut3-dev build-essential libx11-dev \
libxmu-dev libxi-dev libglu1-mesa libglu1-mesa-dev libfreeimage-dev \
&& apt-get -y install ffmpeg libsm6 libxext6 libffi-dev python3-dev python3-pip gcc

ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_CACHE_DIR=/.cache \
PORT=9090 \
WORKERS=2 \
THREADS=4 \
CUDA_HOME=/usr/local/cuda

RUN conda install -c "nvidia/label/cuda-12.1.1" cuda -y
ENV CUDA_HOME=/opt/conda \
TORCH_CUDA_ARCH_LIST="6.0;6.1;7.0;7.5;8.0;8.6+PTX;8.9;9.0"

# install base requirements
COPY requirements-base.txt .
RUN --mount=type=cache,target=${PIP_CACHE_DIR},sharing=locked \
pip install -r requirements-base.txt

# install model requirements
COPY requirements.txt .
RUN --mount=type=cache,target=${PIP_CACHE_DIR},sharing=locked \
pip3 install -r requirements.txt

# install test requirements if needed
COPY requirements-test.txt .
# build only when TEST_ENV="true"
RUN --mount=type=cache,target=${PIP_CACHE_DIR},sharing=locked \
if [ "$TEST_ENV" = "true" ]; then \
pip3 install -r requirements-test.txt; \
fi

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

CMD ["/app/start.sh"]
531 changes: 531 additions & 0 deletions label_studio_ml/examples/yolo/README.md

Large diffs are not rendered by default.

112 changes: 112 additions & 0 deletions label_studio_ml/examples/yolo/README_DEVELOP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
```mermaid
classDiagram
class ControlModel {
+str type
+ControlTag control
+str from_name
+str to_name
+str value
+YOLO model
+float score_threshold
+Optional[Dict[str, str]] label_map
+LabelStudioMLBase label_studio_ml_backend
+get_cached_model(path: str) YOLO
+create(cls, mlbackend: LabelStudioMLBase, control: ControlTag) ControlModel
+predict_regions(path: str) List[Dict]
+debug_plot(image)
}

class RectangleLabelsModel {
+predict_regions(path: str) List[Dict]
+create_rectangles(results, path) List[Dict]
+create_rotated_rectangles(results, path) List[Dict]
}

class PolygonLabelsModel {
+predict_regions(path: str) List[Dict]
+create_polygons(results, path) List[Dict]
}

class ChoicesModel {
+predict_regions(path: str) List[Dict]
+create_choices(results, path) List[Dict]
}

class VideoRectangleModel {
+predict_regions(path: str) List[Dict]
+create_video_rectangles(results, path) List[Dict]
+update_tracker_params(yaml_path: str, prefix: str) str | None
}

ControlModel <|-- RectangleLabelsModel
ControlModel <|-- PolygonLabelsModel
ControlModel <|-- ChoicesModel
ControlModel <|-- VideoRectangleModel
```

### 1. **Architecture Overview**

The architecture of the project is modular and is primarily centered around integrating YOLO-based models with Label Studio to automate the labeling of images and videos. The system is organized into several Python modules that interact with each other to perform this task. The main components of the architecture include:

1. **Main YOLO Integration Module (`model.py`)**:
- This is the central module that connects Label Studio with YOLO models. It handles the overall process of detecting control tags from Label Studio’s configuration, running predictions on tasks, and returning the predictions in the format that Label Studio expects.

2. **Control Models (`control_models/`)**:
- The control models are specialized modules that correspond to different annotation types in Label Studio (e.g., RectangleLabels, PolygonLabels, Choices, VideoRectangle). Each control model is responsible for handling specific types of annotations by using the YOLO model to predict the necessary regions or labels.

3. **Base Control Model (`control_models/base.py`)**:
- This is an abstract base class that provides common functionality for all control models. It handles tasks like loading the YOLO model, caching it for efficiency, and providing a template for the predict and create methods.

4. **Specific Control Models**:
- **RectangleLabelsModel (`control_models/rectanglelabels.py`)**: Handles bounding boxes (both simple and oriented bounding boxes) for images.
- **PolygonLabelsModel (`control_models/polygonlabels.py`)**: Deals with polygon annotations, typically used for segmentation tasks.
- **ChoicesModel (`control_models/choices.py`)**: Manages classification tasks where the model predicts one or more labels for the entire image.
- **VideoRectangleModel (`control_models/videorectangle.py`)**: Focuses on tracking objects across video frames, generating bounding boxes for each frame.

### 2. **Module Descriptions**

1. **`model.py` (Main YOLO Integration Module)**:
- **Purpose**: This module serves as the entry point for integrating YOLO models with Label Studio. It is responsible for setting up the YOLO model, detecting which control models are needed based on the Label Studio configuration, running predictions on tasks, and returning the results in the required format.
- **Key Functions**:
- `setup()`: Initializes the YOLO model parameters.
- `detect_control_models()`: Scans the Label Studio configuration to determine which control models to use.
- `predict()`: Runs predictions on a batch of tasks and formats the results for Label Studio.
- `fit()`: (Not implemented) Placeholder for updating the model based on new annotations.

2. **`control_models/base.py` (Base Control Model)**:
- **Purpose**: Provides a common interface and shared functionality for all specific control models. It includes methods for loading and caching the YOLO model, plotting results for debugging, and abstract methods that need to be implemented by subclasses.
- **Key Functions**:
- `get_cached_model()`: Retrieves a YOLO model from cache or loads it if not cached.
- `create()`: Factory method to instantiate a control model.
- `predict_regions()`: Abstract method to be implemented by subclasses to perform predictions.

3. **`control_models/choices.py` (ChoicesModel)**:
- **Purpose**: Handles classification tasks where the model predicts one or more labels for an image. It converts the YOLO model’s classification output into Label Studio’s choices format.
- **Key Functions**:
- `create_choices()`: Processes the YOLO model’s output and maps it to the Label Studio choices format.

4. **`control_models/rectanglelabels.py` (RectangleLabelsModel)**:
- **Purpose**: Manages the creation of bounding box annotations, both simple (axis-aligned) and oriented (rotated), from the YOLO model’s output.
- **Key Functions**:
- `create_rectangles()`: Converts the YOLO model’s bounding box predictions into Label Studio’s rectangle labels format.
- `create_rotated_rectangles()`: Handles oriented bounding boxes (OBB) by processing rotation angles and converting them to the required format.

5. **`control_models/polygonlabels.py` (PolygonLabelsModel)**:
- **Purpose**: Converts segmentation masks generated by the YOLO model into polygon annotations for Label Studio. This is useful for tasks where precise boundaries around objects are required.
- **Key Functions**:
- `create_polygons()`: Transforms the YOLO model’s segmentation output into polygon annotations.

6. **`control_models/videorectangle.py` (VideoRectangleModel)**:
- **Purpose**: Focuses on tracking objects across video frames, using YOLO’s tracking capabilities to generate bounding box annotations for each frame in a video sequence.
- **Key Functions**:
- `predict_regions()`: Runs YOLO’s tracking model on a video and converts the results into Label Studio’s video rectangle format.
- `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.

### **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.

- **Inter-Module Communication**: Each control model inherits from `ControlModel` in `base.py`, ensuring that they all share common methods for loading the YOLO model, handling predictions, and caching. The specific control models (e.g., RectangleLabelsModel, PolygonLabelsModel) implement the abstract methods defined in `ControlModel` to provide the specialized behavior needed for different types of annotations.

This modular structure allows for easy extension and modification, where new control models can be added to handle additional annotation types or new model architectures.
Loading