Update 4 main ops for paths and .run() (#3715)

* Add yolov5/ to path

* rename functions to run()

* cleanup

* rename fix

* CI fix

* cleanup find models/export.py
pull/3720/head
Glenn Jocher 2021-06-21 17:25:04 +02:00 committed by GitHub
parent 75c0ff43af
commit 1f69d12591
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 130 additions and 100 deletions

View File

@ -74,5 +74,5 @@ jobs:
python hubconf.py # hub python hubconf.py # hub
python models/yolo.py --cfg ${{ matrix.model }}.yaml # inspect python models/yolo.py --cfg ${{ matrix.model }}.yaml # inspect
python models/export.py --img 128 --batch 1 --weights ${{ matrix.model }}.pt # export python export.py --img 128 --batch 1 --weights ${{ matrix.model }}.pt # export
shell: bash shell: bash

View File

@ -52,5 +52,5 @@ jobs:
![CI CPU testing](https://github.com/ultralytics/yolov5/workflows/CI%20CPU%20testing/badge.svg) ![CI CPU testing](https://github.com/ultralytics/yolov5/workflows/CI%20CPU%20testing/badge.svg)
If this badge is green, all [YOLOv5 GitHub Actions](https://github.com/ultralytics/yolov5/actions) Continuous Integration (CI) tests are currently passing. CI tests verify correct operation of YOLOv5 training ([train.py](https://github.com/ultralytics/yolov5/blob/master/train.py)), testing ([test.py](https://github.com/ultralytics/yolov5/blob/master/test.py)), inference ([detect.py](https://github.com/ultralytics/yolov5/blob/master/detect.py)) and export ([export.py](https://github.com/ultralytics/yolov5/blob/master/models/export.py)) on MacOS, Windows, and Ubuntu every 24 hours and on every commit. If this badge is green, all [YOLOv5 GitHub Actions](https://github.com/ultralytics/yolov5/actions) Continuous Integration (CI) tests are currently passing. CI tests verify correct operation of YOLOv5 training ([train.py](https://github.com/ultralytics/yolov5/blob/master/train.py)), testing ([test.py](https://github.com/ultralytics/yolov5/blob/master/test.py)), inference ([detect.py](https://github.com/ultralytics/yolov5/blob/master/detect.py)) and export ([export.py](https://github.com/ultralytics/yolov5/blob/master/export.py)) on MacOS, Windows, and Ubuntu every 24 hours and on every commit.

View File

@ -1,4 +1,11 @@
"""Run inference with a YOLOv5 model on images, videos, directories, streams
Usage:
$ python path/to/detect.py --source path/to/img.jpg --weights yolov5s.pt --img 640
"""
import argparse import argparse
import sys
import time import time
from pathlib import Path from pathlib import Path
@ -6,6 +13,9 @@ import cv2
import torch import torch
import torch.backends.cudnn as cudnn import torch.backends.cudnn as cudnn
FILE = Path(__file__).absolute()
sys.path.append(FILE.parents[0].as_posix()) # add yolov5/ to path
from models.experimental import attempt_load from models.experimental import attempt_load
from utils.datasets import LoadStreams, LoadImages from utils.datasets import LoadStreams, LoadImages
from utils.general import check_img_size, check_requirements, check_imshow, colorstr, non_max_suppression, \ from utils.general import check_img_size, check_requirements, check_imshow, colorstr, non_max_suppression, \
@ -15,30 +25,30 @@ from utils.torch_utils import select_device, load_classifier, time_synchronized
@torch.no_grad() @torch.no_grad()
def detect(weights='yolov5s.pt', # model.pt path(s) def run(weights='yolov5s.pt', # model.pt path(s)
source='data/images', # file/dir/URL/glob, 0 for webcam source='data/images', # file/dir/URL/glob, 0 for webcam
imgsz=640, # inference size (pixels) imgsz=640, # inference size (pixels)
conf_thres=0.25, # confidence threshold conf_thres=0.25, # confidence threshold
iou_thres=0.45, # NMS IOU threshold iou_thres=0.45, # NMS IOU threshold
max_det=1000, # maximum detections per image max_det=1000, # maximum detections per image
device='', # cuda device, i.e. 0 or 0,1,2,3 or cpu device='', # cuda device, i.e. 0 or 0,1,2,3 or cpu
view_img=False, # show results view_img=False, # show results
save_txt=False, # save results to *.txt save_txt=False, # save results to *.txt
save_conf=False, # save confidences in --save-txt labels save_conf=False, # save confidences in --save-txt labels
save_crop=False, # save cropped prediction boxes save_crop=False, # save cropped prediction boxes
nosave=False, # do not save images/videos nosave=False, # do not save images/videos
classes=None, # filter by class: --class 0, or --class 0 2 3 classes=None, # filter by class: --class 0, or --class 0 2 3
agnostic_nms=False, # class-agnostic NMS agnostic_nms=False, # class-agnostic NMS
augment=False, # augmented inference augment=False, # augmented inference
update=False, # update all models update=False, # update all models
project='runs/detect', # save results to project/name project='runs/detect', # save results to project/name
name='exp', # save results to project/name name='exp', # save results to project/name
exist_ok=False, # existing project/name ok, do not increment exist_ok=False, # existing project/name ok, do not increment
line_thickness=3, # bounding box thickness (pixels) line_thickness=3, # bounding box thickness (pixels)
hide_labels=False, # hide labels hide_labels=False, # hide labels
hide_conf=False, # hide confidences hide_conf=False, # hide confidences
half=False, # use FP16 half-precision inference half=False, # use FP16 half-precision inference
): ):
save_img = not nosave and not source.endswith('.txt') # save inference images save_img = not nosave and not source.endswith('.txt') # save inference images
webcam = source.isnumeric() or source.endswith('.txt') or source.lower().startswith( webcam = source.isnumeric() or source.endswith('.txt') or source.lower().startswith(
('rtsp://', 'rtmp://', 'http://', 'https://')) ('rtsp://', 'rtmp://', 'http://', 'https://'))
@ -204,7 +214,7 @@ def parse_opt():
def main(opt): def main(opt):
print(colorstr('detect: ') + ', '.join(f'{k}={v}' for k, v in vars(opt).items())) print(colorstr('detect: ') + ', '.join(f'{k}={v}' for k, v in vars(opt).items()))
check_requirements(exclude=('tensorboard', 'thop')) check_requirements(exclude=('tensorboard', 'thop'))
detect(**vars(opt)) run(**vars(opt))
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,7 +1,7 @@
"""Export a YOLOv5 *.pt model to TorchScript, ONNX, CoreML formats """Export a YOLOv5 *.pt model to TorchScript, ONNX, CoreML formats
Usage: Usage:
$ python path/to/models/export.py --weights yolov5s.pt --img 640 --batch 1 $ python path/to/export.py --weights yolov5s.pt --img 640 --batch 1
""" """
import argparse import argparse
@ -14,7 +14,7 @@ import torch.nn as nn
from torch.utils.mobile_optimizer import optimize_for_mobile from torch.utils.mobile_optimizer import optimize_for_mobile
FILE = Path(__file__).absolute() FILE = Path(__file__).absolute()
sys.path.append(FILE.parents[1].as_posix()) # add yolov5/ to path sys.path.append(FILE.parents[0].as_posix()) # add yolov5/ to path
from models.common import Conv from models.common import Conv
from models.yolo import Detect from models.yolo import Detect
@ -24,19 +24,19 @@ from utils.general import colorstr, check_img_size, check_requirements, file_siz
from utils.torch_utils import select_device from utils.torch_utils import select_device
def export(weights='./yolov5s.pt', # weights path def run(weights='./yolov5s.pt', # weights path
img_size=(640, 640), # image (height, width) img_size=(640, 640), # image (height, width)
batch_size=1, # batch size batch_size=1, # batch size
device='cpu', # cuda device, i.e. 0 or 0,1,2,3 or cpu device='cpu', # cuda device, i.e. 0 or 0,1,2,3 or cpu
include=('torchscript', 'onnx', 'coreml'), # include formats include=('torchscript', 'onnx', 'coreml'), # include formats
half=False, # FP16 half-precision export half=False, # FP16 half-precision export
inplace=False, # set YOLOv5 Detect() inplace=True inplace=False, # set YOLOv5 Detect() inplace=True
train=False, # model.train() mode train=False, # model.train() mode
optimize=False, # TorchScript: optimize for mobile optimize=False, # TorchScript: optimize for mobile
dynamic=False, # ONNX: dynamic axes dynamic=False, # ONNX: dynamic axes
simplify=False, # ONNX: simplify model simplify=False, # ONNX: simplify model
opset_version=12, # ONNX: opset version opset_version=12, # ONNX: opset version
): ):
t = time.time() t = time.time()
include = [x.lower() for x in include] include = [x.lower() for x in include]
img_size *= 2 if len(img_size) == 1 else 1 # expand img_size *= 2 if len(img_size) == 1 else 1 # expand
@ -165,7 +165,7 @@ def parse_opt():
def main(opt): def main(opt):
set_logging() set_logging()
print(colorstr('export: ') + ', '.join(f'{k}={v}' for k, v in vars(opt).items())) print(colorstr('export: ') + ', '.join(f'{k}={v}' for k, v in vars(opt).items()))
export(**vars(opt)) run(**vars(opt))
if __name__ == "__main__": if __name__ == "__main__":

72
test.py
View File

@ -1,6 +1,13 @@
"""Test a trained YOLOv5 model accuracy on a custom dataset
Usage:
$ python path/to/test.py --data coco128.yaml --weights yolov5s.pt --img 640
"""
import argparse import argparse
import json import json
import os import os
import sys
from pathlib import Path from pathlib import Path
from threading import Thread from threading import Thread
@ -9,6 +16,9 @@ import torch
import yaml import yaml
from tqdm import tqdm from tqdm import tqdm
FILE = Path(__file__).absolute()
sys.path.append(FILE.parents[0].as_posix()) # add yolov5/ to path
from models.experimental import attempt_load from models.experimental import attempt_load
from utils.datasets import create_dataloader from utils.datasets import create_dataloader
from utils.general import coco80_to_coco91_class, check_dataset, check_file, check_img_size, check_requirements, \ from utils.general import coco80_to_coco91_class, check_dataset, check_file, check_img_size, check_requirements, \
@ -19,32 +29,32 @@ from utils.torch_utils import select_device, time_synchronized
@torch.no_grad() @torch.no_grad()
def test(data, def run(data,
weights=None, # model.pt path(s) weights=None, # model.pt path(s)
batch_size=32, # batch size batch_size=32, # batch size
imgsz=640, # inference size (pixels) imgsz=640, # inference size (pixels)
conf_thres=0.001, # confidence threshold conf_thres=0.001, # confidence threshold
iou_thres=0.6, # NMS IoU threshold iou_thres=0.6, # NMS IoU threshold
task='val', # train, val, test, speed or study task='val', # train, val, test, speed or study
device='', # cuda device, i.e. 0 or 0,1,2,3 or cpu device='', # cuda device, i.e. 0 or 0,1,2,3 or cpu
single_cls=False, # treat as single-class dataset single_cls=False, # treat as single-class dataset
augment=False, # augmented inference augment=False, # augmented inference
verbose=False, # verbose output verbose=False, # verbose output
save_txt=False, # save results to *.txt save_txt=False, # save results to *.txt
save_hybrid=False, # save label+prediction hybrid results to *.txt save_hybrid=False, # save label+prediction hybrid results to *.txt
save_conf=False, # save confidences in --save-txt labels save_conf=False, # save confidences in --save-txt labels
save_json=False, # save a cocoapi-compatible JSON results file save_json=False, # save a cocoapi-compatible JSON results file
project='runs/test', # save to project/name project='runs/test', # save to project/name
name='exp', # save to project/name name='exp', # save to project/name
exist_ok=False, # existing project/name ok, do not increment exist_ok=False, # existing project/name ok, do not increment
half=True, # use FP16 half-precision inference half=True, # use FP16 half-precision inference
model=None, model=None,
dataloader=None, dataloader=None,
save_dir=Path(''), save_dir=Path(''),
plots=True, plots=True,
wandb_logger=None, wandb_logger=None,
compute_loss=None, compute_loss=None,
): ):
# Initialize/load model and set device # Initialize/load model and set device
training = model is not None training = model is not None
if training: # called by train.py if training: # called by train.py
@ -327,12 +337,12 @@ def main(opt):
check_requirements(exclude=('tensorboard', 'thop')) check_requirements(exclude=('tensorboard', 'thop'))
if opt.task in ('train', 'val', 'test'): # run normally if opt.task in ('train', 'val', 'test'): # run normally
test(**vars(opt)) run(**vars(opt))
elif opt.task == 'speed': # speed benchmarks elif opt.task == 'speed': # speed benchmarks
for w in opt.weights if isinstance(opt.weights, list) else [opt.weights]: for w in opt.weights if isinstance(opt.weights, list) else [opt.weights]:
test(opt.data, weights=w, batch_size=opt.batch_size, imgsz=opt.imgsz, conf_thres=.25, iou_thres=.45, run(opt.data, weights=w, batch_size=opt.batch_size, imgsz=opt.imgsz, conf_thres=.25, iou_thres=.45,
save_json=False, plots=False) save_json=False, plots=False)
elif opt.task == 'study': # run over a range of settings and save/plot elif opt.task == 'study': # run over a range of settings and save/plot
# python test.py --task study --data coco.yaml --iou 0.7 --weights yolov5s.pt yolov5m.pt yolov5l.pt yolov5x.pt # python test.py --task study --data coco.yaml --iou 0.7 --weights yolov5s.pt yolov5m.pt yolov5l.pt yolov5x.pt
@ -342,8 +352,8 @@ def main(opt):
y = [] # y axis y = [] # y axis
for i in x: # img-size for i in x: # img-size
print(f'\nRunning {f} point {i}...') print(f'\nRunning {f} point {i}...')
r, _, t = test(opt.data, weights=w, batch_size=opt.batch_size, imgsz=i, conf_thres=opt.conf_thres, r, _, t = run(opt.data, weights=w, batch_size=opt.batch_size, imgsz=i, conf_thres=opt.conf_thres,
iou_thres=opt.iou_thres, save_json=opt.save_json, plots=False) iou_thres=opt.iou_thres, save_json=opt.save_json, plots=False)
y.append(r + t) # results and times y.append(r + t) # results and times
np.savetxt(f, y, fmt='%10.4g') # save np.savetxt(f, y, fmt='%10.4g') # save
os.system('zip -r study.zip study_*.txt') os.system('zip -r study.zip study_*.txt')

View File

@ -1,8 +1,15 @@
"""Train a YOLOv5 model on a custom dataset
Usage:
$ python path/to/train.py --data coco128.yaml --weights yolov5s.pt --img 640
"""
import argparse import argparse
import logging import logging
import math import math
import os import os
import random import random
import sys
import time import time
import warnings import warnings
from copy import deepcopy from copy import deepcopy
@ -22,6 +29,9 @@ from torch.nn.parallel import DistributedDataParallel as DDP
from torch.utils.tensorboard import SummaryWriter from torch.utils.tensorboard import SummaryWriter
from tqdm import tqdm from tqdm import tqdm
FILE = Path(__file__).absolute()
sys.path.append(FILE.parents[0].as_posix()) # add yolov5/ to path
import test # for end-of-epoch mAP import test # for end-of-epoch mAP
from models.experimental import attempt_load from models.experimental import attempt_load
from models.yolo import Model from models.yolo import Model
@ -89,7 +99,7 @@ def train(hyp, # path/to/hyp.yaml or hyp dictionary
# W&B # W&B
opt.hyp = hyp # add hyperparameters opt.hyp = hyp # add hyperparameters
run_id = torch.load(weights).get('wandb_id') if weights.endswith('.pt') and os.path.isfile(weights) else None run_id = torch.load(weights).get('wandb_id') if weights.endswith('.pt') and os.path.isfile(weights) else None
run_id = run_id if opt.resume else None # start fresh run if transfer learning run_id = run_id if opt.resume else None # start fresh run if transfer learning
wandb_logger = WandbLogger(opt, save_dir.stem, run_id, data_dict) wandb_logger = WandbLogger(opt, save_dir.stem, run_id, data_dict)
loggers['wandb'] = wandb_logger.wandb loggers['wandb'] = wandb_logger.wandb
if loggers['wandb']: if loggers['wandb']:
@ -375,18 +385,18 @@ def train(hyp, # path/to/hyp.yaml or hyp dictionary
final_epoch = epoch + 1 == epochs final_epoch = epoch + 1 == epochs
if not notest or final_epoch: # Calculate mAP if not notest or final_epoch: # Calculate mAP
wandb_logger.current_epoch = epoch + 1 wandb_logger.current_epoch = epoch + 1
results, maps, _ = test.test(data_dict, results, maps, _ = test.run(data_dict,
batch_size=batch_size // WORLD_SIZE * 2, batch_size=batch_size // WORLD_SIZE * 2,
imgsz=imgsz_test, imgsz=imgsz_test,
model=ema.ema, model=ema.ema,
single_cls=single_cls, single_cls=single_cls,
dataloader=testloader, dataloader=testloader,
save_dir=save_dir, save_dir=save_dir,
save_json=is_coco and final_epoch, save_json=is_coco and final_epoch,
verbose=nc < 50 and final_epoch, verbose=nc < 50 and final_epoch,
plots=plots and final_epoch, plots=plots and final_epoch,
wandb_logger=wandb_logger, wandb_logger=wandb_logger,
compute_loss=compute_loss) compute_loss=compute_loss)
# Write # Write
with open(results_file, 'a') as f: with open(results_file, 'a') as f:
@ -443,17 +453,17 @@ def train(hyp, # path/to/hyp.yaml or hyp dictionary
if not evolve: if not evolve:
if is_coco: # COCO dataset if is_coco: # COCO dataset
for m in [last, best] if best.exists() else [last]: # speed, mAP tests for m in [last, best] if best.exists() else [last]: # speed, mAP tests
results, _, _ = test.test(data, results, _, _ = test.run(data,
batch_size=batch_size // WORLD_SIZE * 2, batch_size=batch_size // WORLD_SIZE * 2,
imgsz=imgsz_test, imgsz=imgsz_test,
conf_thres=0.001, conf_thres=0.001,
iou_thres=0.7, iou_thres=0.7,
model=attempt_load(m, device).half(), model=attempt_load(m, device).half(),
single_cls=single_cls, single_cls=single_cls,
dataloader=testloader, dataloader=testloader,
save_dir=save_dir, save_dir=save_dir,
save_json=True, save_json=True,
plots=False) plots=False)
# Strip optimizers # Strip optimizers
for f in last, best: for f in last, best:

4
tutorial.ipynb vendored
View File

@ -1125,7 +1125,7 @@
"\n", "\n",
"![CI CPU testing](https://github.com/ultralytics/yolov5/workflows/CI%20CPU%20testing/badge.svg)\n", "![CI CPU testing](https://github.com/ultralytics/yolov5/workflows/CI%20CPU%20testing/badge.svg)\n",
"\n", "\n",
"If this badge is green, all [YOLOv5 GitHub Actions](https://github.com/ultralytics/yolov5/actions) Continuous Integration (CI) tests are currently passing. CI tests verify correct operation of YOLOv5 training ([train.py](https://github.com/ultralytics/yolov5/blob/master/train.py)), testing ([test.py](https://github.com/ultralytics/yolov5/blob/master/test.py)), inference ([detect.py](https://github.com/ultralytics/yolov5/blob/master/detect.py)) and export ([export.py](https://github.com/ultralytics/yolov5/blob/master/models/export.py)) on MacOS, Windows, and Ubuntu every 24 hours and on every commit.\n" "If this badge is green, all [YOLOv5 GitHub Actions](https://github.com/ultralytics/yolov5/actions) Continuous Integration (CI) tests are currently passing. CI tests verify correct operation of YOLOv5 training ([train.py](https://github.com/ultralytics/yolov5/blob/master/train.py)), testing ([test.py](https://github.com/ultralytics/yolov5/blob/master/test.py)), inference ([detect.py](https://github.com/ultralytics/yolov5/blob/master/detect.py)) and export ([export.py](https://github.com/ultralytics/yolov5/blob/master/export.py)) on MacOS, Windows, and Ubuntu every 24 hours and on every commit.\n"
] ]
}, },
{ {
@ -1212,7 +1212,7 @@
" done\n", " done\n",
" python hubconf.py # hub\n", " python hubconf.py # hub\n",
" python models/yolo.py --cfg $m.yaml # inspect\n", " python models/yolo.py --cfg $m.yaml # inspect\n",
" python models/export.py --weights $m.pt --img 640 --batch 1 # export\n", " python export.py --weights $m.pt --img 640 --batch 1 # export\n",
"done" "done"
], ],
"execution_count": null, "execution_count": null,