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

Example for object detection with ultralytics YOLO v8 model #2508

Merged
merged 13 commits into from
Aug 25, 2023
62 changes: 62 additions & 0 deletions examples/object_detector/yolo/yolov8/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Object Detection using Ultralytics's pretrained YOLOv8(yolov8n) model.


Install `ultralytics` using
```
python -m pip install -r requirements.txt
```

In this example, we are using the YOLOv8 Nano model from ultralytics.Downlaod the pretrained weights from [Ultralytics](https://docs.ultralytics.com/models/yolov8/#supported-modes)

```
wget https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8n.pt
```

## Create a model archive file for Yolov8n model

```
torch-model-archiver --model-name yolov8n --version 1.0 --serialized-file yolov8n.pt --handler custom_handler.py
```

```
mkdir model_store
mv yolov8n.mar model_store/.
```

## Start TorchServe and register the model


```
torchserve --start --model-store model_store --ncs
curl -X POST "localhost:8081/models?model_name=yolov8n&url=yolov8n.mar&initial_workers=4&batch_size=2"
```

results in

```
{
"status": "Model \"yolov8n\" Version: 1.0 registered with 4 initial workers"
}
```

## Run Inference

Here we are counting the number of detected objects in the image. You can change the post-process method in the handler to return the bounding box coordinates

```
curl http://127.0.0.1:8080/predictions/yolov8n -T persons.jpg & curl http://127.0.0.1:8080/predictions/yolov8n -T bus.jpg
```

gives the output

```
{
"person": 4,
agunapal marked this conversation as resolved.
Show resolved Hide resolved
"handbag": 3,
"bench": 3
}{
"person": 4,
"bus": 1,
"stop sign": 1
}
```
Binary file added examples/object_detector/yolo/yolov8/bus.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
88 changes: 88 additions & 0 deletions examples/object_detector/yolo/yolov8/custom_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import logging
import os
from collections import defaultdict

import torch
from torchvision import transforms
from ultralytics import YOLO

from ts.torch_handler.object_detector import ObjectDetector
from ts.utils.util import load_label_mapping

logger = logging.getLogger(__name__)

try:
import torch_xla.core.xla_model as xm

XLA_AVAILABLE = True
except ImportError as error:
XLA_AVAILABLE = False


class Yolov8Handler(ObjectDetector):
image_processing = transforms.Compose(
[transforms.Resize(640), transforms.CenterCrop(640), transforms.ToTensor()]
)

def __init__(self):
super(Yolov8Handler, self).__init__()

def initialize(self, context):
agunapal marked this conversation as resolved.
Show resolved Hide resolved
properties = context.system_properties
if torch.cuda.is_available() and properties.get("gpu_id") is not None:
self.map_location = "cuda"
self.device = torch.device(
self.map_location + ":" + str(properties.get("gpu_id"))
)
elif XLA_AVAILABLE:
self.device = xm.xla_device()
agunapal marked this conversation as resolved.
Show resolved Hide resolved
else:
self.map_location = "cpu"
self.device = torch.device(self.map_location)

self.manifest = context.manifest

model_dir = properties.get("model_dir")
self.model_pt_path = None
if "serializedFile" in self.manifest["model"]:
serialized_file = self.manifest["model"]["serializedFile"]
self.model_pt_path = os.path.join(model_dir, serialized_file)

self.model = self._load_torchscript_model(self.model_pt_path)
agunapal marked this conversation as resolved.
Show resolved Hide resolved

logger.debug("Model file %s loaded successfully", self.model_pt_path)

# Load class mapping for classifiers
mapping_file_path = os.path.join(model_dir, "index_to_name.json")
self.mapping = load_label_mapping(mapping_file_path)
agunapal marked this conversation as resolved.
Show resolved Hide resolved

self.initialized = True

def _load_torchscript_model(self, model_pt_path):
agunapal marked this conversation as resolved.
Show resolved Hide resolved
"""Loads the PyTorch model and returns the NN model object.

Args:
model_pt_path (str): denotes the path of the model file.

Returns:
(NN Model Object) : Loads the model object.
"""
# TODO: remove this method if https://github.com/pytorch/text/issues/1793 gets resolved

model = YOLO(model_pt_path)
model.to(self.device)
return model

def postprocess(self, res):
output = []
for data in res:
classes = data.boxes.cls.tolist()
names = data.names

result = defaultdict(int)

for cls in classes:
agunapal marked this conversation as resolved.
Show resolved Hide resolved
result[names[int(cls)]] += 1
output.append(result)

return output
Binary file added examples/object_detector/yolo/yolov8/persons.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions examples/object_detector/yolo/yolov8/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ultralytics>=8.0.144
Loading