glenn-jocher commited on
Commit
4e04cb0
1 Parent(s): a820b43

Allow YOLOv5 execution from arbitrary `cwd` (#4954)

Browse files

* Allow YOLOv5 execution from arbitrary `cwd`

* Fix str bugs

Files changed (4) hide show
  1. detect.py +8 -6
  2. export.py +1 -0
  3. train.py +8 -6
  4. val.py +6 -5
detect.py CHANGED
@@ -19,6 +19,7 @@ FILE = Path(__file__).resolve()
19
  ROOT = FILE.parents[0] # YOLOv5 root directory
20
  if str(ROOT) not in sys.path:
21
  sys.path.append(str(ROOT)) # add ROOT to PATH
 
22
 
23
  from models.experimental import attempt_load
24
  from utils.datasets import LoadImages, LoadStreams
@@ -30,8 +31,8 @@ from utils.torch_utils import load_classifier, select_device, time_sync
30
 
31
 
32
  @torch.no_grad()
33
- def run(weights='yolov5s.pt', # model.pt path(s)
34
- source='data/images', # file/dir/URL/glob, 0 for webcam
35
  imgsz=640, # inference size (pixels)
36
  conf_thres=0.25, # confidence threshold
37
  iou_thres=0.45, # NMS IOU threshold
@@ -47,7 +48,7 @@ def run(weights='yolov5s.pt', # model.pt path(s)
47
  augment=False, # augmented inference
48
  visualize=False, # visualize features
49
  update=False, # update all models
50
- project='runs/detect', # save results to project/name
51
  name='exp', # save results to project/name
52
  exist_ok=False, # existing project/name ok, do not increment
53
  line_thickness=3, # bounding box thickness (pixels)
@@ -55,6 +56,7 @@ def run(weights='yolov5s.pt', # model.pt path(s)
55
  hide_conf=False, # hide confidences
56
  half=False, # use FP16 half-precision inference
57
  ):
 
58
  save_img = not nosave and not source.endswith('.txt') # save inference images
59
  webcam = source.isnumeric() or source.endswith('.txt') or source.lower().startswith(
60
  ('rtsp://', 'rtmp://', 'http://', 'https://'))
@@ -254,8 +256,8 @@ def run(weights='yolov5s.pt', # model.pt path(s)
254
 
255
  def parse_opt():
256
  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('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[640], help='inference size h,w')
260
  parser.add_argument('--conf-thres', type=float, default=0.25, help='confidence threshold')
261
  parser.add_argument('--iou-thres', type=float, default=0.45, help='NMS IoU threshold')
@@ -271,7 +273,7 @@ def parse_opt():
271
  parser.add_argument('--augment', action='store_true', help='augmented inference')
272
  parser.add_argument('--visualize', action='store_true', help='visualize features')
273
  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')
275
  parser.add_argument('--name', default='exp', help='save results to project/name')
276
  parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
277
  parser.add_argument('--line-thickness', default=3, type=int, help='bounding box thickness (pixels)')
 
19
  ROOT = FILE.parents[0] # YOLOv5 root directory
20
  if str(ROOT) not in sys.path:
21
  sys.path.append(str(ROOT)) # add ROOT to PATH
22
+ ROOT = ROOT.relative_to(Path.cwd()) # relative
23
 
24
  from models.experimental import attempt_load
25
  from utils.datasets import LoadImages, LoadStreams
 
31
 
32
 
33
  @torch.no_grad()
34
+ def run(weights=ROOT / 'yolov5s.pt', # model.pt path(s)
35
+ source=ROOT / 'data/images', # file/dir/URL/glob, 0 for webcam
36
  imgsz=640, # inference size (pixels)
37
  conf_thres=0.25, # confidence threshold
38
  iou_thres=0.45, # NMS IOU threshold
 
48
  augment=False, # augmented inference
49
  visualize=False, # visualize features
50
  update=False, # update all models
51
+ project=ROOT / 'runs/detect', # save results to project/name
52
  name='exp', # save results to project/name
53
  exist_ok=False, # existing project/name ok, do not increment
54
  line_thickness=3, # bounding box thickness (pixels)
 
56
  hide_conf=False, # hide confidences
57
  half=False, # use FP16 half-precision inference
58
  ):
59
+ source = str(source)
60
  save_img = not nosave and not source.endswith('.txt') # save inference images
61
  webcam = source.isnumeric() or source.endswith('.txt') or source.lower().startswith(
62
  ('rtsp://', 'rtmp://', 'http://', 'https://'))
 
256
 
257
  def parse_opt():
258
  parser = argparse.ArgumentParser()
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')
261
  parser.add_argument('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[640], help='inference size h,w')
262
  parser.add_argument('--conf-thres', type=float, default=0.25, help='confidence threshold')
263
  parser.add_argument('--iou-thres', type=float, default=0.45, help='NMS IoU threshold')
 
273
  parser.add_argument('--augment', action='store_true', help='augmented inference')
274
  parser.add_argument('--visualize', action='store_true', help='visualize features')
275
  parser.add_argument('--update', action='store_true', help='update all models')
276
+ parser.add_argument('--project', default=ROOT / 'runs/detect', help='save results to project/name')
277
  parser.add_argument('--name', default='exp', help='save results to project/name')
278
  parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
279
  parser.add_argument('--line-thickness', default=3, type=int, help='bounding box thickness (pixels)')
export.py CHANGED
@@ -34,6 +34,7 @@ FILE = Path(__file__).resolve()
34
  ROOT = FILE.parents[0] # YOLOv5 root directory
35
  if str(ROOT) not in sys.path:
36
  sys.path.append(str(ROOT)) # add ROOT to PATH
 
37
 
38
  from models.common import Conv
39
  from models.experimental import attempt_load
 
34
  ROOT = FILE.parents[0] # YOLOv5 root directory
35
  if str(ROOT) not in sys.path:
36
  sys.path.append(str(ROOT)) # add ROOT to PATH
37
+ ROOT = ROOT.relative_to(Path.cwd()) # relative
38
 
39
  from models.common import Conv
40
  from models.experimental import attempt_load
train.py CHANGED
@@ -30,6 +30,7 @@ FILE = Path(__file__).resolve()
30
  ROOT = FILE.parents[0] # YOLOv5 root directory
31
  if str(ROOT) not in sys.path:
32
  sys.path.append(str(ROOT)) # add ROOT to PATH
 
33
 
34
  import val # for end-of-epoch mAP
35
  from models.experimental import attempt_load
@@ -429,10 +430,10 @@ def train(hyp, # path/to/hyp.yaml or hyp dictionary
429
 
430
  def parse_opt(known=False):
431
  parser = argparse.ArgumentParser()
432
- parser.add_argument('--weights', type=str, default='yolov5s.pt', help='initial weights path')
433
  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')
436
  parser.add_argument('--epochs', type=int, default=300)
437
  parser.add_argument('--batch-size', type=int, default=16, help='total batch size for all GPUs')
438
  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):
451
  parser.add_argument('--adam', action='store_true', help='use torch.optim.Adam() optimizer')
452
  parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')
453
  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')
455
  parser.add_argument('--entity', default=None, help='W&B entity')
 
456
  parser.add_argument('--name', default='exp', help='save to project/name')
457
  parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
458
  parser.add_argument('--quad', action='store_true', help='quad dataloader')
@@ -486,10 +487,11 @@ def main(opt, callbacks=Callbacks()):
486
  opt.cfg, opt.weights, opt.resume = '', ckpt, True # reinstate
487
  LOGGER.info(f'Resuming training from {ckpt}')
488
  else:
489
- opt.data, opt.cfg, opt.hyp = check_file(opt.data), check_yaml(opt.cfg), check_yaml(opt.hyp) # check YAMLs
 
490
  assert len(opt.cfg) or len(opt.weights), 'either --cfg or --weights must be specified'
491
  if opt.evolve:
492
- opt.project = 'runs/evolve'
493
  opt.exist_ok, opt.resume = opt.resume, False # pass resume to exist_ok and disable resume
494
  opt.save_dir = str(increment_path(Path(opt.project) / opt.name, exist_ok=opt.exist_ok))
495
 
 
30
  ROOT = FILE.parents[0] # YOLOv5 root directory
31
  if str(ROOT) not in sys.path:
32
  sys.path.append(str(ROOT)) # add ROOT to PATH
33
+ ROOT = ROOT.relative_to(Path.cwd()) # relative
34
 
35
  import val # for end-of-epoch mAP
36
  from models.experimental import attempt_load
 
430
 
431
  def parse_opt(known=False):
432
  parser = argparse.ArgumentParser()
433
+ parser.add_argument('--weights', type=str, default=ROOT / 'yolov5s.pt', help='initial weights path')
434
  parser.add_argument('--cfg', type=str, default='', help='model.yaml 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')
437
  parser.add_argument('--epochs', type=int, default=300)
438
  parser.add_argument('--batch-size', type=int, default=16, help='total batch size for all GPUs')
439
  parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=640, help='train, val image size (pixels)')
 
452
  parser.add_argument('--adam', action='store_true', help='use torch.optim.Adam() optimizer')
453
  parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')
454
  parser.add_argument('--workers', type=int, default=8, help='maximum number of dataloader workers')
 
455
  parser.add_argument('--entity', default=None, help='W&B entity')
456
+ parser.add_argument('--project', default=ROOT / 'runs/train', help='save to project/name')
457
  parser.add_argument('--name', default='exp', help='save to project/name')
458
  parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
459
  parser.add_argument('--quad', action='store_true', help='quad dataloader')
 
487
  opt.cfg, opt.weights, opt.resume = '', ckpt, True # reinstate
488
  LOGGER.info(f'Resuming training from {ckpt}')
489
  else:
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
492
  assert len(opt.cfg) or len(opt.weights), 'either --cfg or --weights must be specified'
493
  if opt.evolve:
494
+ opt.project = str(ROOT / 'runs/evolve')
495
  opt.exist_ok, opt.resume = opt.resume, False # pass resume to exist_ok and disable resume
496
  opt.save_dir = str(increment_path(Path(opt.project) / opt.name, exist_ok=opt.exist_ok))
497
 
val.py CHANGED
@@ -21,6 +21,7 @@ FILE = Path(__file__).resolve()
21
  ROOT = FILE.parents[0] # YOLOv5 root directory
22
  if str(ROOT) not in sys.path:
23
  sys.path.append(str(ROOT)) # add ROOT to PATH
 
24
 
25
  from models.experimental import attempt_load
26
  from utils.datasets import create_dataloader
@@ -95,7 +96,7 @@ def run(data,
95
  save_hybrid=False, # save label+prediction hybrid results to *.txt
96
  save_conf=False, # save confidences in --save-txt labels
97
  save_json=False, # save a COCO-JSON results file
98
- project='runs/val', # save to project/name
99
  name='exp', # save to project/name
100
  exist_ok=False, # existing project/name ok, do not increment
101
  half=True, # use FP16 half-precision inference
@@ -297,8 +298,8 @@ def run(data,
297
 
298
  def parse_opt():
299
  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)')
302
  parser.add_argument('--batch-size', type=int, default=32, help='batch size')
303
  parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=640, help='inference size (pixels)')
304
  parser.add_argument('--conf-thres', type=float, default=0.001, help='confidence threshold')
@@ -312,14 +313,14 @@ def parse_opt():
312
  parser.add_argument('--save-hybrid', action='store_true', help='save label+prediction hybrid results to *.txt')
313
  parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
314
  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('--name', default='exp', help='save to project/name')
317
  parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
318
  parser.add_argument('--half', action='store_true', help='use FP16 half-precision inference')
319
  opt = parser.parse_args()
 
320
  opt.save_json |= opt.data.endswith('coco.yaml')
321
  opt.save_txt |= opt.save_hybrid
322
- opt.data = check_yaml(opt.data) # check YAML
323
  print_args(FILE.stem, opt)
324
  return opt
325
 
 
21
  ROOT = FILE.parents[0] # YOLOv5 root directory
22
  if str(ROOT) not in sys.path:
23
  sys.path.append(str(ROOT)) # add ROOT to PATH
24
+ ROOT = ROOT.relative_to(Path.cwd()) # relative
25
 
26
  from models.experimental import attempt_load
27
  from utils.datasets import create_dataloader
 
96
  save_hybrid=False, # save label+prediction hybrid results to *.txt
97
  save_conf=False, # save confidences in --save-txt labels
98
  save_json=False, # save a COCO-JSON results file
99
+ project=ROOT / 'runs/val', # save to project/name
100
  name='exp', # save to project/name
101
  exist_ok=False, # existing project/name ok, do not increment
102
  half=True, # use FP16 half-precision inference
 
298
 
299
  def parse_opt():
300
  parser = argparse.ArgumentParser()
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)')
303
  parser.add_argument('--batch-size', type=int, default=32, help='batch size')
304
  parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=640, help='inference size (pixels)')
305
  parser.add_argument('--conf-thres', type=float, default=0.001, help='confidence threshold')
 
313
  parser.add_argument('--save-hybrid', action='store_true', help='save label+prediction hybrid results to *.txt')
314
  parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
315
  parser.add_argument('--save-json', action='store_true', help='save a COCO-JSON results file')
316
+ parser.add_argument('--project', default=ROOT / 'runs/val', help='save to project/name')
317
  parser.add_argument('--name', default='exp', help='save to project/name')
318
  parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
319
  parser.add_argument('--half', action='store_true', help='use FP16 half-precision inference')
320
  opt = parser.parse_args()
321
+ opt.data = check_yaml(opt.data) # check YAML
322
  opt.save_json |= opt.data.endswith('coco.yaml')
323
  opt.save_txt |= opt.save_hybrid
 
324
  print_args(FILE.stem, opt)
325
  return opt
326