bplusplus 0.1.1__py3-none-any.whl → 1.1.0__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.
Potentially problematic release.
This version of bplusplus might be problematic. Click here for more details.
- bplusplus/__init__.py +5 -3
- bplusplus/{collect_images.py → collect.py} +3 -3
- bplusplus/prepare.py +573 -0
- bplusplus/train_validate.py +8 -64
- bplusplus/yolov5detect/__init__.py +1 -0
- bplusplus/yolov5detect/detect.py +444 -0
- bplusplus/yolov5detect/export.py +1530 -0
- bplusplus/yolov5detect/insect.yaml +8 -0
- bplusplus/yolov5detect/models/__init__.py +0 -0
- bplusplus/yolov5detect/models/common.py +1109 -0
- bplusplus/yolov5detect/models/experimental.py +130 -0
- bplusplus/yolov5detect/models/hub/anchors.yaml +56 -0
- bplusplus/yolov5detect/models/hub/yolov3-spp.yaml +52 -0
- bplusplus/yolov5detect/models/hub/yolov3-tiny.yaml +42 -0
- bplusplus/yolov5detect/models/hub/yolov3.yaml +52 -0
- bplusplus/yolov5detect/models/hub/yolov5-bifpn.yaml +49 -0
- bplusplus/yolov5detect/models/hub/yolov5-fpn.yaml +43 -0
- bplusplus/yolov5detect/models/hub/yolov5-p2.yaml +55 -0
- bplusplus/yolov5detect/models/hub/yolov5-p34.yaml +42 -0
- bplusplus/yolov5detect/models/hub/yolov5-p6.yaml +57 -0
- bplusplus/yolov5detect/models/hub/yolov5-p7.yaml +68 -0
- bplusplus/yolov5detect/models/hub/yolov5-panet.yaml +49 -0
- bplusplus/yolov5detect/models/hub/yolov5l6.yaml +61 -0
- bplusplus/yolov5detect/models/hub/yolov5m6.yaml +61 -0
- bplusplus/yolov5detect/models/hub/yolov5n6.yaml +61 -0
- bplusplus/yolov5detect/models/hub/yolov5s-LeakyReLU.yaml +50 -0
- bplusplus/yolov5detect/models/hub/yolov5s-ghost.yaml +49 -0
- bplusplus/yolov5detect/models/hub/yolov5s-transformer.yaml +49 -0
- bplusplus/yolov5detect/models/hub/yolov5s6.yaml +61 -0
- bplusplus/yolov5detect/models/hub/yolov5x6.yaml +61 -0
- bplusplus/yolov5detect/models/segment/yolov5l-seg.yaml +49 -0
- bplusplus/yolov5detect/models/segment/yolov5m-seg.yaml +49 -0
- bplusplus/yolov5detect/models/segment/yolov5n-seg.yaml +49 -0
- bplusplus/yolov5detect/models/segment/yolov5s-seg.yaml +49 -0
- bplusplus/yolov5detect/models/segment/yolov5x-seg.yaml +49 -0
- bplusplus/yolov5detect/models/tf.py +797 -0
- bplusplus/yolov5detect/models/yolo.py +495 -0
- bplusplus/yolov5detect/models/yolov5l.yaml +49 -0
- bplusplus/yolov5detect/models/yolov5m.yaml +49 -0
- bplusplus/yolov5detect/models/yolov5n.yaml +49 -0
- bplusplus/yolov5detect/models/yolov5s.yaml +49 -0
- bplusplus/yolov5detect/models/yolov5x.yaml +49 -0
- bplusplus/yolov5detect/utils/__init__.py +97 -0
- bplusplus/yolov5detect/utils/activations.py +134 -0
- bplusplus/yolov5detect/utils/augmentations.py +448 -0
- bplusplus/yolov5detect/utils/autoanchor.py +175 -0
- bplusplus/yolov5detect/utils/autobatch.py +70 -0
- bplusplus/yolov5detect/utils/aws/__init__.py +0 -0
- bplusplus/yolov5detect/utils/aws/mime.sh +26 -0
- bplusplus/yolov5detect/utils/aws/resume.py +41 -0
- bplusplus/yolov5detect/utils/aws/userdata.sh +27 -0
- bplusplus/yolov5detect/utils/callbacks.py +72 -0
- bplusplus/yolov5detect/utils/dataloaders.py +1385 -0
- bplusplus/yolov5detect/utils/docker/Dockerfile +73 -0
- bplusplus/yolov5detect/utils/docker/Dockerfile-arm64 +40 -0
- bplusplus/yolov5detect/utils/docker/Dockerfile-cpu +42 -0
- bplusplus/yolov5detect/utils/downloads.py +136 -0
- bplusplus/yolov5detect/utils/flask_rest_api/README.md +70 -0
- bplusplus/yolov5detect/utils/flask_rest_api/example_request.py +17 -0
- bplusplus/yolov5detect/utils/flask_rest_api/restapi.py +49 -0
- bplusplus/yolov5detect/utils/general.py +1294 -0
- bplusplus/yolov5detect/utils/google_app_engine/Dockerfile +25 -0
- bplusplus/yolov5detect/utils/google_app_engine/additional_requirements.txt +6 -0
- bplusplus/yolov5detect/utils/google_app_engine/app.yaml +16 -0
- bplusplus/yolov5detect/utils/loggers/__init__.py +476 -0
- bplusplus/yolov5detect/utils/loggers/clearml/README.md +222 -0
- bplusplus/yolov5detect/utils/loggers/clearml/__init__.py +0 -0
- bplusplus/yolov5detect/utils/loggers/clearml/clearml_utils.py +230 -0
- bplusplus/yolov5detect/utils/loggers/clearml/hpo.py +90 -0
- bplusplus/yolov5detect/utils/loggers/comet/README.md +250 -0
- bplusplus/yolov5detect/utils/loggers/comet/__init__.py +551 -0
- bplusplus/yolov5detect/utils/loggers/comet/comet_utils.py +151 -0
- bplusplus/yolov5detect/utils/loggers/comet/hpo.py +126 -0
- bplusplus/yolov5detect/utils/loggers/comet/optimizer_config.json +135 -0
- bplusplus/yolov5detect/utils/loggers/wandb/__init__.py +0 -0
- bplusplus/yolov5detect/utils/loggers/wandb/wandb_utils.py +210 -0
- bplusplus/yolov5detect/utils/loss.py +259 -0
- bplusplus/yolov5detect/utils/metrics.py +381 -0
- bplusplus/yolov5detect/utils/plots.py +517 -0
- bplusplus/yolov5detect/utils/segment/__init__.py +0 -0
- bplusplus/yolov5detect/utils/segment/augmentations.py +100 -0
- bplusplus/yolov5detect/utils/segment/dataloaders.py +366 -0
- bplusplus/yolov5detect/utils/segment/general.py +160 -0
- bplusplus/yolov5detect/utils/segment/loss.py +198 -0
- bplusplus/yolov5detect/utils/segment/metrics.py +225 -0
- bplusplus/yolov5detect/utils/segment/plots.py +152 -0
- bplusplus/yolov5detect/utils/torch_utils.py +482 -0
- bplusplus/yolov5detect/utils/triton.py +90 -0
- bplusplus-1.1.0.dist-info/METADATA +179 -0
- bplusplus-1.1.0.dist-info/RECORD +92 -0
- bplusplus/build_model.py +0 -38
- bplusplus-0.1.1.dist-info/METADATA +0 -97
- bplusplus-0.1.1.dist-info/RECORD +0 -8
- {bplusplus-0.1.1.dist-info → bplusplus-1.1.0.dist-info}/LICENSE +0 -0
- {bplusplus-0.1.1.dist-info → bplusplus-1.1.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# YOLOv5 🚀 by Ultralytics, AGPL-3.0 license
|
|
2
|
+
# Builds ultralytics/yolov5:latest image on DockerHub https://hub.docker.com/r/ultralytics/yolov5
|
|
3
|
+
# Image is CUDA-optimized for YOLOv5 single/multi-GPU training and inference
|
|
4
|
+
|
|
5
|
+
# Start FROM PyTorch image https://hub.docker.com/r/pytorch/pytorch
|
|
6
|
+
FROM pytorch/pytorch:2.0.0-cuda11.7-cudnn8-runtime
|
|
7
|
+
|
|
8
|
+
# Downloads to user config dir
|
|
9
|
+
ADD https://ultralytics.com/assets/Arial.ttf https://ultralytics.com/assets/Arial.Unicode.ttf /root/.config/Ultralytics/
|
|
10
|
+
|
|
11
|
+
# Install linux packages
|
|
12
|
+
ENV DEBIAN_FRONTEND noninteractive
|
|
13
|
+
RUN apt update
|
|
14
|
+
RUN TZ=Etc/UTC apt install -y tzdata
|
|
15
|
+
RUN apt install --no-install-recommends -y gcc git zip curl htop libgl1 libglib2.0-0 libpython3-dev gnupg
|
|
16
|
+
# RUN alias python=python3
|
|
17
|
+
|
|
18
|
+
# Security updates
|
|
19
|
+
# https://security.snyk.io/vuln/SNYK-UBUNTU1804-OPENSSL-3314796
|
|
20
|
+
RUN apt upgrade --no-install-recommends -y openssl
|
|
21
|
+
|
|
22
|
+
# Create working directory
|
|
23
|
+
RUN rm -rf /usr/src/app && mkdir -p /usr/src/app
|
|
24
|
+
WORKDIR /usr/src/app
|
|
25
|
+
|
|
26
|
+
# Copy contents
|
|
27
|
+
COPY . /usr/src/app
|
|
28
|
+
|
|
29
|
+
# Install pip packages
|
|
30
|
+
COPY requirements.txt .
|
|
31
|
+
RUN python3 -m pip install --upgrade pip wheel
|
|
32
|
+
RUN pip install --no-cache -r requirements.txt albumentations comet gsutil notebook \
|
|
33
|
+
coremltools onnx onnx-simplifier onnxruntime 'openvino-dev>=2023.0'
|
|
34
|
+
# tensorflow tensorflowjs \
|
|
35
|
+
|
|
36
|
+
# Set environment variables
|
|
37
|
+
ENV OMP_NUM_THREADS=1
|
|
38
|
+
|
|
39
|
+
# Cleanup
|
|
40
|
+
ENV DEBIAN_FRONTEND teletype
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# Usage Examples -------------------------------------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
# Build and Push
|
|
46
|
+
# t=ultralytics/yolov5:latest && sudo docker build -f utils/docker/Dockerfile -t $t . && sudo docker push $t
|
|
47
|
+
|
|
48
|
+
# Pull and Run
|
|
49
|
+
# t=ultralytics/yolov5:latest && sudo docker pull $t && sudo docker run -it --ipc=host --gpus all $t
|
|
50
|
+
|
|
51
|
+
# Pull and Run with local directory access
|
|
52
|
+
# t=ultralytics/yolov5:latest && sudo docker pull $t && sudo docker run -it --ipc=host --gpus all -v "$(pwd)"/datasets:/usr/src/datasets $t
|
|
53
|
+
|
|
54
|
+
# Kill all
|
|
55
|
+
# sudo docker kill $(sudo docker ps -q)
|
|
56
|
+
|
|
57
|
+
# Kill all image-based
|
|
58
|
+
# sudo docker kill $(sudo docker ps -qa --filter ancestor=ultralytics/yolov5:latest)
|
|
59
|
+
|
|
60
|
+
# DockerHub tag update
|
|
61
|
+
# t=ultralytics/yolov5:latest tnew=ultralytics/yolov5:v6.2 && sudo docker pull $t && sudo docker tag $t $tnew && sudo docker push $tnew
|
|
62
|
+
|
|
63
|
+
# Clean up
|
|
64
|
+
# sudo docker system prune -a --volumes
|
|
65
|
+
|
|
66
|
+
# Update Ubuntu drivers
|
|
67
|
+
# https://www.maketecheasier.com/install-nvidia-drivers-ubuntu/
|
|
68
|
+
|
|
69
|
+
# DDP test
|
|
70
|
+
# python -m torch.distributed.run --nproc_per_node 2 --master_port 1 train.py --epochs 3
|
|
71
|
+
|
|
72
|
+
# GCP VM from Image
|
|
73
|
+
# docker.io/ultralytics/yolov5:latest
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# YOLOv5 🚀 by Ultralytics, AGPL-3.0 license
|
|
2
|
+
# Builds ultralytics/yolov5:latest-arm64 image on DockerHub https://hub.docker.com/r/ultralytics/yolov5
|
|
3
|
+
# Image is aarch64-compatible for Apple M1 and other ARM architectures i.e. Jetson Nano and Raspberry Pi
|
|
4
|
+
|
|
5
|
+
# Start FROM Ubuntu image https://hub.docker.com/_/ubuntu
|
|
6
|
+
FROM arm64v8/ubuntu:22.10
|
|
7
|
+
|
|
8
|
+
# Downloads to user config dir
|
|
9
|
+
ADD https://ultralytics.com/assets/Arial.ttf https://ultralytics.com/assets/Arial.Unicode.ttf /root/.config/Ultralytics/
|
|
10
|
+
|
|
11
|
+
# Install linux packages
|
|
12
|
+
ENV DEBIAN_FRONTEND noninteractive
|
|
13
|
+
RUN apt update
|
|
14
|
+
RUN TZ=Etc/UTC apt install -y tzdata
|
|
15
|
+
RUN apt install --no-install-recommends -y python3-pip git zip curl htop gcc libgl1 libglib2.0-0 libpython3-dev
|
|
16
|
+
# RUN alias python=python3
|
|
17
|
+
|
|
18
|
+
# Install pip packages
|
|
19
|
+
COPY requirements.txt .
|
|
20
|
+
RUN python3 -m pip install --upgrade pip wheel
|
|
21
|
+
RUN pip install --no-cache -r requirements.txt albumentations gsutil notebook \
|
|
22
|
+
coremltools onnx onnxruntime
|
|
23
|
+
# tensorflow-aarch64 tensorflowjs \
|
|
24
|
+
|
|
25
|
+
# Create working directory
|
|
26
|
+
RUN mkdir -p /usr/src/app
|
|
27
|
+
WORKDIR /usr/src/app
|
|
28
|
+
|
|
29
|
+
# Copy contents
|
|
30
|
+
COPY . /usr/src/app
|
|
31
|
+
ENV DEBIAN_FRONTEND teletype
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# Usage Examples -------------------------------------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
# Build and Push
|
|
37
|
+
# t=ultralytics/yolov5:latest-arm64 && sudo docker build --platform linux/arm64 -f utils/docker/Dockerfile-arm64 -t $t . && sudo docker push $t
|
|
38
|
+
|
|
39
|
+
# Pull and Run
|
|
40
|
+
# t=ultralytics/yolov5:latest-arm64 && sudo docker pull $t && sudo docker run -it --ipc=host -v "$(pwd)"/datasets:/usr/src/datasets $t
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# YOLOv5 🚀 by Ultralytics, AGPL-3.0 license
|
|
2
|
+
# Builds ultralytics/yolov5:latest-cpu image on DockerHub https://hub.docker.com/r/ultralytics/yolov5
|
|
3
|
+
# Image is CPU-optimized for ONNX, OpenVINO and PyTorch YOLOv5 deployments
|
|
4
|
+
|
|
5
|
+
# Start FROM Ubuntu image https://hub.docker.com/_/ubuntu
|
|
6
|
+
FROM ubuntu:23.10
|
|
7
|
+
|
|
8
|
+
# Downloads to user config dir
|
|
9
|
+
ADD https://ultralytics.com/assets/Arial.ttf https://ultralytics.com/assets/Arial.Unicode.ttf /root/.config/Ultralytics/
|
|
10
|
+
|
|
11
|
+
# Install linux packages
|
|
12
|
+
# g++ required to build 'tflite_support' and 'lap' packages, libusb-1.0-0 required for 'tflite_support' package
|
|
13
|
+
RUN apt update \
|
|
14
|
+
&& apt install --no-install-recommends -y python3-pip git zip curl htop libgl1 libglib2.0-0 libpython3-dev gnupg g++ libusb-1.0-0
|
|
15
|
+
# RUN alias python=python3
|
|
16
|
+
|
|
17
|
+
# Remove python3.11/EXTERNALLY-MANAGED or use 'pip install --break-system-packages' avoid 'externally-managed-environment' Ubuntu nightly error
|
|
18
|
+
RUN rm -rf /usr/lib/python3.11/EXTERNALLY-MANAGED
|
|
19
|
+
|
|
20
|
+
# Install pip packages
|
|
21
|
+
COPY requirements.txt .
|
|
22
|
+
RUN python3 -m pip install --upgrade pip wheel
|
|
23
|
+
RUN pip install --no-cache -r requirements.txt albumentations gsutil notebook \
|
|
24
|
+
coremltools onnx onnx-simplifier onnxruntime 'openvino-dev>=2023.0' \
|
|
25
|
+
# tensorflow tensorflowjs \
|
|
26
|
+
--extra-index-url https://download.pytorch.org/whl/cpu
|
|
27
|
+
|
|
28
|
+
# Create working directory
|
|
29
|
+
RUN mkdir -p /usr/src/app
|
|
30
|
+
WORKDIR /usr/src/app
|
|
31
|
+
|
|
32
|
+
# Copy contents
|
|
33
|
+
COPY . /usr/src/app
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# Usage Examples -------------------------------------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
# Build and Push
|
|
39
|
+
# t=ultralytics/yolov5:latest-cpu && sudo docker build -f utils/docker/Dockerfile-cpu -t $t . && sudo docker push $t
|
|
40
|
+
|
|
41
|
+
# Pull and Run
|
|
42
|
+
# t=ultralytics/yolov5:latest-cpu && sudo docker pull $t && sudo docker run -it --ipc=host -v "$(pwd)"/datasets:/usr/src/datasets $t
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Ultralytics YOLOv5 🚀, AGPL-3.0 license
|
|
2
|
+
"""Download utils."""
|
|
3
|
+
|
|
4
|
+
import logging
|
|
5
|
+
import subprocess
|
|
6
|
+
import urllib
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import requests
|
|
10
|
+
import torch
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def is_url(url, check=True):
|
|
14
|
+
"""Determines if a string is a URL and optionally checks its existence online, returning a boolean."""
|
|
15
|
+
try:
|
|
16
|
+
url = str(url)
|
|
17
|
+
result = urllib.parse.urlparse(url)
|
|
18
|
+
assert all([result.scheme, result.netloc]) # check if is url
|
|
19
|
+
return (urllib.request.urlopen(url).getcode() == 200) if check else True # check if exists online
|
|
20
|
+
except (AssertionError, urllib.request.HTTPError):
|
|
21
|
+
return False
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def gsutil_getsize(url=""):
|
|
25
|
+
"""
|
|
26
|
+
Returns the size in bytes of a file at a Google Cloud Storage URL using `gsutil du`.
|
|
27
|
+
|
|
28
|
+
Returns 0 if the command fails or output is empty.
|
|
29
|
+
"""
|
|
30
|
+
output = subprocess.check_output(["gsutil", "du", url], shell=True, encoding="utf-8")
|
|
31
|
+
return int(output.split()[0]) if output else 0
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def url_getsize(url="https://ultralytics.com/images/bus.jpg"):
|
|
35
|
+
"""Returns the size in bytes of a downloadable file at a given URL; defaults to -1 if not found."""
|
|
36
|
+
response = requests.head(url, allow_redirects=True)
|
|
37
|
+
return int(response.headers.get("content-length", -1))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def curl_download(url, filename, *, silent: bool = False) -> bool:
|
|
41
|
+
"""Download a file from a url to a filename using curl."""
|
|
42
|
+
silent_option = "sS" if silent else "" # silent
|
|
43
|
+
proc = subprocess.run(
|
|
44
|
+
[
|
|
45
|
+
"curl",
|
|
46
|
+
"-#",
|
|
47
|
+
f"-{silent_option}L",
|
|
48
|
+
url,
|
|
49
|
+
"--output",
|
|
50
|
+
filename,
|
|
51
|
+
"--retry",
|
|
52
|
+
"9",
|
|
53
|
+
"-C",
|
|
54
|
+
"-",
|
|
55
|
+
]
|
|
56
|
+
)
|
|
57
|
+
return proc.returncode == 0
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def safe_download(file, url, url2=None, min_bytes=1e0, error_msg=""):
|
|
61
|
+
"""
|
|
62
|
+
Downloads a file from a URL (or alternate URL) to a specified path if file is above a minimum size.
|
|
63
|
+
|
|
64
|
+
Removes incomplete downloads.
|
|
65
|
+
"""
|
|
66
|
+
from utils.general import LOGGER
|
|
67
|
+
|
|
68
|
+
file = Path(file)
|
|
69
|
+
assert_msg = f"Downloaded file '{file}' does not exist or size is < min_bytes={min_bytes}"
|
|
70
|
+
try: # url1
|
|
71
|
+
LOGGER.info(f"Downloading {url} to {file}...")
|
|
72
|
+
torch.hub.download_url_to_file(url, str(file), progress=LOGGER.level <= logging.INFO)
|
|
73
|
+
assert file.exists() and file.stat().st_size > min_bytes, assert_msg # check
|
|
74
|
+
except Exception as e: # url2
|
|
75
|
+
if file.exists():
|
|
76
|
+
file.unlink() # remove partial downloads
|
|
77
|
+
LOGGER.info(f"ERROR: {e}\nRe-attempting {url2 or url} to {file}...")
|
|
78
|
+
# curl download, retry and resume on fail
|
|
79
|
+
curl_download(url2 or url, file)
|
|
80
|
+
finally:
|
|
81
|
+
if not file.exists() or file.stat().st_size < min_bytes: # check
|
|
82
|
+
if file.exists():
|
|
83
|
+
file.unlink() # remove partial downloads
|
|
84
|
+
LOGGER.info(f"ERROR: {assert_msg}\n{error_msg}")
|
|
85
|
+
LOGGER.info("")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def attempt_download(file, repo="ultralytics/yolov5", release="v7.0"):
|
|
89
|
+
"""Downloads a file from GitHub release assets or via direct URL if not found locally, supporting backup
|
|
90
|
+
versions.
|
|
91
|
+
"""
|
|
92
|
+
from utils.general import LOGGER
|
|
93
|
+
|
|
94
|
+
def github_assets(repository, version="latest"):
|
|
95
|
+
"""Fetches GitHub repository release tag and asset names using the GitHub API."""
|
|
96
|
+
if version != "latest":
|
|
97
|
+
version = f"tags/{version}" # i.e. tags/v7.0
|
|
98
|
+
response = requests.get(f"https://api.github.com/repos/{repository}/releases/{version}").json() # github api
|
|
99
|
+
return response["tag_name"], [x["name"] for x in response["assets"]] # tag, assets
|
|
100
|
+
|
|
101
|
+
file = Path(str(file).strip().replace("'", ""))
|
|
102
|
+
if not file.exists():
|
|
103
|
+
# URL specified
|
|
104
|
+
name = Path(urllib.parse.unquote(str(file))).name # decode '%2F' to '/' etc.
|
|
105
|
+
if str(file).startswith(("http:/", "https:/")): # download
|
|
106
|
+
url = str(file).replace(":/", "://") # Pathlib turns :// -> :/
|
|
107
|
+
file = name.split("?")[0] # parse authentication https://url.com/file.txt?auth...
|
|
108
|
+
if Path(file).is_file():
|
|
109
|
+
LOGGER.info(f"Found {url} locally at {file}") # file already exists
|
|
110
|
+
else:
|
|
111
|
+
safe_download(file=file, url=url, min_bytes=1e5)
|
|
112
|
+
return file
|
|
113
|
+
|
|
114
|
+
# GitHub assets
|
|
115
|
+
assets = [f"yolov5{size}{suffix}.pt" for size in "nsmlx" for suffix in ("", "6", "-cls", "-seg")] # default
|
|
116
|
+
try:
|
|
117
|
+
tag, assets = github_assets(repo, release)
|
|
118
|
+
except Exception:
|
|
119
|
+
try:
|
|
120
|
+
tag, assets = github_assets(repo) # latest release
|
|
121
|
+
except Exception:
|
|
122
|
+
try:
|
|
123
|
+
tag = subprocess.check_output("git tag", shell=True, stderr=subprocess.STDOUT).decode().split()[-1]
|
|
124
|
+
except Exception:
|
|
125
|
+
tag = release
|
|
126
|
+
|
|
127
|
+
if name in assets:
|
|
128
|
+
file.parent.mkdir(parents=True, exist_ok=True) # make parent dir (if required)
|
|
129
|
+
safe_download(
|
|
130
|
+
file,
|
|
131
|
+
url=f"https://github.com/{repo}/releases/download/{tag}/{name}",
|
|
132
|
+
min_bytes=1e5,
|
|
133
|
+
error_msg=f"{file} missing, try downloading from https://github.com/{repo}/releases/{tag}",
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
return str(file)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Flask REST API
|
|
2
|
+
|
|
3
|
+
[REST](https://en.wikipedia.org/wiki/Representational_state_transfer) [API](https://en.wikipedia.org/wiki/API)s are commonly used to expose Machine Learning (ML) models to other services. This folder contains an example REST API created using Flask to expose the YOLOv5s model from [PyTorch Hub](https://pytorch.org/hub/ultralytics_yolov5/).
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
[Flask](https://palletsprojects.com/projects/flask/) is required. Install with:
|
|
8
|
+
|
|
9
|
+
```shell
|
|
10
|
+
$ pip install Flask
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Run
|
|
14
|
+
|
|
15
|
+
After Flask installation run:
|
|
16
|
+
|
|
17
|
+
```shell
|
|
18
|
+
$ python3 restapi.py --port 5000
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Then use [curl](https://curl.se/) to perform a request:
|
|
22
|
+
|
|
23
|
+
```shell
|
|
24
|
+
$ curl -X POST -F image=@zidane.jpg 'http://localhost:5000/v1/object-detection/yolov5s'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The model inference results are returned as a JSON response:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
[
|
|
31
|
+
{
|
|
32
|
+
"class": 0,
|
|
33
|
+
"confidence": 0.8900438547,
|
|
34
|
+
"height": 0.9318675399,
|
|
35
|
+
"name": "person",
|
|
36
|
+
"width": 0.3264600933,
|
|
37
|
+
"xcenter": 0.7438579798,
|
|
38
|
+
"ycenter": 0.5207948685
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"class": 0,
|
|
42
|
+
"confidence": 0.8440024257,
|
|
43
|
+
"height": 0.7155083418,
|
|
44
|
+
"name": "person",
|
|
45
|
+
"width": 0.6546785235,
|
|
46
|
+
"xcenter": 0.427829951,
|
|
47
|
+
"ycenter": 0.6334488392
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"class": 27,
|
|
51
|
+
"confidence": 0.3771208823,
|
|
52
|
+
"height": 0.3902671337,
|
|
53
|
+
"name": "tie",
|
|
54
|
+
"width": 0.0696444362,
|
|
55
|
+
"xcenter": 0.3675483763,
|
|
56
|
+
"ycenter": 0.7991207838
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"class": 27,
|
|
60
|
+
"confidence": 0.3527112305,
|
|
61
|
+
"height": 0.1540903747,
|
|
62
|
+
"name": "tie",
|
|
63
|
+
"width": 0.0336618312,
|
|
64
|
+
"xcenter": 0.7814827561,
|
|
65
|
+
"ycenter": 0.5065554976
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
An example python script to perform inference using [requests](https://docs.python-requests.org/en/master/) is given in `example_request.py`
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Ultralytics YOLOv5 🚀, AGPL-3.0 license
|
|
2
|
+
"""Perform test request."""
|
|
3
|
+
|
|
4
|
+
import pprint
|
|
5
|
+
|
|
6
|
+
import requests
|
|
7
|
+
|
|
8
|
+
DETECTION_URL = "http://localhost:5000/v1/object-detection/yolov5s"
|
|
9
|
+
IMAGE = "zidane.jpg"
|
|
10
|
+
|
|
11
|
+
# Read image
|
|
12
|
+
with open(IMAGE, "rb") as f:
|
|
13
|
+
image_data = f.read()
|
|
14
|
+
|
|
15
|
+
response = requests.post(DETECTION_URL, files={"image": image_data}).json()
|
|
16
|
+
|
|
17
|
+
pprint.pprint(response)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Ultralytics YOLOv5 🚀, AGPL-3.0 license
|
|
2
|
+
"""Run a Flask REST API exposing one or more YOLOv5s models."""
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import io
|
|
6
|
+
|
|
7
|
+
import torch
|
|
8
|
+
from flask import Flask, request
|
|
9
|
+
from PIL import Image
|
|
10
|
+
|
|
11
|
+
app = Flask(__name__)
|
|
12
|
+
models = {}
|
|
13
|
+
|
|
14
|
+
DETECTION_URL = "/v1/object-detection/<model>"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@app.route(DETECTION_URL, methods=["POST"])
|
|
18
|
+
def predict(model):
|
|
19
|
+
"""Predict and return object detections in JSON format given an image and model name via a Flask REST API POST
|
|
20
|
+
request.
|
|
21
|
+
"""
|
|
22
|
+
if request.method != "POST":
|
|
23
|
+
return
|
|
24
|
+
|
|
25
|
+
if request.files.get("image"):
|
|
26
|
+
# Method 1
|
|
27
|
+
# with request.files["image"] as f:
|
|
28
|
+
# im = Image.open(io.BytesIO(f.read()))
|
|
29
|
+
|
|
30
|
+
# Method 2
|
|
31
|
+
im_file = request.files["image"]
|
|
32
|
+
im_bytes = im_file.read()
|
|
33
|
+
im = Image.open(io.BytesIO(im_bytes))
|
|
34
|
+
|
|
35
|
+
if model in models:
|
|
36
|
+
results = models[model](im, size=640) # reduce size=320 for faster inference
|
|
37
|
+
return results.pandas().xyxy[0].to_json(orient="records")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
if __name__ == "__main__":
|
|
41
|
+
parser = argparse.ArgumentParser(description="Flask API exposing YOLOv5 model")
|
|
42
|
+
parser.add_argument("--port", default=5000, type=int, help="port number")
|
|
43
|
+
parser.add_argument("--model", nargs="+", default=["yolov5s"], help="model(s) to run, i.e. --model yolov5n yolov5s")
|
|
44
|
+
opt = parser.parse_args()
|
|
45
|
+
|
|
46
|
+
for m in opt.model:
|
|
47
|
+
models[m] = torch.hub.load("ultralytics/yolov5", m, force_reload=True, skip_validation=True)
|
|
48
|
+
|
|
49
|
+
app.run(host="0.0.0.0", port=opt.port) # debug=True causes Restarting with stat
|