Skip to content

Commit 4e04cb0

Browse files
authored
Allow YOLOv5 execution from arbitrary cwd (ultralytics#4954)
* Allow YOLOv5 execution from arbitrary `cwd` * Fix str bugs
1 parent a820b43 commit 4e04cb0

File tree

4 files changed

+23
-17
lines changed

4 files changed

+23
-17
lines changed

detect.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
ROOT = FILE.parents[0] # YOLOv5 root directory
2020
if str(ROOT) not in sys.path:
2121
sys.path.append(str(ROOT)) # add ROOT to PATH
22+
ROOT = ROOT.relative_to(Path.cwd()) # relative
2223

2324
from models.experimental import attempt_load
2425
from utils.datasets import LoadImages, LoadStreams
@@ -30,8 +31,8 @@
3031

3132

3233
@torch.no_grad()
33-
def run(weights='yolov5s.pt', # model.pt path(s)
34-
source='data/images', # file/dir/URL/glob, 0 for webcam
34+
def run(weights=ROOT / 'yolov5s.pt', # model.pt path(s)
35+
source=ROOT / 'data/images', # file/dir/URL/glob, 0 for webcam
3536
imgsz=640, # inference size (pixels)
3637
conf_thres=0.25, # confidence threshold
3738
iou_thres=0.45, # NMS IOU threshold
@@ -47,14 +48,15 @@ def run(weights='yolov5s.pt', # model.pt path(s)
4748
augment=False, # augmented inference
4849
visualize=False, # visualize features
4950
update=False, # update all models
50-
project='runs/detect', # save results to project/name
51+
project=ROOT / 'runs/detect', # save results to project/name
5152
name='exp', # save results to project/name
5253
exist_ok=False, # existing project/name ok, do not increment
5354
line_thickness=3, # bounding box thickness (pixels)
5455
hide_labels=False, # hide labels
5556
hide_conf=False, # hide confidences
5657
half=False, # use FP16 half-precision inference
5758
):
59+
source = str(source)
5860
save_img = not nosave and not source.endswith('.txt') # save inference images
5961
webcam = source.isnumeric() or source.endswith('.txt') or source.lower().startswith(
6062
('rtsp://', 'rtmp://', 'http://', 'https://'))
@@ -254,8 +256,8 @@ def wrap_frozen_graph(gd, inputs, outputs):
254256

255257
def parse_opt():
256258
parser = argparse.ArgumentParser()
257-
parser.add_argument('--weights', nargs='+', type=str, default='yolov5s.pt', help='model path(s)')
258-
parser.add_argument('--source', type=str, default='data/images', help='file/dir/URL/glob, 0 for webcam')
259+
parser.add_argument('--weights', nargs='+', type=str, default=ROOT / 'yolov5s.pt', help='model path(s)')
260+
parser.add_argument('--source', type=str, default=ROOT / 'data/images', help='file/dir/URL/glob, 0 for webcam')
259261
parser.add_argument('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[640], help='inference size h,w')
260262
parser.add_argument('--conf-thres', type=float, default=0.25, help='confidence threshold')
261263
parser.add_argument('--iou-thres', type=float, default=0.45, help='NMS IoU threshold')
@@ -271,7 +273,7 @@ def parse_opt():
271273
parser.add_argument('--augment', action='store_true', help='augmented inference')
272274
parser.add_argument('--visualize', action='store_true', help='visualize features')
273275
parser.add_argument('--update', action='store_true', help='update all models')
274-
parser.add_argument('--project', default='runs/detect', help='save results to project/name')
276+
parser.add_argument('--project', default=ROOT / 'runs/detect', help='save results to project/name')
275277
parser.add_argument('--name', default='exp', help='save results to project/name')
276278
parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
277279
parser.add_argument('--line-thickness', default=3, type=int, help='bounding box thickness (pixels)')

export.py

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
ROOT = FILE.parents[0] # YOLOv5 root directory
3535
if str(ROOT) not in sys.path:
3636
sys.path.append(str(ROOT)) # add ROOT to PATH
37+
ROOT = ROOT.relative_to(Path.cwd()) # relative
3738

3839
from models.common import Conv
3940
from models.experimental import attempt_load

train.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
ROOT = FILE.parents[0] # YOLOv5 root directory
3131
if str(ROOT) not in sys.path:
3232
sys.path.append(str(ROOT)) # add ROOT to PATH
33+
ROOT = ROOT.relative_to(Path.cwd()) # relative
3334

3435
import val # for end-of-epoch mAP
3536
from models.experimental import attempt_load
@@ -429,10 +430,10 @@ def train(hyp, # path/to/hyp.yaml or hyp dictionary
429430

430431
def parse_opt(known=False):
431432
parser = argparse.ArgumentParser()
432-
parser.add_argument('--weights', type=str, default='yolov5s.pt', help='initial weights path')
433+
parser.add_argument('--weights', type=str, default=ROOT / 'yolov5s.pt', help='initial weights path')
433434
parser.add_argument('--cfg', type=str, default='', help='model.yaml path')
434-
parser.add_argument('--data', type=str, default='data/coco128.yaml', help='dataset.yaml path')
435-
parser.add_argument('--hyp', type=str, default='data/hyps/hyp.scratch.yaml', help='hyperparameters path')
435+
parser.add_argument('--data', type=str, default=ROOT / 'data/coco128.yaml', help='dataset.yaml path')
436+
parser.add_argument('--hyp', type=str, default=ROOT / 'data/hyps/hyp.scratch.yaml', help='hyperparameters path')
436437
parser.add_argument('--epochs', type=int, default=300)
437438
parser.add_argument('--batch-size', type=int, default=16, help='total batch size for all GPUs')
438439
parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=640, help='train, val image size (pixels)')
@@ -451,8 +452,8 @@ def parse_opt(known=False):
451452
parser.add_argument('--adam', action='store_true', help='use torch.optim.Adam() optimizer')
452453
parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')
453454
parser.add_argument('--workers', type=int, default=8, help='maximum number of dataloader workers')
454-
parser.add_argument('--project', default='runs/train', help='save to project/name')
455455
parser.add_argument('--entity', default=None, help='W&B entity')
456+
parser.add_argument('--project', default=ROOT / 'runs/train', help='save to project/name')
456457
parser.add_argument('--name', default='exp', help='save to project/name')
457458
parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
458459
parser.add_argument('--quad', action='store_true', help='quad dataloader')
@@ -486,10 +487,11 @@ def main(opt, callbacks=Callbacks()):
486487
opt.cfg, opt.weights, opt.resume = '', ckpt, True # reinstate
487488
LOGGER.info(f'Resuming training from {ckpt}')
488489
else:
489-
opt.data, opt.cfg, opt.hyp = check_file(opt.data), check_yaml(opt.cfg), check_yaml(opt.hyp) # check YAMLs
490+
opt.data, opt.cfg, opt.hyp, opt.weights, opt.project = \
491+
check_file(opt.data), check_yaml(opt.cfg), check_yaml(opt.hyp), str(opt.weights), str(opt.project) # checks
490492
assert len(opt.cfg) or len(opt.weights), 'either --cfg or --weights must be specified'
491493
if opt.evolve:
492-
opt.project = 'runs/evolve'
494+
opt.project = str(ROOT / 'runs/evolve')
493495
opt.exist_ok, opt.resume = opt.resume, False # pass resume to exist_ok and disable resume
494496
opt.save_dir = str(increment_path(Path(opt.project) / opt.name, exist_ok=opt.exist_ok))
495497

val.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
ROOT = FILE.parents[0] # YOLOv5 root directory
2222
if str(ROOT) not in sys.path:
2323
sys.path.append(str(ROOT)) # add ROOT to PATH
24+
ROOT = ROOT.relative_to(Path.cwd()) # relative
2425

2526
from models.experimental import attempt_load
2627
from utils.datasets import create_dataloader
@@ -95,7 +96,7 @@ def run(data,
9596
save_hybrid=False, # save label+prediction hybrid results to *.txt
9697
save_conf=False, # save confidences in --save-txt labels
9798
save_json=False, # save a COCO-JSON results file
98-
project='runs/val', # save to project/name
99+
project=ROOT / 'runs/val', # save to project/name
99100
name='exp', # save to project/name
100101
exist_ok=False, # existing project/name ok, do not increment
101102
half=True, # use FP16 half-precision inference
@@ -297,8 +298,8 @@ def run(data,
297298

298299
def parse_opt():
299300
parser = argparse.ArgumentParser()
300-
parser.add_argument('--data', type=str, default='data/coco128.yaml', help='dataset.yaml path')
301-
parser.add_argument('--weights', nargs='+', type=str, default='yolov5s.pt', help='model.pt path(s)')
301+
parser.add_argument('--data', type=str, default=ROOT / 'data/coco128.yaml', help='dataset.yaml path')
302+
parser.add_argument('--weights', nargs='+', type=str, default=ROOT / 'yolov5s.pt', help='model.pt path(s)')
302303
parser.add_argument('--batch-size', type=int, default=32, help='batch size')
303304
parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=640, help='inference size (pixels)')
304305
parser.add_argument('--conf-thres', type=float, default=0.001, help='confidence threshold')
@@ -312,14 +313,14 @@ def parse_opt():
312313
parser.add_argument('--save-hybrid', action='store_true', help='save label+prediction hybrid results to *.txt')
313314
parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
314315
parser.add_argument('--save-json', action='store_true', help='save a COCO-JSON results file')
315-
parser.add_argument('--project', default='runs/val', help='save to project/name')
316+
parser.add_argument('--project', default=ROOT / 'runs/val', help='save to project/name')
316317
parser.add_argument('--name', default='exp', help='save to project/name')
317318
parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
318319
parser.add_argument('--half', action='store_true', help='use FP16 half-precision inference')
319320
opt = parser.parse_args()
321+
opt.data = check_yaml(opt.data) # check YAML
320322
opt.save_json |= opt.data.endswith('coco.yaml')
321323
opt.save_txt |= opt.save_hybrid
322-
opt.data = check_yaml(opt.data) # check YAML
323324
print_args(FILE.stem, opt)
324325
return opt
325326

0 commit comments

Comments
 (0)