PyTorch ํ๋ธ
์ด ๊ฐ์ด๋๋ ๋ค์์์ YOLOv5 ๐๋ฅผ ๋ก๋ํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํฉ๋๋ค. PyTorch https:// pytorch.org/hub/ultralytics_yolov5.
์์ํ๊ธฐ ์ ์
์๊ตฌ ์ฌํญ.txt๋ฅผ Python>=3.8.0 ํ๊ฒฝ์ ํฌํจํ์ฌ PyTorch>=1.8. ๋ชจ๋ธ ๋ฐ ๋ฐ์ดํฐ ์ธํธ๋ ์ต์ YOLOv5 ๋ฆด๋ฆฌ์ค์์ ์๋์ผ๋ก ๋ค์ด๋ก๋๋ฉ๋๋ค.
ํ๋กํ: ๋ณต์ ๋ https://github.com/ultralytics / yolov5 ๋ถํ์ ๐
PyTorch ํ๋ธ์ YOLOv5 ๋ก๋
๊ฐ๋จํ ์
์ด ์๋ PyTorch ํ๋ธ์์ ์ฌ์ ํ์ต๋ YOLOv5s ๋ชจ๋ธ์ ๋ค์๊ณผ ๊ฐ์ด ๋ก๋ํฉ๋๋ค. model
๋ฅผ ํธ์ถํ๊ณ ์ถ๋ก ์ ์ํด ์ด๋ฏธ์ง๋ฅผ ์ ๋ฌํฉ๋๋ค. 'yolov5s'
์ ๊ฐ์ฅ ๊ฐ๋ณ๊ณ ๋น ๋ฅธ YOLOv5 ๋ชจ๋ธ์
๋๋ค. ์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ ๋ชจ๋ธ์ ๋ํ ์์ธํ ๋ด์ฉ์ README.
import torch
# Model
model = torch.hub.load("ultralytics/yolov5", "yolov5s")
# Image
im = "https://ultralytics.com/images/zidane.jpg"
# Inference
results = model(im)
results.pandas().xyxy[0]
# xmin ymin xmax ymax confidence class name
# 0 749.50 43.50 1148.0 704.5 0.874023 0 person
# 1 433.50 433.50 517.5 714.5 0.687988 27 tie
# 2 114.75 195.75 1095.0 708.0 0.624512 0 person
# 3 986.00 304.00 1028.0 420.0 0.286865 27 tie
์์ธํ ์์
์ด ์๋ ๋ค์์ ๋ณด์ฌ์ค๋๋ค. ์ผ๊ด ์ถ๋ก ์ ํจ๊ป PIL ๊ทธ๋ฆฌ๊ณ OpenCV ์ด๋ฏธ์ง ์์ค. results
๋ ์ธ์ ๋ฅผ ์ฝ์๋ก ์ด๋ํฉ๋๋ค, ์ ์ฅ ์ runs/hub
, ํ์ ๋ฅผ ์ฌ์ฉํ์ฌ ์ง์๋๋ ํ๊ฒฝ์์ ํ๋ฉด์ ํ์ํ๊ณ ํ
์ ๋๋ ํ๋ค ๋ฐ์ดํฐํ๋ ์.
import cv2
import torch
from PIL import Image
# Model
model = torch.hub.load("ultralytics/yolov5", "yolov5s")
# Images
for f in "zidane.jpg", "bus.jpg":
torch.hub.download_url_to_file("https://ultralytics.com/images/" + f, f) # download 2 images
im1 = Image.open("zidane.jpg") # PIL image
im2 = cv2.imread("bus.jpg")[..., ::-1] # OpenCV image (BGR to RGB)
# Inference
results = model([im1, im2], size=640) # batch of images
# Results
results.print()
results.save() # or .show()
results.xyxy[0] # im1 predictions (tensor)
results.pandas().xyxy[0] # im1 predictions (pandas)
# xmin ymin xmax ymax confidence class name
# 0 749.50 43.50 1148.0 704.5 0.874023 0 person
# 1 433.50 433.50 517.5 714.5 0.687988 27 tie
# 2 114.75 195.75 1095.0 708.0 0.624512 0 person
# 3 986.00 304.00 1028.0 420.0 0.286865 27 tie
๋ชจ๋ ์ถ๋ก ์ต์
์ ๋ค์์ ์ฐธ์กฐํ์ธ์. YOLOv5 AutoShape()
์์ผ๋ก ๋ฉ์๋.
์ถ๋ก ์ค์
YOLOv5 ๋ชจ๋ธ์๋ ์ ๋ขฐ๋ ์๊ณ๊ฐ, IoU ์๊ณ๊ฐ ๋ฑ๊ณผ ๊ฐ์ ๋ค์ํ ์ถ๋ก ์์ฑ์ด ํฌํจ๋์ด ์์ผ๋ฉฐ, ์ด๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค:
model.conf = 0.25 # NMS confidence threshold
iou = 0.45 # NMS IoU threshold
agnostic = False # NMS class-agnostic
multi_label = False # NMS multiple labels per box
classes = None # (optional list) filter by class, i.e. = [0, 15, 16] for COCO persons, cats and dogs
max_det = 1000 # maximum number of detections per image
amp = False # Automatic Mixed Precision (AMP) inference
results = model(im, size=320) # custom inference size
์ฅ์น
๋ชจ๋ธ์ ์์ฑ ํ ๋ชจ๋ ๋๋ฐ์ด์ค๋ก ์ ์กํ ์ ์์ต๋๋ค:
๋ชจ๋ธ์ ์ง์ ๋ง๋ค ์๋ ์์ต๋๋ค. device
:
ํ๋กํ: ์ ๋ ฅ ์ด๋ฏธ์ง๋ ์ถ๋ก ์ ์ ์ฌ๋ฐ๋ฅธ ๋ชจ๋ธ ์ฅ์น๋ก ์๋ ์ ์ก๋ฉ๋๋ค.
๋ฌด์ ์ถ๋ ฅ
๋ค์์ ์ฌ์ฉํ์ฌ ๋ชจ๋ธ์ ์๋์ผ๋ก ๋ก๋ํ ์ ์์ต๋๋ค. _verbose=False
:
์ ๋ ฅ ์ฑ๋
๊ธฐ๋ณธ 3๊ฐ๊ฐ ์๋ 4๊ฐ์ ์ ๋ ฅ ์ฑ๋๋ก ์ฌ์ ํ์ต๋ YOLOv5s ๋ชจ๋ธ์ ๋ก๋ํฉ๋๋ค:
์ด ๊ฒฝ์ฐ ๋ชจ๋ธ์ ๋ ์ด์ ์ฌ์ ํ์ต๋ ์ ๋ ฅ ๋ ์ด์ด์ ๋์ผํ ๋ชจ์์ด ์๋ ์ฒซ ๋ฒ์งธ ์ ๋ ฅ ๋ ์ด์ด๋ฅผ ์ ์ธํ๊ณ ์ฌ์ ํ์ต๋ ๊ฐ์ค์น๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ์ ๋ ฅ ๋ ์ด์ด๋ ๋ฌด์์ ๊ฐ์ค์น๋ก ์ด๊ธฐํ๋ ์ํ๋ก ์ ์ง๋ฉ๋๋ค.
์์ ์
๊ธฐ๋ณธ๊ฐ 80์ด ์๋ 10๊ฐ์ ์ถ๋ ฅ ํด๋์ค๋ก ์ฌ์ ํ์ต๋ YOLOv5s ๋ชจ๋ธ์ ๋ก๋ํฉ๋๋ค:
์ด ๊ฒฝ์ฐ ๋ชจ๋ธ์ ๋ ์ด์ ์ฌ์ ํ์ต๋ ์ถ๋ ฅ ๋ ์ด์ด์ ๋์ผํ ๋ชจ์์ด ์๋ ์ถ๋ ฅ ๋ ์ด์ด๋ฅผ ์ ์ธํ ์ฌ์ ํ์ต๋ ๊ฐ์ค์น๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ์ถ๋ ฅ ๋ ์ด์ด๋ ๋ฌด์์ ๊ฐ์ค์น๋ก ์ด๊ธฐํ๋ ์ํ๋ก ์ ์ง๋ฉ๋๋ค.
๊ฐ์ ์ฌ์ฅ์
์์ ๋จ๊ณ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด ์ค์ force_reload=True
๊ธฐ์กด ์บ์๋ฅผ ์ญ์ ํ๊ณ PyTorch ํ๋ธ์์ ์ต์ YOLOv5 ๋ฒ์ ์ ๊ฐ์ ๋ก ์๋ก ๋ค์ด๋ก๋ํ๋ฉด ๋์์ด ๋ ์ ์์ต๋๋ค.
์คํฌ๋ฆฐ์ท ์ถ๋ก
๋ฐ์คํฌํฑ ํ๋ฉด์์ ์ถ๋ก ์ ์คํํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ํ์ธ์:
import torch
from PIL import ImageGrab
# Model
model = torch.hub.load("ultralytics/yolov5", "yolov5s")
# Image
im = ImageGrab.grab() # take a screenshot
# Inference
results = model(im)
๋ค์คGPU ์ถ๋ก
YOLOv5 ๋ชจ๋ธ์ ์ค๋ ๋ ์ถ๋ก ์ ํตํด ์ฌ๋ฌ GPU์ ๋ณ๋ ฌ๋ก ๋ก๋ํ ์ ์์ต๋๋ค:
import threading
import torch
def run(model, im):
"""Performs inference on an image using a given model and saves the output; model must support `.save()` method."""
results = model(im)
results.save()
# Models
model0 = torch.hub.load("ultralytics/yolov5", "yolov5s", device=0)
model1 = torch.hub.load("ultralytics/yolov5", "yolov5s", device=1)
# Inference
threading.Thread(target=run, args=[model0, "https://ultralytics.com/images/zidane.jpg"], daemon=True).start()
threading.Thread(target=run, args=[model1, "https://ultralytics.com/images/bus.jpg"], daemon=True).start()
๊ต์ก
์ถ๋ก ์ด ์๋ ํธ๋ ์ด๋์ ์ํด YOLOv5 ๋ชจ๋ธ์ ๋ก๋ํ๋ ค๋ฉด autoshape=False
. ๋ฌด์์๋ก ์ด๊ธฐํ๋ ๊ฐ์ค์น๋ก ๋ชจ๋ธ์ ๋ก๋ํ๋ ค๋ฉด(์ฒ์๋ถํฐ ํ์ตํ๋ ค๋ฉด) ๋ค์์ ์ฌ์ฉํฉ๋๋ค. pretrained=False
. ์ด ๊ฒฝ์ฐ ์์ฒด ๊ต์ก ์คํฌ๋ฆฝํธ๋ฅผ ์ ๊ณตํด์ผ ํฉ๋๋ค. ๋๋ YOLOv5 ์ฌ์ฉ์ ์ง์ ๋ฐ์ดํฐ ์์ต์ ๊ต์ก ๋ชจ๋ธ ํธ๋ ์ด๋์ ์ํด
import torch
model = torch.hub.load("ultralytics/yolov5", "yolov5s", autoshape=False) # load pretrained
model = torch.hub.load("ultralytics/yolov5", "yolov5s", autoshape=False, pretrained=False) # load scratch
Base64 ๊ฒฐ๊ณผ
API ์๋น์ค์ ํจ๊ป ์ฌ์ฉํ์ธ์. ์์ธํ ๋ด์ฉ์ https://github.com/ultralytics/yolov5 /pull/2291 ๋ฐ ํ๋ผ์คํฌ REST API ์์ ๋ฅผ ์ฐธ์กฐํ์ธ์.
results = model(im) # inference
results.ims # array of original images (as np array) passed to model for inference
results.render() # updates results.ims with boxes and labels
for im in results.ims:
buffered = BytesIO()
im_base64 = Image.fromarray(im)
im_base64.save(buffered, format="JPEG")
print(base64.b64encode(buffered.getvalue()).decode("utf-8")) # base64 encoded image with results
์๋ฆฐ ๊ฒฐ๊ณผ
๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๊ณ ๊ฐ์ง ํฌ๋กญ์ผ๋ก ์ ์ฅํ ์ ์์ต๋๋ค:
ํ๋ค ๊ฒฐ๊ณผ
๊ฒฐ๊ณผ๋ ํ๋ค์ค ๋ฐ์ดํฐํ๋ ์์ผ๋ก ๋ฐํํ ์ ์์ต๋๋ค:
ํ๋ค ์ถ๋ ฅ(ํ์ฅํ๋ ค๋ฉด ํด๋ฆญ)
์ ๋ ฌ๋ ๊ฒฐ๊ณผ
๊ฒฐ๊ณผ๋ฅผ ์ด๋ณ๋ก ์ ๋ ฌํ ์ ์์ต๋๋ค(์: ์ฐจ๋ ๋ฒํธํ ์ซ์ ๊ฐ์ง๋ฅผ ์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ(x์ถ)์ผ๋ก ์ ๋ ฌ):
๋ฐ์ค ์๋ฅด๊ธฐ ๊ฒฐ๊ณผ
๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๊ณ ๊ฐ์ง ํฌ๋กญ์ผ๋ก ์ ์ฅํ ์ ์์ต๋๋ค:
JSON ๊ฒฐ๊ณผ
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ด ๋ณํ๋ ํ JSON ํ์์ผ๋ก ๋ฐํ๋ ์ ์์ต๋๋ค. .pandas()
๋ฐ์ดํฐ ํ๋ ์์ ์ฌ์ฉํ๋ .to_json()
๋ฉ์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค. JSON ํ์์ ๋ค์์ ์ฌ์ฉํ์ฌ ์์ ํ ์ ์์ต๋๋ค. orient
์ธ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. ํ๋ค ๋ณด๊ธฐ .to_json()
๋ฌธ์ ๋ฅผ ์ฐธ์กฐํ์ธ์.
results = model(ims) # inference
results.pandas().xyxy[0].to_json(orient="records") # JSON img1 predictions
JSON ์ถ๋ ฅ(ํ์ฅํ๋ ค๋ฉด ํด๋ฆญ)
[
{
"xmin": 749.5,
"ymin": 43.5,
"xmax": 1148.0,
"ymax": 704.5,
"confidence": 0.8740234375,
"class": 0,
"name": "person"
},
{
"xmin": 433.5,
"ymin": 433.5,
"xmax": 517.5,
"ymax": 714.5,
"confidence": 0.6879882812,
"class": 27,
"name": "tie"
},
{
"xmin": 115.25,
"ymin": 195.75,
"xmax": 1096.0,
"ymax": 708.0,
"confidence": 0.6254882812,
"class": 0,
"name": "person"
},
{
"xmin": 986.0,
"ymin": 304.0,
"xmax": 1028.0,
"ymax": 420.0,
"confidence": 0.2873535156,
"class": 27,
"name": "tie"
}
]
์ฌ์ฉ์ ์ง์ ๋ชจ๋ธ
์ด ์์ ์์๋ ์ฌ์ฉ์ ์ง์ 20ํด๋์ค VOC-ํ๋ จ๋ YOLOv5s ๋ชจ๋ธ 'best.pt'
PyTorch ํ๋ธ.
import torch
model = torch.hub.load("ultralytics/yolov5", "custom", path="path/to/best.pt") # local model
model = torch.hub.load("path/to/yolov5", "custom", path="path/to/best.pt", source="local") # local repo
TensorRT, ONNX ๋ฐ OpenVINO ๋ชจ๋ธ
PyTorch Hub๋ ์ฌ์ฉ์ ์ง์ ํ์ต๋ ๋ชจ๋ธ์ ํฌํจํ์ฌ ๋๋ถ๋ถ์ YOLOv5 ๋ด๋ณด๋ด๊ธฐ ํ์์ ๋ํ ์ถ๋ก ์ ์ง์ํฉ๋๋ค. ๋ชจ๋ธ ๋ด๋ณด๋ด๊ธฐ์ ๋ํ ์์ธํ ๋ด์ฉ์ TFLite, ONNX, CoreML, TensorRT ๋ด๋ณด๋ด๊ธฐ ํํ ๋ฆฌ์ผ์ ์ฐธ์กฐํ์ธ์.
๐ก ProTip: TensorRT ๋ PyTorch ๋ณด๋ค ์ต๋ 2~5๋ฐฐ ๋น ๋ฅผ ์ ์์ต๋๋ค. GPU ๋ฒค์น๋งํฌ ๐ก ProTip: ONNX ๋ฐ OpenVINO ๋ PyTorch ๋ณด๋ค ์ต๋ 2-3๋ฐฐ ๋น ๋ฅผ ์ ์์ต๋๋ค. CPU ๋ฒค์น๋งํฌ
import torch
model = torch.hub.load("ultralytics/yolov5", "custom", path="yolov5s.pt") # PyTorch
model = torch.hub.load("ultralytics/yolov5", "custom", path="yolov5s.torchscript") # TorchScript
model = torch.hub.load("ultralytics/yolov5", "custom", path="yolov5s.onnx") # ONNX
model = torch.hub.load("ultralytics/yolov5", "custom", path="yolov5s_openvino_model/") # OpenVINO
model = torch.hub.load("ultralytics/yolov5", "custom", path="yolov5s.engine") # TensorRT
model = torch.hub.load("ultralytics/yolov5", "custom", path="yolov5s.mlmodel") # CoreML (macOS-only)
model = torch.hub.load("ultralytics/yolov5", "custom", path="yolov5s.tflite") # TFLite
model = torch.hub.load("ultralytics/yolov5", "custom", path="yolov5s_paddle_model/") # PaddlePaddle
์ง์ ํ๊ฒฝ
Ultralytics ๋ ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ ๋ค์ํ ํ๊ฒฝ์ ์ ๊ณตํ๋ฉฐ, ๊ฐ ํ๊ฒฝ์๋ ๋ค์๊ณผ ๊ฐ์ ํ์ ์ข ์์ฑ์ด ์ฌ์ ์ค์น๋์ด ์์ต๋๋ค. CUDA, CUDNN, Python, ๋ฐ PyTorch์ ๊ฐ์ ํ์ ์ข ์ ์์๋ฅผ ์ค์นํ์ฌ ํ๋ก์ ํธ๋ฅผ ์์ํ ์ ์์ต๋๋ค.
- ๋ฌด๋ฃ GPU ๋ ธํธ๋ถ:
- Google Cloud: GCP ๋น ๋ฅธ ์์ ๊ฐ์ด๋
- Amazon: AWS ๋น ๋ฅธ ์์ ๊ฐ์ด๋
- Azure: AzureML ๋น ๋ฅธ ์์ ๊ฐ์ด๋
- Docker: Docker ๋น ๋ฅธ ์์ ๊ฐ์ด๋
ํ๋ก์ ํธ ์ํ
์ด ๋ฐฐ์ง๋ ๋ชจ๋ YOLOv5 GitHub Actions ์ง์์ ํตํฉ(CI) ํ ์คํธ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ํต๊ณผ๋์์์ ๋ํ๋ ๋๋ค. ์ด๋ฌํ CI ํ ์คํธ๋ ๊ต์ก, ๊ฒ์ฆ, ์ถ๋ก , ๋ด๋ณด๋ด๊ธฐ ๋ฐ ๋ฒค์น๋งํฌ ๋ฑ ๋ค์ํ ์ฃผ์ ์ธก๋ฉด์์ YOLOv5 ์ ๊ธฐ๋ฅ๊ณผ ์ฑ๋ฅ์ ์๊ฒฉํ๊ฒ ํ์ธํฉ๋๋ค. 24์๊ฐ๋ง๋ค ๊ทธ๋ฆฌ๊ณ ์๋ก์ด ์ปค๋ฐ์ด ์์ ๋๋ง๋ค ํ ์คํธ๋ฅผ ์ํํ์ฌ macOS, Windows ๋ฐ Ubuntu์์ ์ผ๊ด๋๊ณ ์์ ์ ์ธ ์๋์ ๋ณด์ฅํฉ๋๋ค.