YONG627 commited on
Commit
2dd5705
·
1 Parent(s): f23e79b

Upload 5 files

Browse files
yolov5-code-main/segment/__pycache__/val.cpython-38.pyc ADDED
Binary file (16.3 kB). View file
 
yolov5-code-main/segment/predict.py ADDED
@@ -0,0 +1,284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # YOLOv5 🚀 by Ultralytics, GPL-3.0 license
2
+ """
3
+ Run YOLOv5 segmentation inference on images, videos, directories, streams, etc.
4
+
5
+ Usage - sources:
6
+ $ python segment/predict.py --weights yolov5s-seg.pt --source 0 # webcam
7
+ img.jpg # image
8
+ vid.mp4 # video
9
+ screen # screenshot
10
+ path/ # directory
11
+ list.txt # list of images
12
+ list.streams # list of streams
13
+ 'path/*.jpg' # glob
14
+ 'https://youtu.be/Zgi9g1ksQHc' # YouTube
15
+ 'rtsp://example.com/media.mp4' # RTSP, RTMP, HTTP stream
16
+
17
+ Usage - formats:
18
+ $ python segment/predict.py --weights yolov5s-seg.pt # PyTorch
19
+ yolov5s-seg.torchscript # TorchScript
20
+ yolov5s-seg.onnx # ONNX Runtime or OpenCV DNN with --dnn
21
+ yolov5s-seg_openvino_model # OpenVINO
22
+ yolov5s-seg.engine # TensorRT
23
+ yolov5s-seg.mlmodel # CoreML (macOS-only)
24
+ yolov5s-seg_saved_model # TensorFlow SavedModel
25
+ yolov5s-seg.pb # TensorFlow GraphDef
26
+ yolov5s-seg.tflite # TensorFlow Lite
27
+ yolov5s-seg_edgetpu.tflite # TensorFlow Edge TPU
28
+ yolov5s-seg_paddle_model # PaddlePaddle
29
+ """
30
+
31
+ import argparse
32
+ import os
33
+ import platform
34
+ import sys
35
+ from pathlib import Path
36
+
37
+ import torch
38
+
39
+ FILE = Path(__file__).resolve()
40
+ ROOT = FILE.parents[1] # YOLOv5 root directory
41
+ if str(ROOT) not in sys.path:
42
+ sys.path.append(str(ROOT)) # add ROOT to PATH
43
+ ROOT = Path(os.path.relpath(ROOT, Path.cwd())) # relative
44
+
45
+ from models.common import DetectMultiBackend
46
+ from utils.dataloaders import IMG_FORMATS, VID_FORMATS, LoadImages, LoadScreenshots, LoadStreams
47
+ from utils.general import (LOGGER, Profile, check_file, check_img_size, check_imshow, check_requirements, colorstr, cv2,
48
+ increment_path, non_max_suppression, print_args, scale_boxes, scale_segments,
49
+ strip_optimizer)
50
+ from utils.plots import Annotator, colors, save_one_box
51
+ from utils.segment.general import masks2segments, process_mask, process_mask_native
52
+ from utils.torch_utils import select_device, smart_inference_mode
53
+
54
+
55
+ @smart_inference_mode()
56
+ def run(
57
+ weights=ROOT / 'yolov5s-seg.pt', # model.pt path(s)
58
+ source=ROOT / 'data/images', # file/dir/URL/glob/screen/0(webcam)
59
+ data=ROOT / 'data/coco128.yaml', # dataset.yaml path
60
+ imgsz=(640, 640), # inference size (height, width)
61
+ conf_thres=0.25, # confidence threshold
62
+ iou_thres=0.45, # NMS IOU threshold
63
+ max_det=1000, # maximum detections per image
64
+ device='', # cuda device, i.e. 0 or 0,1,2,3 or cpu
65
+ view_img=False, # show results
66
+ save_txt=False, # save results to *.txt
67
+ save_conf=False, # save confidences in --save-txt labels
68
+ save_crop=False, # save cropped prediction boxes
69
+ nosave=False, # do not save images/videos
70
+ classes=None, # filter by class: --class 0, or --class 0 2 3
71
+ agnostic_nms=False, # class-agnostic NMS
72
+ augment=False, # augmented inference
73
+ visualize=False, # visualize features
74
+ update=False, # update all models
75
+ project=ROOT / 'runs/predict-seg', # save results to project/name
76
+ name='exp', # save results to project/name
77
+ exist_ok=False, # existing project/name ok, do not increment
78
+ line_thickness=3, # bounding box thickness (pixels)
79
+ hide_labels=False, # hide labels
80
+ hide_conf=False, # hide confidences
81
+ half=False, # use FP16 half-precision inference
82
+ dnn=False, # use OpenCV DNN for ONNX inference
83
+ vid_stride=1, # video frame-rate stride
84
+ retina_masks=False,
85
+ ):
86
+ source = str(source)
87
+ save_img = not nosave and not source.endswith('.txt') # save inference images
88
+ is_file = Path(source).suffix[1:] in (IMG_FORMATS + VID_FORMATS)
89
+ is_url = source.lower().startswith(('rtsp://', 'rtmp://', 'http://', 'https://'))
90
+ webcam = source.isnumeric() or source.endswith('.streams') or (is_url and not is_file)
91
+ screenshot = source.lower().startswith('screen')
92
+ if is_url and is_file:
93
+ source = check_file(source) # download
94
+
95
+ # Directories
96
+ save_dir = increment_path(Path(project) / name, exist_ok=exist_ok) # increment run
97
+ (save_dir / 'labels' if save_txt else save_dir).mkdir(parents=True, exist_ok=True) # make dir
98
+
99
+ # Load model
100
+ device = select_device(device)
101
+ model = DetectMultiBackend(weights, device=device, dnn=dnn, data=data, fp16=half)
102
+ stride, names, pt = model.stride, model.names, model.pt
103
+ imgsz = check_img_size(imgsz, s=stride) # check image size
104
+
105
+ # Dataloader
106
+ bs = 1 # batch_size
107
+ if webcam:
108
+ view_img = check_imshow(warn=True)
109
+ dataset = LoadStreams(source, img_size=imgsz, stride=stride, auto=pt, vid_stride=vid_stride)
110
+ bs = len(dataset)
111
+ elif screenshot:
112
+ dataset = LoadScreenshots(source, img_size=imgsz, stride=stride, auto=pt)
113
+ else:
114
+ dataset = LoadImages(source, img_size=imgsz, stride=stride, auto=pt, vid_stride=vid_stride)
115
+ vid_path, vid_writer = [None] * bs, [None] * bs
116
+
117
+ # Run inference
118
+ model.warmup(imgsz=(1 if pt else bs, 3, *imgsz)) # warmup
119
+ seen, windows, dt = 0, [], (Profile(), Profile(), Profile())
120
+ for path, im, im0s, vid_cap, s in dataset:
121
+ with dt[0]:
122
+ im = torch.from_numpy(im).to(model.device)
123
+ im = im.half() if model.fp16 else im.float() # uint8 to fp16/32
124
+ im /= 255 # 0 - 255 to 0.0 - 1.0
125
+ if len(im.shape) == 3:
126
+ im = im[None] # expand for batch dim
127
+
128
+ # Inference
129
+ with dt[1]:
130
+ visualize = increment_path(save_dir / Path(path).stem, mkdir=True) if visualize else False
131
+ pred, proto = model(im, augment=augment, visualize=visualize)[:2]
132
+
133
+ # NMS
134
+ with dt[2]:
135
+ pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det, nm=32)
136
+
137
+ # Second-stage classifier (optional)
138
+ # pred = utils.general.apply_classifier(pred, classifier_model, im, im0s)
139
+
140
+ # Process predictions
141
+ for i, det in enumerate(pred): # per image
142
+ seen += 1
143
+ if webcam: # batch_size >= 1
144
+ p, im0, frame = path[i], im0s[i].copy(), dataset.count
145
+ s += f'{i}: '
146
+ else:
147
+ p, im0, frame = path, im0s.copy(), getattr(dataset, 'frame', 0)
148
+
149
+ p = Path(p) # to Path
150
+ save_path = str(save_dir / p.name) # im.jpg
151
+ txt_path = str(save_dir / 'labels' / p.stem) + ('' if dataset.mode == 'image' else f'_{frame}') # im.txt
152
+ s += '%gx%g ' % im.shape[2:] # print string
153
+ imc = im0.copy() if save_crop else im0 # for save_crop
154
+ annotator = Annotator(im0, line_width=line_thickness, example=str(names))
155
+ if len(det):
156
+ if retina_masks:
157
+ # scale bbox first the crop masks
158
+ det[:, :4] = scale_boxes(im.shape[2:], det[:, :4], im0.shape).round() # rescale boxes to im0 size
159
+ masks = process_mask_native(proto[i], det[:, 6:], det[:, :4], im0.shape[:2]) # HWC
160
+ else:
161
+ masks = process_mask(proto[i], det[:, 6:], det[:, :4], im.shape[2:], upsample=True) # HWC
162
+ det[:, :4] = scale_boxes(im.shape[2:], det[:, :4], im0.shape).round() # rescale boxes to im0 size
163
+
164
+ # Segments
165
+ if save_txt:
166
+ segments = [
167
+ scale_segments(im0.shape if retina_masks else im.shape[2:], x, im0.shape, normalize=True)
168
+ for x in reversed(masks2segments(masks))]
169
+
170
+ # Print results
171
+ for c in det[:, 5].unique():
172
+ n = (det[:, 5] == c).sum() # detections per class
173
+ s += f"{n} {names[int(c)]}{'s' * (n > 1)}, " # add to string
174
+
175
+ # Mask plotting
176
+ annotator.masks(
177
+ masks,
178
+ colors=[colors(x, True) for x in det[:, 5]],
179
+ im_gpu=torch.as_tensor(im0, dtype=torch.float16).to(device).permute(2, 0, 1).flip(0).contiguous() /
180
+ 255 if retina_masks else im[i])
181
+
182
+ # Write results
183
+ for j, (*xyxy, conf, cls) in enumerate(reversed(det[:, :6])):
184
+ if save_txt: # Write to file
185
+ seg = segments[j].reshape(-1) # (n,2) to (n*2)
186
+ line = (cls, *seg, conf) if save_conf else (cls, *seg) # label format
187
+ with open(f'{txt_path}.txt', 'a') as f:
188
+ f.write(('%g ' * len(line)).rstrip() % line + '\n')
189
+
190
+ if save_img or save_crop or view_img: # Add bbox to image
191
+ c = int(cls) # integer class
192
+ label = None if hide_labels else (names[c] if hide_conf else f'{names[c]} {conf:.2f}')
193
+ annotator.box_label(xyxy, label, color=colors(c, True))
194
+ # annotator.draw.polygon(segments[j], outline=colors(c, True), width=3)
195
+ if save_crop:
196
+ save_one_box(xyxy, imc, file=save_dir / 'crops' / names[c] / f'{p.stem}.jpg', BGR=True)
197
+
198
+ # Stream results
199
+ im0 = annotator.result()
200
+ if view_img:
201
+ if platform.system() == 'Linux' and p not in windows:
202
+ windows.append(p)
203
+ cv2.namedWindow(str(p), cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIO) # allow window resize (Linux)
204
+ cv2.resizeWindow(str(p), im0.shape[1], im0.shape[0])
205
+ cv2.imshow(str(p), im0)
206
+ if cv2.waitKey(1) == ord('q'): # 1 millisecond
207
+ exit()
208
+
209
+ # Save results (image with detections)
210
+ if save_img:
211
+ if dataset.mode == 'image':
212
+ cv2.imwrite(save_path, im0)
213
+ else: # 'video' or 'stream'
214
+ if vid_path[i] != save_path: # new video
215
+ vid_path[i] = save_path
216
+ if isinstance(vid_writer[i], cv2.VideoWriter):
217
+ vid_writer[i].release() # release previous video writer
218
+ if vid_cap: # video
219
+ fps = vid_cap.get(cv2.CAP_PROP_FPS)
220
+ w = int(vid_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
221
+ h = int(vid_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
222
+ else: # stream
223
+ fps, w, h = 30, im0.shape[1], im0.shape[0]
224
+ save_path = str(Path(save_path).with_suffix('.mp4')) # force *.mp4 suffix on results videos
225
+ vid_writer[i] = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))
226
+ vid_writer[i].write(im0)
227
+
228
+ # Print time (inference-only)
229
+ LOGGER.info(f"{s}{'' if len(det) else '(no detections), '}{dt[1].dt * 1E3:.1f}ms")
230
+
231
+ # Print results
232
+ t = tuple(x.t / seen * 1E3 for x in dt) # speeds per image
233
+ LOGGER.info(f'Speed: %.1fms pre-process, %.1fms inference, %.1fms NMS per image at shape {(1, 3, *imgsz)}' % t)
234
+ if save_txt or save_img:
235
+ s = f"\n{len(list(save_dir.glob('labels/*.txt')))} labels saved to {save_dir / 'labels'}" if save_txt else ''
236
+ LOGGER.info(f"Results saved to {colorstr('bold', save_dir)}{s}")
237
+ if update:
238
+ strip_optimizer(weights[0]) # update model (to fix SourceChangeWarning)
239
+
240
+
241
+ def parse_opt():
242
+ parser = argparse.ArgumentParser()
243
+ parser.add_argument('--weights', nargs='+', type=str, default=ROOT / 'yolov5s-seg.pt', help='model path(s)')
244
+ parser.add_argument('--source', type=str, default=0, help='file/dir/URL/glob/screen/0(webcam)')
245
+ parser.add_argument('--data', type=str, default=ROOT / 'data/coco128.yaml', help='(optional) dataset.yaml path')
246
+ parser.add_argument('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[640], help='inference size h,w')
247
+ parser.add_argument('--conf-thres', type=float, default=0.25, help='confidence threshold')
248
+ parser.add_argument('--iou-thres', type=float, default=0.45, help='NMS IoU threshold')
249
+ parser.add_argument('--max-det', type=int, default=1000, help='maximum detections per image')
250
+ parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
251
+ parser.add_argument('--view-img', action='store_true', help='show results')
252
+ parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
253
+ parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
254
+ parser.add_argument('--save-crop', action='store_true', help='save cropped prediction boxes')
255
+ parser.add_argument('--nosave', action='store_true', help='do not save images/videos')
256
+ parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --classes 0, or --classes 0 2 3')
257
+ parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
258
+ parser.add_argument('--augment', action='store_true', help='augmented inference')
259
+ parser.add_argument('--visualize', action='store_true', help='visualize features')
260
+ parser.add_argument('--update', action='store_true', help='update all models')
261
+ parser.add_argument('--project', default=ROOT / 'runs/predict-seg', help='save results to project/name')
262
+ parser.add_argument('--name', default='exp', help='save results to project/name')
263
+ parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
264
+ parser.add_argument('--line-thickness', default=3, type=int, help='bounding box thickness (pixels)')
265
+ parser.add_argument('--hide-labels', default=False, action='store_true', help='hide labels')
266
+ parser.add_argument('--hide-conf', default=False, action='store_true', help='hide confidences')
267
+ parser.add_argument('--half', action='store_true', help='use FP16 half-precision inference')
268
+ parser.add_argument('--dnn', action='store_true', help='use OpenCV DNN for ONNX inference')
269
+ parser.add_argument('--vid-stride', type=int, default=1, help='video frame-rate stride')
270
+ parser.add_argument('--retina-masks', action='store_true', help='whether to plot masks in native resolution')
271
+ opt = parser.parse_args()
272
+ opt.imgsz *= 2 if len(opt.imgsz) == 1 else 1 # expand
273
+ print_args(vars(opt))
274
+ return opt
275
+
276
+
277
+ def main(opt):
278
+ check_requirements(exclude=('tensorboard', 'thop'))
279
+ run(**vars(opt))
280
+
281
+
282
+ if __name__ == '__main__':
283
+ opt = parse_opt()
284
+ main(opt)
yolov5-code-main/segment/train.py ADDED
@@ -0,0 +1,665 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # YOLOv5 🚀 by Ultralytics, GPL-3.0 license
2
+ """
3
+ Train a YOLOv5 segment model on a segment dataset
4
+ Models and datasets download automatically from the latest YOLOv5 release.
5
+
6
+ Usage - Single-GPU training:
7
+ $ python segment/train.py --data coco128-seg.yaml --weights yolov5s-seg.pt --img 640 # from pretrained (recommended)
8
+ $ python segment/train.py --data coco128-seg.yaml --weights '' --cfg yolov5s-seg.yaml --img 640 # from scratch
9
+
10
+ Usage - Multi-GPU DDP training:
11
+ $ python -m torch.distributed.run --nproc_per_node 4 --master_port 1 segment/train.py --data coco128-seg.yaml --weights yolov5s-seg.pt --img 640 --device 0,1,2,3
12
+
13
+ Models: https://github.com/ultralytics/yolov5/tree/master/models
14
+ Datasets: https://github.com/ultralytics/yolov5/tree/master/data
15
+ Tutorial: https://github.com/ultralytics/yolov5/wiki/Train-Custom-Data
16
+ """
17
+
18
+ import argparse
19
+ import math
20
+ import os
21
+ os.environ["GIT_PYTHON_REFRESH"] = "quiet"
22
+ import random
23
+ import subprocess
24
+ import sys
25
+ import time
26
+ from copy import deepcopy
27
+ from datetime import datetime
28
+ from pathlib import Path
29
+
30
+ import numpy as np
31
+ import torch
32
+ import torch.distributed as dist
33
+ import torch.nn as nn
34
+ import yaml
35
+ from torch.optim import lr_scheduler
36
+ from tqdm import tqdm
37
+
38
+ FILE = Path(__file__).resolve()
39
+ ROOT = FILE.parents[1] # YOLOv5 root directory
40
+ if str(ROOT) not in sys.path:
41
+ sys.path.append(str(ROOT)) # add ROOT to PATH
42
+ ROOT = Path(os.path.relpath(ROOT, Path.cwd())) # relative
43
+
44
+ import segment.val as validate # for end-of-epoch mAP
45
+ from models.experimental import attempt_load
46
+ from models.yolo import SegmentationModel
47
+ from utils.autoanchor import check_anchors
48
+ from utils.autobatch import check_train_batch_size
49
+ from utils.callbacks import Callbacks
50
+ from utils.downloads import attempt_download, is_url
51
+ from utils.general import (LOGGER, TQDM_BAR_FORMAT, check_amp, check_dataset, check_file, check_git_info,
52
+ check_git_status, check_img_size, check_requirements, check_suffix, check_yaml, colorstr,
53
+ get_latest_run, increment_path, init_seeds, intersect_dicts, labels_to_class_weights,
54
+ labels_to_image_weights, one_cycle, print_args, print_mutation, strip_optimizer, yaml_save)
55
+ from utils.loggers import GenericLogger
56
+ from utils.plots import plot_evolve, plot_labels
57
+ from utils.segment.dataloaders import create_dataloader
58
+ from utils.segment.loss import ComputeLoss
59
+ from utils.segment.metrics import KEYS, fitness
60
+ from utils.segment.plots import plot_images_and_masks, plot_results_with_masks
61
+ from utils.torch_utils import (EarlyStopping, ModelEMA, de_parallel, select_device, smart_DDP, smart_optimizer,
62
+ smart_resume, torch_distributed_zero_first)
63
+
64
+ LOCAL_RANK = int(os.getenv('LOCAL_RANK', -1)) # https://pytorch.org/docs/stable/elastic/run.html
65
+ RANK = int(os.getenv('RANK', -1))
66
+ WORLD_SIZE = int(os.getenv('WORLD_SIZE', 1))
67
+ GIT_INFO = check_git_info()
68
+
69
+
70
+ def train(hyp, opt, device, callbacks): # hyp is path/to/hyp.yaml or hyp dictionary
71
+ save_dir, epochs, batch_size, weights, single_cls, evolve, data, cfg, resume, noval, nosave, workers, freeze, mask_ratio = \
72
+ Path(opt.save_dir), opt.epochs, opt.batch_size, opt.weights, opt.single_cls, opt.evolve, opt.data, opt.cfg, \
73
+ opt.resume, opt.noval, opt.nosave, opt.workers, opt.freeze, opt.mask_ratio
74
+ # callbacks.run('on_pretrain_routine_start')
75
+
76
+ # Directories
77
+ w = save_dir / 'weights' # weights dir
78
+ (w.parent if evolve else w).mkdir(parents=True, exist_ok=True) # make dir
79
+ last, best = w / 'last.pt', w / 'best.pt'
80
+
81
+ # Hyperparameters
82
+ if isinstance(hyp, str):
83
+ with open(hyp, errors='ignore') as f:
84
+ hyp = yaml.safe_load(f) # load hyps dict
85
+ LOGGER.info(colorstr('hyperparameters: ') + ', '.join(f'{k}={v}' for k, v in hyp.items()))
86
+ opt.hyp = hyp.copy() # for saving hyps to checkpoints
87
+
88
+ # Save run settings
89
+ if not evolve:
90
+ yaml_save(save_dir / 'hyp.yaml', hyp)
91
+ yaml_save(save_dir / 'opt.yaml', vars(opt))
92
+
93
+ # Loggers
94
+ data_dict = None
95
+ if RANK in {-1, 0}:
96
+ logger = GenericLogger(opt=opt, console_logger=LOGGER)
97
+
98
+ # Config
99
+ plots = not evolve and not opt.noplots # create plots
100
+ overlap = not opt.no_overlap
101
+ cuda = device.type != 'cpu'
102
+ init_seeds(opt.seed + 1 + RANK, deterministic=True)
103
+ with torch_distributed_zero_first(LOCAL_RANK):
104
+ data_dict = data_dict or check_dataset(data) # check if None
105
+ train_path, val_path = data_dict['train'], data_dict['val']
106
+ nc = 1 if single_cls else int(data_dict['nc']) # number of classes
107
+ names = {0: 'item'} if single_cls and len(data_dict['names']) != 1 else data_dict['names'] # class names
108
+ is_coco = isinstance(val_path, str) and val_path.endswith('coco/val2017.txt') # COCO dataset
109
+
110
+ # Model
111
+ check_suffix(weights, '.pt') # check weights
112
+ pretrained = weights.endswith('.pt')
113
+ if pretrained:
114
+ with torch_distributed_zero_first(LOCAL_RANK):
115
+ weights = attempt_download(weights) # download if not found locally
116
+ ckpt = torch.load(weights, map_location='cpu') # load checkpoint to CPU to avoid CUDA memory leak
117
+ model = SegmentationModel(cfg or ckpt['model'].yaml, ch=3, nc=nc, anchors=hyp.get('anchors')).to(device)
118
+ exclude = ['anchor'] if (cfg or hyp.get('anchors')) and not resume else [] # exclude keys
119
+ csd = ckpt['model'].float().state_dict() # checkpoint state_dict as FP32
120
+ csd = intersect_dicts(csd, model.state_dict(), exclude=exclude) # intersect
121
+ model.load_state_dict(csd, strict=False) # load
122
+ LOGGER.info(f'Transferred {len(csd)}/{len(model.state_dict())} items from {weights}') # report
123
+ else:
124
+ model = SegmentationModel(cfg, ch=3, nc=nc, anchors=hyp.get('anchors')).to(device) # create
125
+ amp = check_amp(model) # check AMP
126
+
127
+ # Freeze
128
+ freeze = [f'model.{x}.' for x in (freeze if len(freeze) > 1 else range(freeze[0]))] # layers to freeze
129
+ for k, v in model.named_parameters():
130
+ v.requires_grad = True # train all layers
131
+ # v.register_hook(lambda x: torch.nan_to_num(x)) # NaN to 0 (commented for erratic training results)
132
+ if any(x in k for x in freeze):
133
+ LOGGER.info(f'freezing {k}')
134
+ v.requires_grad = False
135
+
136
+ # Image size
137
+ gs = max(int(model.stride.max()), 32) # grid size (max stride)
138
+ imgsz = check_img_size(opt.imgsz, gs, floor=gs * 2) # verify imgsz is gs-multiple
139
+
140
+ # Batch size
141
+ if RANK == -1 and batch_size == -1: # single-GPU only, estimate best batch size
142
+ batch_size = check_train_batch_size(model, imgsz, amp)
143
+ logger.update_params({'batch_size': batch_size})
144
+ # loggers.on_params_update({"batch_size": batch_size})
145
+
146
+ # Optimizer
147
+ nbs = 64 # nominal batch size
148
+ accumulate = max(round(nbs / batch_size), 1) # accumulate loss before optimizing
149
+ hyp['weight_decay'] *= batch_size * accumulate / nbs # scale weight_decay
150
+ optimizer = smart_optimizer(model, opt.optimizer, hyp['lr0'], hyp['momentum'], hyp['weight_decay'])
151
+
152
+ # Scheduler
153
+ if opt.cos_lr:
154
+ lf = one_cycle(1, hyp['lrf'], epochs) # cosine 1->hyp['lrf']
155
+ else:
156
+ lf = lambda x: (1 - x / epochs) * (1.0 - hyp['lrf']) + hyp['lrf'] # linear
157
+ scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lf) # plot_lr_scheduler(optimizer, scheduler, epochs)
158
+
159
+ # EMA
160
+ ema = ModelEMA(model) if RANK in {-1, 0} else None
161
+
162
+ # Resume
163
+ best_fitness, start_epoch = 0.0, 0
164
+ if pretrained:
165
+ if resume:
166
+ best_fitness, start_epoch, epochs = smart_resume(ckpt, optimizer, ema, weights, epochs, resume)
167
+ del ckpt, csd
168
+
169
+ # DP mode
170
+ if cuda and RANK == -1 and torch.cuda.device_count() > 1:
171
+ LOGGER.warning('WARNING ⚠️ DP not recommended, use torch.distributed.run for best DDP Multi-GPU results.\n'
172
+ 'See Multi-GPU Tutorial at https://github.com/ultralytics/yolov5/issues/475 to get started.')
173
+ model = torch.nn.DataParallel(model)
174
+
175
+ # SyncBatchNorm
176
+ if opt.sync_bn and cuda and RANK != -1:
177
+ model = torch.nn.SyncBatchNorm.convert_sync_batchnorm(model).to(device)
178
+ LOGGER.info('Using SyncBatchNorm()')
179
+
180
+ # Trainloader
181
+ train_loader, dataset = create_dataloader(
182
+ train_path,
183
+ imgsz,
184
+ batch_size // WORLD_SIZE,
185
+ gs,
186
+ single_cls,
187
+ hyp=hyp,
188
+ augment=True,
189
+ cache=None if opt.cache == 'val' else opt.cache,
190
+ rect=opt.rect,
191
+ rank=LOCAL_RANK,
192
+ workers=workers,
193
+ image_weights=opt.image_weights,
194
+ quad=opt.quad,
195
+ prefix=colorstr('train: '),
196
+ shuffle=True,
197
+ mask_downsample_ratio=mask_ratio,
198
+ overlap_mask=overlap,
199
+ )
200
+ labels = np.concatenate(dataset.labels, 0)
201
+ mlc = int(labels[:, 0].max()) # max label class
202
+ assert mlc < nc, f'Label class {mlc} exceeds nc={nc} in {data}. Possible class labels are 0-{nc - 1}'
203
+
204
+ # Process 0
205
+ if RANK in {-1, 0}:
206
+ val_loader = create_dataloader(val_path,
207
+ imgsz,
208
+ batch_size // WORLD_SIZE * 2,
209
+ gs,
210
+ single_cls,
211
+ hyp=hyp,
212
+ cache=None if noval else opt.cache,
213
+ rect=True,
214
+ rank=-1,
215
+ workers=workers * 2,
216
+ pad=0.5,
217
+ mask_downsample_ratio=mask_ratio,
218
+ overlap_mask=overlap,
219
+ prefix=colorstr('val: '))[0]
220
+
221
+ if not resume:
222
+ if not opt.noautoanchor:
223
+ check_anchors(dataset, model=model, thr=hyp['anchor_t'], imgsz=imgsz) # run AutoAnchor
224
+ model.half().float() # pre-reduce anchor precision
225
+
226
+ if plots:
227
+ plot_labels(labels, names, save_dir)
228
+ # callbacks.run('on_pretrain_routine_end', labels, names)
229
+
230
+ # DDP mode
231
+ if cuda and RANK != -1:
232
+ model = smart_DDP(model)
233
+
234
+ # Model attributes
235
+ nl = de_parallel(model).model[-1].nl # number of detection layers (to scale hyps)
236
+ hyp['box'] *= 3 / nl # scale to layers
237
+ hyp['cls'] *= nc / 80 * 3 / nl # scale to classes and layers
238
+ hyp['obj'] *= (imgsz / 640) ** 2 * 3 / nl # scale to image size and layers
239
+ hyp['label_smoothing'] = opt.label_smoothing
240
+ model.nc = nc # attach number of classes to model
241
+ model.hyp = hyp # attach hyperparameters to model
242
+ model.class_weights = labels_to_class_weights(dataset.labels, nc).to(device) * nc # attach class weights
243
+ model.names = names
244
+
245
+ # Start training
246
+ t0 = time.time()
247
+ nb = len(train_loader) # number of batches
248
+ nw = max(round(hyp['warmup_epochs'] * nb), 100) # number of warmup iterations, max(3 epochs, 100 iterations)
249
+ # nw = min(nw, (epochs - start_epoch) / 2 * nb) # limit warmup to < 1/2 of training
250
+ last_opt_step = -1
251
+ maps = np.zeros(nc) # mAP per class
252
+ results = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) # P, R, mAP@.5, mAP@.5-.95, val_loss(box, obj, cls)
253
+ scheduler.last_epoch = start_epoch - 1 # do not move
254
+ scaler = torch.cuda.amp.GradScaler(enabled=amp)
255
+ stopper, stop = EarlyStopping(patience=opt.patience), False
256
+ compute_loss = ComputeLoss(model, overlap=overlap) # init loss class
257
+ # callbacks.run('on_train_start')
258
+ LOGGER.info(f'Image sizes {imgsz} train, {imgsz} val\n'
259
+ f'Using {train_loader.num_workers * WORLD_SIZE} dataloader workers\n'
260
+ f"Logging results to {colorstr('bold', save_dir)}\n"
261
+ f'Starting training for {epochs} epochs...')
262
+ for epoch in range(start_epoch, epochs): # epoch ------------------------------------------------------------------
263
+ # callbacks.run('on_train_epoch_start')
264
+ model.train()
265
+
266
+ # Update image weights (optional, single-GPU only)
267
+ if opt.image_weights:
268
+ cw = model.class_weights.cpu().numpy() * (1 - maps) ** 2 / nc # class weights
269
+ iw = labels_to_image_weights(dataset.labels, nc=nc, class_weights=cw) # image weights
270
+ dataset.indices = random.choices(range(dataset.n), weights=iw, k=dataset.n) # rand weighted idx
271
+
272
+ # Update mosaic border (optional)
273
+ # b = int(random.uniform(0.25 * imgsz, 0.75 * imgsz + gs) // gs * gs)
274
+ # dataset.mosaic_border = [b - imgsz, -b] # height, width borders
275
+
276
+ mloss = torch.zeros(4, device=device) # mean losses
277
+ if RANK != -1:
278
+ train_loader.sampler.set_epoch(epoch)
279
+ pbar = enumerate(train_loader)
280
+ LOGGER.info(('\n' + '%11s' * 8) %
281
+ ('Epoch', 'GPU_mem', 'box_loss', 'seg_loss', 'obj_loss', 'cls_loss', 'Instances', 'Size'))
282
+ if RANK in {-1, 0}:
283
+ pbar = tqdm(pbar, total=nb, bar_format=TQDM_BAR_FORMAT) # progress bar
284
+ optimizer.zero_grad()
285
+ for i, (imgs, targets, paths, _, masks) in pbar: # batch ------------------------------------------------------
286
+ # callbacks.run('on_train_batch_start')
287
+ ni = i + nb * epoch # number integrated batches (since train start)
288
+ imgs = imgs.to(device, non_blocking=True).float() / 255 # uint8 to float32, 0-255 to 0.0-1.0
289
+
290
+ # Warmup
291
+ if ni <= nw:
292
+ xi = [0, nw] # x interp
293
+ # compute_loss.gr = np.interp(ni, xi, [0.0, 1.0]) # iou loss ratio (obj_loss = 1.0 or iou)
294
+ accumulate = max(1, np.interp(ni, xi, [1, nbs / batch_size]).round())
295
+ for j, x in enumerate(optimizer.param_groups):
296
+ # bias lr falls from 0.1 to lr0, all other lrs rise from 0.0 to lr0
297
+ x['lr'] = np.interp(ni, xi, [hyp['warmup_bias_lr'] if j == 0 else 0.0, x['initial_lr'] * lf(epoch)])
298
+ if 'momentum' in x:
299
+ x['momentum'] = np.interp(ni, xi, [hyp['warmup_momentum'], hyp['momentum']])
300
+
301
+ # Multi-scale
302
+ if opt.multi_scale:
303
+ sz = random.randrange(imgsz * 0.5, imgsz * 1.5 + gs) // gs * gs # size
304
+ sf = sz / max(imgs.shape[2:]) # scale factor
305
+ if sf != 1:
306
+ ns = [math.ceil(x * sf / gs) * gs for x in imgs.shape[2:]] # new shape (stretched to gs-multiple)
307
+ imgs = nn.functional.interpolate(imgs, size=ns, mode='bilinear', align_corners=False)
308
+
309
+ # Forward
310
+ with torch.cuda.amp.autocast(amp):
311
+ pred = model(imgs) # forward
312
+ loss, loss_items = compute_loss(pred, targets.to(device), masks=masks.to(device).float())
313
+ if RANK != -1:
314
+ loss *= WORLD_SIZE # gradient averaged between devices in DDP mode
315
+ if opt.quad:
316
+ loss *= 4.
317
+
318
+ # Backward
319
+ scaler.scale(loss).backward()
320
+
321
+ # Optimize - https://pytorch.org/docs/master/notes/amp_examples.html
322
+ if ni - last_opt_step >= accumulate:
323
+ scaler.unscale_(optimizer) # unscale gradients
324
+ torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=10.0) # clip gradients
325
+ scaler.step(optimizer) # optimizer.step
326
+ scaler.update()
327
+ optimizer.zero_grad()
328
+ if ema:
329
+ ema.update(model)
330
+ last_opt_step = ni
331
+
332
+ # Log
333
+ if RANK in {-1, 0}:
334
+ mloss = (mloss * i + loss_items) / (i + 1) # update mean losses
335
+ mem = f'{torch.cuda.memory_reserved() / 1E9 if torch.cuda.is_available() else 0:.3g}G' # (GB)
336
+ pbar.set_description(('%11s' * 2 + '%11.4g' * 6) %
337
+ (f'{epoch}/{epochs - 1}', mem, *mloss, targets.shape[0], imgs.shape[-1]))
338
+ # callbacks.run('on_train_batch_end', model, ni, imgs, targets, paths)
339
+ # if callbacks.stop_training:
340
+ # return
341
+
342
+ # Mosaic plots
343
+ if plots:
344
+ if ni < 3:
345
+ plot_images_and_masks(imgs, targets, masks, paths, save_dir / f'train_batch{ni}.jpg')
346
+ if ni == 10:
347
+ files = sorted(save_dir.glob('train*.jpg'))
348
+ logger.log_images(files, 'Mosaics', epoch)
349
+ # end batch ------------------------------------------------------------------------------------------------
350
+
351
+ # Scheduler
352
+ lr = [x['lr'] for x in optimizer.param_groups] # for loggers
353
+ scheduler.step()
354
+
355
+ if RANK in {-1, 0}:
356
+ # mAP
357
+ # callbacks.run('on_train_epoch_end', epoch=epoch)
358
+ ema.update_attr(model, include=['yaml', 'nc', 'hyp', 'names', 'stride', 'class_weights'])
359
+ final_epoch = (epoch + 1 == epochs) or stopper.possible_stop
360
+ if not noval or final_epoch: # Calculate mAP
361
+ results, maps, _ = validate.run(data_dict,
362
+ batch_size=batch_size // WORLD_SIZE * 2,
363
+ imgsz=imgsz,
364
+ half=amp,
365
+ model=ema.ema,
366
+ single_cls=single_cls,
367
+ dataloader=val_loader,
368
+ save_dir=save_dir,
369
+ plots=False,
370
+ callbacks=callbacks,
371
+ compute_loss=compute_loss,
372
+ mask_downsample_ratio=mask_ratio,
373
+ overlap=overlap)
374
+
375
+ # Update best mAP
376
+ fi = fitness(np.array(results).reshape(1, -1)) # weighted combination of [P, R, mAP@.5, mAP@.5-.95]
377
+ stop = stopper(epoch=epoch, fitness=fi) # early stop check
378
+ if fi > best_fitness:
379
+ best_fitness = fi
380
+ log_vals = list(mloss) + list(results) + lr
381
+ # callbacks.run('on_fit_epoch_end', log_vals, epoch, best_fitness, fi)
382
+ # Log val metrics and media
383
+ metrics_dict = dict(zip(KEYS, log_vals))
384
+ logger.log_metrics(metrics_dict, epoch)
385
+
386
+ # Save model
387
+ if (not nosave) or (final_epoch and not evolve): # if save
388
+ ckpt = {
389
+ 'epoch': epoch,
390
+ 'best_fitness': best_fitness,
391
+ 'model': deepcopy(de_parallel(model)).half(),
392
+ 'ema': deepcopy(ema.ema).half(),
393
+ 'updates': ema.updates,
394
+ 'optimizer': optimizer.state_dict(),
395
+ 'opt': vars(opt),
396
+ 'git': GIT_INFO, # {remote, branch, commit} if a git repo
397
+ 'date': datetime.now().isoformat()}
398
+
399
+ # Save last, best and delete
400
+ torch.save(ckpt, last)
401
+ if best_fitness == fi:
402
+ torch.save(ckpt, best)
403
+ if opt.save_period > 0 and epoch % opt.save_period == 0:
404
+ torch.save(ckpt, w / f'epoch{epoch}.pt')
405
+ logger.log_model(w / f'epoch{epoch}.pt')
406
+ del ckpt
407
+ # callbacks.run('on_model_save', last, epoch, final_epoch, best_fitness, fi)
408
+
409
+ # EarlyStopping
410
+ if RANK != -1: # if DDP training
411
+ broadcast_list = [stop if RANK == 0 else None]
412
+ dist.broadcast_object_list(broadcast_list, 0) # broadcast 'stop' to all ranks
413
+ if RANK != 0:
414
+ stop = broadcast_list[0]
415
+ if stop:
416
+ break # must break all DDP ranks
417
+
418
+ # end epoch ----------------------------------------------------------------------------------------------------
419
+ # end training -----------------------------------------------------------------------------------------------------
420
+ if RANK in {-1, 0}:
421
+ LOGGER.info(f'\n{epoch - start_epoch + 1} epochs completed in {(time.time() - t0) / 3600:.3f} hours.')
422
+ for f in last, best:
423
+ if f.exists():
424
+ strip_optimizer(f) # strip optimizers
425
+ if f is best:
426
+ LOGGER.info(f'\nValidating {f}...')
427
+ results, _, _ = validate.run(
428
+ data_dict,
429
+ batch_size=batch_size // WORLD_SIZE * 2,
430
+ imgsz=imgsz,
431
+ model=attempt_load(f, device).half(),
432
+ iou_thres=0.65 if is_coco else 0.60, # best pycocotools at iou 0.65
433
+ single_cls=single_cls,
434
+ dataloader=val_loader,
435
+ save_dir=save_dir,
436
+ save_json=is_coco,
437
+ verbose=True,
438
+ plots=plots,
439
+ callbacks=callbacks,
440
+ compute_loss=compute_loss,
441
+ mask_downsample_ratio=mask_ratio,
442
+ overlap=overlap) # val best model with plots
443
+ if is_coco:
444
+ # callbacks.run('on_fit_epoch_end', list(mloss) + list(results) + lr, epoch, best_fitness, fi)
445
+ metrics_dict = dict(zip(KEYS, list(mloss) + list(results) + lr))
446
+ logger.log_metrics(metrics_dict, epoch)
447
+
448
+ # callbacks.run('on_train_end', last, best, epoch, results)
449
+ # on train end callback using genericLogger
450
+ logger.log_metrics(dict(zip(KEYS[4:16], results)), epochs)
451
+ if not opt.evolve:
452
+ logger.log_model(best, epoch)
453
+ if plots:
454
+ plot_results_with_masks(file=save_dir / 'results.csv') # save results.png
455
+ files = ['results.png', 'confusion_matrix.png', *(f'{x}_curve.png' for x in ('F1', 'PR', 'P', 'R'))]
456
+ files = [(save_dir / f) for f in files if (save_dir / f).exists()] # filter
457
+ LOGGER.info(f"Results saved to {colorstr('bold', save_dir)}")
458
+ logger.log_images(files, 'Results', epoch + 1)
459
+ logger.log_images(sorted(save_dir.glob('val*.jpg')), 'Validation', epoch + 1)
460
+ torch.cuda.empty_cache()
461
+ return results
462
+
463
+
464
+ def parse_opt(known=False):
465
+ parser = argparse.ArgumentParser()
466
+ parser.add_argument('--weights', type=str, default=ROOT / 'yolov5s-seg.pt', help='initial weights path')
467
+ parser.add_argument('--cfg', type=str, default='', help='model.yaml path')
468
+ parser.add_argument('--data', type=str, default="C:/Users/yong/Desktop/yolov5-code-main/data/coco128-seg.yaml", help='dataset.yaml path')
469
+ parser.add_argument('--hyp', type=str, default=ROOT / 'data/hyps/hyp.scratch-low.yaml', help='hyperparameters path')
470
+ parser.add_argument('--epochs', type=int, default=25, help='total training epochs')
471
+ parser.add_argument('--batch-size', type=int, default=1, help='total batch size for all GPUs, -1 for autobatch')
472
+ parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=640, help='train, val image size (pixels)')
473
+ parser.add_argument('--rect', action='store_true', help='rectangular training')
474
+ parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')
475
+ parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')
476
+ parser.add_argument('--noval', action='store_true', help='only validate final epoch')
477
+ parser.add_argument('--noautoanchor', action='store_true', help='disable AutoAnchor')
478
+ parser.add_argument('--noplots', action='store_true', help='save no plot files')
479
+ parser.add_argument('--evolve', type=int, nargs='?', const=300, help='evolve hyperparameters for x generations')
480
+ parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')
481
+ parser.add_argument('--cache', type=str, nargs='?', const='ram', help='image --cache ram/disk')
482
+ parser.add_argument('--image-weights', action='store_true', help='use weighted image selection for training')
483
+ parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
484
+ parser.add_argument('--multi-scale', action='store_true', help='vary img-size +/- 50%%')
485
+ parser.add_argument('--single-cls', action='store_true', help='train multi-class data as single-class')
486
+ parser.add_argument('--optimizer', type=str, choices=['SGD', 'Adam', 'AdamW'], default='SGD', help='optimizer')
487
+ parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')
488
+ parser.add_argument('--workers', type=int, default=8, help='max dataloader workers (per RANK in DDP mode)')
489
+ parser.add_argument('--project', default=ROOT / 'runs/train-seg', help='save to project/name')
490
+ parser.add_argument('--name', default='exp', help='save to project/name')
491
+ parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
492
+ parser.add_argument('--quad', action='store_true', help='quad dataloader')
493
+ parser.add_argument('--cos-lr', action='store_true', help='cosine LR scheduler')
494
+ parser.add_argument('--label-smoothing', type=float, default=0.0, help='Label smoothing epsilon')
495
+ parser.add_argument('--patience', type=int, default=100, help='EarlyStopping patience (epochs without improvement)')
496
+ parser.add_argument('--freeze', nargs='+', type=int, default=[0], help='Freeze layers: backbone=10, first3=0 1 2')
497
+ parser.add_argument('--save-period', type=int, default=-1, help='Save checkpoint every x epochs (disabled if < 1)')
498
+ parser.add_argument('--seed', type=int, default=0, help='Global training seed')
499
+ parser.add_argument('--local_rank', type=int, default=-1, help='Automatic DDP Multi-GPU argument, do not modify')
500
+
501
+ # Instance Segmentation Args
502
+ parser.add_argument('--mask-ratio', type=int, default=4, help='Downsample the truth masks to saving memory')
503
+ parser.add_argument('--no-overlap', action='store_true', help='Overlap masks train faster at slightly less mAP')
504
+
505
+ return parser.parse_known_args()[0] if known else parser.parse_args()
506
+
507
+
508
+ def main(opt, callbacks=Callbacks()):
509
+ # Checks
510
+ if RANK in {-1, 0}:
511
+ print_args(vars(opt))
512
+ check_git_status()
513
+ check_requirements()
514
+
515
+ # Resume
516
+ if opt.resume and not opt.evolve: # resume from specified or most recent last.pt
517
+ last = Path(check_file(opt.resume) if isinstance(opt.resume, str) else get_latest_run())
518
+ opt_yaml = last.parent.parent / 'opt.yaml' # train options yaml
519
+ opt_data = opt.data # original dataset
520
+ if opt_yaml.is_file():
521
+ with open(opt_yaml, errors='ignore') as f:
522
+ d = yaml.safe_load(f)
523
+ else:
524
+ d = torch.load(last, map_location='cpu')['opt']
525
+ opt = argparse.Namespace(**d) # replace
526
+ opt.cfg, opt.weights, opt.resume = '', str(last), True # reinstate
527
+ if is_url(opt_data):
528
+ opt.data = check_file(opt_data) # avoid HUB resume auth timeout
529
+ else:
530
+ opt.data, opt.cfg, opt.hyp, opt.weights, opt.project = \
531
+ check_file(opt.data), check_yaml(opt.cfg), check_yaml(opt.hyp), str(opt.weights), str(opt.project) # checks
532
+ assert len(opt.cfg) or len(opt.weights), 'either --cfg or --weights must be specified'
533
+ if opt.evolve:
534
+ if opt.project == str(ROOT / 'runs/train'): # if default project name, rename to runs/evolve
535
+ opt.project = str(ROOT / 'runs/evolve')
536
+ opt.exist_ok, opt.resume = opt.resume, False # pass resume to exist_ok and disable resume
537
+ if opt.name == 'cfg':
538
+ opt.name = Path(opt.cfg).stem # use model.yaml as name
539
+ opt.save_dir = str(increment_path(Path(opt.project) / opt.name, exist_ok=opt.exist_ok))
540
+
541
+ # DDP mode
542
+ device = select_device(opt.device, batch_size=opt.batch_size)
543
+ if LOCAL_RANK != -1:
544
+ msg = 'is not compatible with YOLOv5 Multi-GPU DDP training'
545
+ assert not opt.image_weights, f'--image-weights {msg}'
546
+ assert not opt.evolve, f'--evolve {msg}'
547
+ assert opt.batch_size != -1, f'AutoBatch with --batch-size -1 {msg}, please pass a valid --batch-size'
548
+ assert opt.batch_size % WORLD_SIZE == 0, f'--batch-size {opt.batch_size} must be multiple of WORLD_SIZE'
549
+ assert torch.cuda.device_count() > LOCAL_RANK, 'insufficient CUDA devices for DDP command'
550
+ torch.cuda.set_device(LOCAL_RANK)
551
+ device = torch.device('cuda', LOCAL_RANK)
552
+ dist.init_process_group(backend='nccl' if dist.is_nccl_available() else 'gloo')
553
+
554
+ # Train
555
+ if not opt.evolve:
556
+ train(opt.hyp, opt, device, callbacks)
557
+
558
+ # Evolve hyperparameters (optional)
559
+ else:
560
+ # Hyperparameter evolution metadata (mutation scale 0-1, lower_limit, upper_limit)
561
+ meta = {
562
+ 'lr0': (1, 1e-5, 1e-1), # initial learning rate (SGD=1E-2, Adam=1E-3)
563
+ 'lrf': (1, 0.01, 1.0), # final OneCycleLR learning rate (lr0 * lrf)
564
+ 'momentum': (0.3, 0.6, 0.98), # SGD momentum/Adam beta1
565
+ 'weight_decay': (1, 0.0, 0.001), # optimizer weight decay
566
+ 'warmup_epochs': (1, 0.0, 5.0), # warmup epochs (fractions ok)
567
+ 'warmup_momentum': (1, 0.0, 0.95), # warmup initial momentum
568
+ 'warmup_bias_lr': (1, 0.0, 0.2), # warmup initial bias lr
569
+ 'box': (1, 0.02, 0.2), # box loss gain
570
+ 'cls': (1, 0.2, 4.0), # cls loss gain
571
+ 'cls_pw': (1, 0.5, 2.0), # cls BCELoss positive_weight
572
+ 'obj': (1, 0.2, 4.0), # obj loss gain (scale with pixels)
573
+ 'obj_pw': (1, 0.5, 2.0), # obj BCELoss positive_weight
574
+ 'iou_t': (0, 0.1, 0.7), # IoU training threshold
575
+ 'anchor_t': (1, 2.0, 8.0), # anchor-multiple threshold
576
+ 'anchors': (2, 2.0, 10.0), # anchors per output grid (0 to ignore)
577
+ 'fl_gamma': (0, 0.0, 2.0), # focal loss gamma (efficientDet default gamma=1.5)
578
+ 'hsv_h': (1, 0.0, 0.1), # image HSV-Hue augmentation (fraction)
579
+ 'hsv_s': (1, 0.0, 0.9), # image HSV-Saturation augmentation (fraction)
580
+ 'hsv_v': (1, 0.0, 0.9), # image HSV-Value augmentation (fraction)
581
+ 'degrees': (1, 0.0, 45.0), # image rotation (+/- deg)
582
+ 'translate': (1, 0.0, 0.9), # image translation (+/- fraction)
583
+ 'scale': (1, 0.0, 0.9), # image scale (+/- gain)
584
+ 'shear': (1, 0.0, 10.0), # image shear (+/- deg)
585
+ 'perspective': (0, 0.0, 0.001), # image perspective (+/- fraction), range 0-0.001
586
+ 'flipud': (1, 0.0, 1.0), # image flip up-down (probability)
587
+ 'fliplr': (0, 0.0, 1.0), # image flip left-right (probability)
588
+ 'mosaic': (1, 0.0, 1.0), # image mixup (probability)
589
+ 'mixup': (1, 0.0, 1.0), # image mixup (probability)
590
+ 'copy_paste': (1, 0.0, 1.0)} # segment copy-paste (probability)
591
+
592
+ with open(opt.hyp, errors='ignore') as f:
593
+ hyp = yaml.safe_load(f) # load hyps dict
594
+ if 'anchors' not in hyp: # anchors commented in hyp.yaml
595
+ hyp['anchors'] = 3
596
+ if opt.noautoanchor:
597
+ del hyp['anchors'], meta['anchors']
598
+ opt.noval, opt.nosave, save_dir = True, True, Path(opt.save_dir) # only val/save final epoch
599
+ # ei = [isinstance(x, (int, float)) for x in hyp.values()] # evolvable indices
600
+ evolve_yaml, evolve_csv = save_dir / 'hyp_evolve.yaml', save_dir / 'evolve.csv'
601
+ if opt.bucket:
602
+ # download evolve.csv if exists
603
+ subprocess.run([
604
+ 'gsutil',
605
+ 'cp',
606
+ f'gs://{opt.bucket}/evolve.csv',
607
+ str(evolve_csv),])
608
+
609
+ for _ in range(opt.evolve): # generations to evolve
610
+ if evolve_csv.exists(): # if evolve.csv exists: select best hyps and mutate
611
+ # Select parent(s)
612
+ parent = 'single' # parent selection method: 'single' or 'weighted'
613
+ x = np.loadtxt(evolve_csv, ndmin=2, delimiter=',', skiprows=1)
614
+ n = min(5, len(x)) # number of previous results to consider
615
+ x = x[np.argsort(-fitness(x))][:n] # top n mutations
616
+ w = fitness(x) - fitness(x).min() + 1E-6 # weights (sum > 0)
617
+ if parent == 'single' or len(x) == 1:
618
+ # x = x[random.randint(0, n - 1)] # random selection
619
+ x = x[random.choices(range(n), weights=w)[0]] # weighted selection
620
+ elif parent == 'weighted':
621
+ x = (x * w.reshape(n, 1)).sum(0) / w.sum() # weighted combination
622
+
623
+ # Mutate
624
+ mp, s = 0.8, 0.2 # mutation probability, sigma
625
+ npr = np.random
626
+ npr.seed(int(time.time()))
627
+ g = np.array([meta[k][0] for k in hyp.keys()]) # gains 0-1
628
+ ng = len(meta)
629
+ v = np.ones(ng)
630
+ while all(v == 1): # mutate until a change occurs (prevent duplicates)
631
+ v = (g * (npr.random(ng) < mp) * npr.randn(ng) * npr.random() * s + 1).clip(0.3, 3.0)
632
+ for i, k in enumerate(hyp.keys()): # plt.hist(v.ravel(), 300)
633
+ hyp[k] = float(x[i + 7] * v[i]) # mutate
634
+
635
+ # Constrain to limits
636
+ for k, v in meta.items():
637
+ hyp[k] = max(hyp[k], v[1]) # lower limit
638
+ hyp[k] = min(hyp[k], v[2]) # upper limit
639
+ hyp[k] = round(hyp[k], 5) # significant digits
640
+
641
+ # Train mutation
642
+ results = train(hyp.copy(), opt, device, callbacks)
643
+ callbacks = Callbacks()
644
+ # Write mutation results
645
+ print_mutation(KEYS, results, hyp.copy(), save_dir, opt.bucket)
646
+
647
+ # Plot results
648
+ plot_evolve(evolve_csv)
649
+ LOGGER.info(f'Hyperparameter evolution finished {opt.evolve} generations\n'
650
+ f"Results saved to {colorstr('bold', save_dir)}\n"
651
+ f'Usage example: $ python train.py --hyp {evolve_yaml}')
652
+
653
+
654
+ def run(**kwargs):
655
+ # Usage: import train; train.run(data='coco128.yaml', imgsz=320, weights='yolov5m.pt')
656
+ opt = parse_opt(True)
657
+ for k, v in kwargs.items():
658
+ setattr(opt, k, v)
659
+ main(opt)
660
+ return opt
661
+
662
+
663
+ if __name__ == '__main__':
664
+ opt = parse_opt()
665
+ main(opt)
yolov5-code-main/segment/tutorial.ipynb ADDED
@@ -0,0 +1,654 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "t6MPjfT5NrKQ",
7
+ "pycharm": {
8
+ "name": "#%% md\n"
9
+ }
10
+ },
11
+ "source": [
12
+ "<div align=\"center\">\n",
13
+ "\n",
14
+ " <a href=\"https://ultralytics.com/yolov5\" target=\"_blank\">\n",
15
+ " <img width=\"1024\", src=\"https://raw.githubusercontent.com/ultralytics/assets/main/yolov5/v70/splash.png\"></a>\n",
16
+ "\n",
17
+ "\n",
18
+ "<br>\n",
19
+ " <a href=\"https://bit.ly/yolov5-paperspace-notebook\"><img src=\"https://assets.paperspace.io/img/gradient-badge.svg\" alt=\"Run on Gradient\"></a>\n",
20
+ " <a href=\"https://colab.research.google.com/github/ultralytics/yolov5/blob/master/segment/tutorial.ipynb\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"></a>\n",
21
+ " <a href=\"https://www.kaggle.com/ultralytics/yolov5\"><img src=\"https://kaggle.com/static/images/open-in-kaggle.svg\" alt=\"Open In Kaggle\"></a>\n",
22
+ "<br>\n",
23
+ "\n",
24
+ "This <a href=\"https://github.com/ultralytics/yolov5\">YOLOv5</a> 🚀 notebook by <a href=\"https://ultralytics.com\">Ultralytics</a> presents simple train, validate and predict examples to help start your AI adventure.<br>See <a href=\"https://github.com/ultralytics/yolov5/issues/new/choose\">GitHub</a> for community support or <a href=\"https://ultralytics.com/contact\">contact us</a> for professional support.\n",
25
+ "\n",
26
+ "</div>"
27
+ ]
28
+ },
29
+ {
30
+ "cell_type": "markdown",
31
+ "metadata": {
32
+ "id": "7mGmQbAO5pQb",
33
+ "pycharm": {
34
+ "name": "#%% md\n"
35
+ }
36
+ },
37
+ "source": [
38
+ "# Setup\n",
39
+ "\n",
40
+ "Clone GitHub [repository](https://github.com/ultralytics/yolov5), install [dependencies](https://github.com/ultralytics/yolov5/blob/master/requirements.txt) and check PyTorch and GPU."
41
+ ]
42
+ },
43
+ {
44
+ "cell_type": "code",
45
+ "execution_count": null,
46
+ "metadata": {
47
+ "colab": {
48
+ "base_uri": "https://localhost:8080/"
49
+ },
50
+ "id": "wbvMlHd_QwMG",
51
+ "outputId": "171b23f0-71b9-4cbf-b666-6fa2ecef70c8",
52
+ "pycharm": {
53
+ "name": "#%%\n"
54
+ }
55
+ },
56
+ "outputs": [
57
+ {
58
+ "output_type": "stream",
59
+ "name": "stderr",
60
+ "text": [
61
+ "YOLOv5 🚀 v7.0-2-gc9d47ae Python-3.7.15 torch-1.12.1+cu113 CUDA:0 (Tesla T4, 15110MiB)\n"
62
+ ]
63
+ },
64
+ {
65
+ "output_type": "stream",
66
+ "name": "stdout",
67
+ "text": [
68
+ "Setup complete ✅ (2 CPUs, 12.7 GB RAM, 22.6/78.2 GB disk)\n"
69
+ ]
70
+ }
71
+ ],
72
+ "source": [
73
+ "!git clone https://github.com/ultralytics/yolov5 # clone\n",
74
+ "%cd yolov5\n",
75
+ "%pip install -qr requirements.txt # install\n",
76
+ "\n",
77
+ "import torch\n",
78
+ "import utils\n",
79
+ "display = utils.notebook_init() # checks"
80
+ ]
81
+ },
82
+ {
83
+ "cell_type": "markdown",
84
+ "metadata": {
85
+ "id": "4JnkELT0cIJg",
86
+ "pycharm": {
87
+ "name": "#%% md\n"
88
+ }
89
+ },
90
+ "source": [
91
+ "# 1. Predict\n",
92
+ "\n",
93
+ "`segment/predict.py` runs YOLOv5 instance segmentation inference on a variety of sources, downloading models automatically from the [latest YOLOv5 release](https://github.com/ultralytics/yolov5/releases), and saving results to `runs/predict`. Example inference sources are:\n",
94
+ "\n",
95
+ "```shell\n",
96
+ "python segment/predict.py --source 0 # webcam\n",
97
+ " img.jpg # image \n",
98
+ " vid.mp4 # video\n",
99
+ " screen # screenshot\n",
100
+ " path/ # directory\n",
101
+ " 'path/*.jpg' # glob\n",
102
+ " 'https://youtu.be/Zgi9g1ksQHc' # YouTube\n",
103
+ " 'rtsp://example.com/media.mp4' # RTSP, RTMP, HTTP stream\n",
104
+ "```"
105
+ ]
106
+ },
107
+ {
108
+ "cell_type": "code",
109
+ "execution_count": null,
110
+ "metadata": {
111
+ "colab": {
112
+ "base_uri": "https://localhost:8080/"
113
+ },
114
+ "id": "zR9ZbuQCH7FX",
115
+ "outputId": "3f67f1c7-f15e-4fa5-d251-967c3b77eaad",
116
+ "pycharm": {
117
+ "name": "#%%\n"
118
+ }
119
+ },
120
+ "outputs": [
121
+ {
122
+ "output_type": "stream",
123
+ "name": "stdout",
124
+ "text": [
125
+ "\u001B[34m\u001B[1msegment/predict: \u001B[0mweights=['yolov5s-seg.pt'], source=data/images, data=data/coco128.yaml, imgsz=[640, 640], conf_thres=0.25, iou_thres=0.45, max_det=1000, device=, view_img=False, save_txt=False, save_conf=False, save_crop=False, nosave=False, classes=None, agnostic_nms=False, augment=False, visualize=False, update=False, project=runs/predict-seg, name=exp, exist_ok=False, line_thickness=3, hide_labels=False, hide_conf=False, half=False, dnn=False, vid_stride=1, retina_masks=False\n",
126
+ "YOLOv5 🚀 v7.0-2-gc9d47ae Python-3.7.15 torch-1.12.1+cu113 CUDA:0 (Tesla T4, 15110MiB)\n",
127
+ "\n",
128
+ "Downloading https://github.com/ultralytics/yolov5/releases/download/v7.0/yolov5s-seg.pt to yolov5s-seg.pt...\n",
129
+ "100% 14.9M/14.9M [00:01<00:00, 12.0MB/s]\n",
130
+ "\n",
131
+ "Fusing layers... \n",
132
+ "YOLOv5s-seg summary: 224 layers, 7611485 parameters, 0 gradients, 26.4 GFLOPs\n",
133
+ "image 1/2 /content/yolov5/data/images/bus.jpg: 640x480 4 persons, 1 bus, 18.2ms\n",
134
+ "image 2/2 /content/yolov5/data/images/zidane.jpg: 384x640 2 persons, 1 tie, 13.4ms\n",
135
+ "Speed: 0.5ms pre-process, 15.8ms inference, 18.5ms NMS per image at shape (1, 3, 640, 640)\n",
136
+ "Results saved to \u001B[1mruns/predict-seg/exp\u001B[0m\n"
137
+ ]
138
+ }
139
+ ],
140
+ "source": [
141
+ "!python segment/predict.py --weights yolov5s-seg.pt --img 640 --conf 0.25 --source data/images\n",
142
+ "#display.Image(filename='runs/predict-seg/exp/zidane.jpg', width=600)"
143
+ ]
144
+ },
145
+ {
146
+ "cell_type": "markdown",
147
+ "metadata": {
148
+ "id": "hkAzDWJ7cWTr",
149
+ "pycharm": {
150
+ "name": "#%% md\n"
151
+ }
152
+ },
153
+ "source": [
154
+ "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n",
155
+ "<img align=\"left\" src=\"https://user-images.githubusercontent.com/26833433/199030123-08c72f8d-6871-4116-8ed3-c373642cf28e.jpg\" width=\"600\">"
156
+ ]
157
+ },
158
+ {
159
+ "cell_type": "markdown",
160
+ "metadata": {
161
+ "id": "0eq1SMWl6Sfn",
162
+ "pycharm": {
163
+ "name": "#%% md\n"
164
+ }
165
+ },
166
+ "source": [
167
+ "# 2. Validate\n",
168
+ "Validate a model's accuracy on the [COCO](https://cocodataset.org/#home) dataset's `val` or `test` splits. Models are downloaded automatically from the [latest YOLOv5 release](https://github.com/ultralytics/yolov5/releases). To show results by class use the `--verbose` flag."
169
+ ]
170
+ },
171
+ {
172
+ "cell_type": "code",
173
+ "execution_count": null,
174
+ "metadata": {
175
+ "colab": {
176
+ "base_uri": "https://localhost:8080/"
177
+ },
178
+ "id": "WQPtK1QYVaD_",
179
+ "outputId": "9d751d8c-bee8-4339-cf30-9854ca530449",
180
+ "pycharm": {
181
+ "name": "#%%\n"
182
+ }
183
+ },
184
+ "outputs": [
185
+ {
186
+ "output_type": "stream",
187
+ "name": "stdout",
188
+ "text": [
189
+ "Downloading https://github.com/ultralytics/yolov5/releases/download/v1.0/coco2017labels-segments.zip ...\n",
190
+ "Downloading http://images.cocodataset.org/zips/val2017.zip ...\n",
191
+ "######################################################################## 100.0%\n",
192
+ "######################################################################## 100.0%\n"
193
+ ]
194
+ }
195
+ ],
196
+ "source": [
197
+ "# Download COCO val\n",
198
+ "!bash data/scripts/get_coco.sh --val --segments # download (780M - 5000 images)"
199
+ ]
200
+ },
201
+ {
202
+ "cell_type": "code",
203
+ "execution_count": null,
204
+ "metadata": {
205
+ "colab": {
206
+ "base_uri": "https://localhost:8080/"
207
+ },
208
+ "id": "X58w8JLpMnjH",
209
+ "outputId": "a140d67a-02da-479e-9ddb-7d54bf9e407a",
210
+ "pycharm": {
211
+ "name": "#%%\n"
212
+ }
213
+ },
214
+ "outputs": [
215
+ {
216
+ "output_type": "stream",
217
+ "name": "stdout",
218
+ "text": [
219
+ "\u001B[34m\u001B[1msegment/val: \u001B[0mdata=/content/yolov5/data/coco.yaml, weights=['yolov5s-seg.pt'], batch_size=32, imgsz=640, conf_thres=0.001, iou_thres=0.6, max_det=300, task=val, device=, workers=8, single_cls=False, augment=False, verbose=False, save_txt=False, save_hybrid=False, save_conf=False, save_json=False, project=runs/val-seg, name=exp, exist_ok=False, half=True, dnn=False\n",
220
+ "YOLOv5 🚀 v7.0-2-gc9d47ae Python-3.7.15 torch-1.12.1+cu113 CUDA:0 (Tesla T4, 15110MiB)\n",
221
+ "\n",
222
+ "Fusing layers... \n",
223
+ "YOLOv5s-seg summary: 224 layers, 7611485 parameters, 0 gradients, 26.4 GFLOPs\n",
224
+ "\u001B[34m\u001B[1mval: \u001B[0mScanning /content/datasets/coco/val2017... 4952 images, 48 backgrounds, 0 corrupt: 100% 5000/5000 [00:03<00:00, 1361.31it/s]\n",
225
+ "\u001B[34m\u001B[1mval: \u001B[0mNew cache created: /content/datasets/coco/val2017.cache\n",
226
+ " Class Images Instances Box(P R mAP50 mAP50-95) Mask(P R mAP50 mAP50-95): 100% 157/157 [01:54<00:00, 1.37it/s]\n",
227
+ " all 5000 36335 0.673 0.517 0.566 0.373 0.672 0.49 0.532 0.319\n",
228
+ "Speed: 0.6ms pre-process, 4.4ms inference, 2.9ms NMS per image at shape (32, 3, 640, 640)\n",
229
+ "Results saved to \u001B[1mruns/val-seg/exp\u001B[0m\n"
230
+ ]
231
+ }
232
+ ],
233
+ "source": [
234
+ "# Validate YOLOv5s-seg on COCO val\n",
235
+ "!python segment/val.py --weights yolov5s-seg.pt --data coco.yaml --img 640 --half"
236
+ ]
237
+ },
238
+ {
239
+ "cell_type": "markdown",
240
+ "metadata": {
241
+ "id": "ZY2VXXXu74w5",
242
+ "pycharm": {
243
+ "name": "#%% md\n"
244
+ }
245
+ },
246
+ "source": [
247
+ "# 3. Train\n",
248
+ "\n",
249
+ "<p align=\"\"><a href=\"https://roboflow.com/?ref=ultralytics\"><img width=\"1000\" src=\"https://github.com/ultralytics/assets/raw/main/im/integrations-loop.png\"/></a></p>\n",
250
+ "Close the active learning loop by sampling images from your inference conditions with the `roboflow` pip package\n",
251
+ "<br><br>\n",
252
+ "\n",
253
+ "Train a YOLOv5s-seg model on the [COCO128](https://www.kaggle.com/ultralytics/coco128) dataset with `--data coco128-seg.yaml`, starting from pretrained `--weights yolov5s-seg.pt`, or from randomly initialized `--weights '' --cfg yolov5s-seg.yaml`.\n",
254
+ "\n",
255
+ "- **Pretrained [Models](https://github.com/ultralytics/yolov5/tree/master/models)** are downloaded\n",
256
+ "automatically from the [latest YOLOv5 release](https://github.com/ultralytics/yolov5/releases)\n",
257
+ "- **[Datasets](https://github.com/ultralytics/yolov5/tree/master/data)** available for autodownload include: [COCO](https://github.com/ultralytics/yolov5/blob/master/data/coco.yaml), [COCO128](https://github.com/ultralytics/yolov5/blob/master/data/coco128.yaml), [VOC](https://github.com/ultralytics/yolov5/blob/master/data/VOC.yaml), [Argoverse](https://github.com/ultralytics/yolov5/blob/master/data/Argoverse.yaml), [VisDrone](https://github.com/ultralytics/yolov5/blob/master/data/VisDrone.yaml), [GlobalWheat](https://github.com/ultralytics/yolov5/blob/master/data/GlobalWheat2020.yaml), [xView](https://github.com/ultralytics/yolov5/blob/master/data/xView.yaml), [Objects365](https://github.com/ultralytics/yolov5/blob/master/data/Objects365.yaml), [SKU-110K](https://github.com/ultralytics/yolov5/blob/master/data/SKU-110K.yaml).\n",
258
+ "- **Training Results** are saved to `runs/train-seg/` with incrementing run directories, i.e. `runs/train-seg/exp2`, `runs/train-seg/exp3` etc.\n",
259
+ "<br><br>\n",
260
+ "\n",
261
+ "A **Mosaic Dataloader** is used for training which combines 4 images into 1 mosaic.\n",
262
+ "\n",
263
+ "## Train on Custom Data with Roboflow 🌟 NEW\n",
264
+ "\n",
265
+ "[Roboflow](https://roboflow.com/?ref=ultralytics) enables you to easily **organize, label, and prepare** a high quality dataset with your own custom data. Roboflow also makes it easy to establish an active learning pipeline, collaborate with your team on dataset improvement, and integrate directly into your model building workflow with the `roboflow` pip package.\n",
266
+ "\n",
267
+ "- Custom Training Example: [https://blog.roboflow.com/train-yolov5-instance-segmentation-custom-dataset/](https://blog.roboflow.com/train-yolov5-instance-segmentation-custom-dataset/?ref=ultralytics)\n",
268
+ "- Custom Training Notebook: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1JTz7kpmHsg-5qwVz2d2IH3AaenI1tv0N?usp=sharing)\n",
269
+ "<br>\n",
270
+ "\n",
271
+ "<p align=\"\"><a href=\"https://roboflow.com/?ref=ultralytics\"><img width=\"480\" src=\"https://robflow-public-assets.s3.amazonaws.com/how-to-train-yolov5-segmentation-annotation.gif\"/></a></p>Label images lightning fast (including with model-assisted labeling)"
272
+ ]
273
+ },
274
+ {
275
+ "cell_type": "code",
276
+ "execution_count": null,
277
+ "metadata": {
278
+ "id": "i3oKtE4g-aNn",
279
+ "pycharm": {
280
+ "name": "#%%\n"
281
+ }
282
+ },
283
+ "outputs": [],
284
+ "source": [
285
+ "#@title Select YOLOv5 🚀 logger {run: 'auto'}\n",
286
+ "logger = 'TensorBoard' #@param ['TensorBoard', 'Comet', 'ClearML']\n",
287
+ "\n",
288
+ "if logger == 'TensorBoard':\n",
289
+ " %load_ext tensorboard\n",
290
+ " %tensorboard --logdir runs/train-seg\n",
291
+ "elif logger == 'Comet':\n",
292
+ " %pip install -q comet_ml\n",
293
+ " import comet_ml; comet_ml.init()\n",
294
+ "elif logger == 'ClearML':\n",
295
+ " import clearml; clearml.browser_login()"
296
+ ]
297
+ },
298
+ {
299
+ "cell_type": "code",
300
+ "execution_count": null,
301
+ "metadata": {
302
+ "colab": {
303
+ "base_uri": "https://localhost:8080/"
304
+ },
305
+ "id": "1NcFxRcFdJ_O",
306
+ "outputId": "3a3e0cf7-e79c-47a5-c8e7-2d26eeeab988",
307
+ "pycharm": {
308
+ "name": "#%%\n"
309
+ }
310
+ },
311
+ "outputs": [
312
+ {
313
+ "output_type": "stream",
314
+ "name": "stdout",
315
+ "text": [
316
+ "\u001B[34m\u001B[1msegment/train: \u001B[0mweights=yolov5s-seg.pt, cfg=, data=coco128-seg.yaml, hyp=data/hyps/hyp.scratch-low.yaml, epochs=3, batch_size=16, imgsz=640, rect=False, resume=False, nosave=False, noval=False, noautoanchor=False, noplots=False, evolve=None, bucket=, cache=ram, image_weights=False, device=, multi_scale=False, single_cls=False, optimizer=SGD, sync_bn=False, workers=8, project=runs/train-seg, name=exp, exist_ok=False, quad=False, cos_lr=False, label_smoothing=0.0, patience=100, freeze=[0], save_period=-1, seed=0, local_rank=-1, mask_ratio=4, no_overlap=False\n",
317
+ "\u001B[34m\u001B[1mgithub: \u001B[0mup to date with https://github.com/ultralytics/yolov5 ✅\n",
318
+ "YOLOv5 🚀 v7.0-2-gc9d47ae Python-3.7.15 torch-1.12.1+cu113 CUDA:0 (Tesla T4, 15110MiB)\n",
319
+ "\n",
320
+ "\u001B[34m\u001B[1mhyperparameters: \u001B[0mlr0=0.01, lrf=0.01, momentum=0.937, weight_decay=0.0005, warmup_epochs=3.0, warmup_momentum=0.8, warmup_bias_lr=0.1, box=0.05, cls=0.5, cls_pw=1.0, obj=1.0, obj_pw=1.0, iou_t=0.2, anchor_t=4.0, fl_gamma=0.0, hsv_h=0.015, hsv_s=0.7, hsv_v=0.4, degrees=0.0, translate=0.1, scale=0.5, shear=0.0, perspective=0.0, flipud=0.0, fliplr=0.5, mosaic=1.0, mixup=0.0, copy_paste=0.0\n",
321
+ "\u001B[34m\u001B[1mTensorBoard: \u001B[0mStart with 'tensorboard --logdir runs/train-seg', view at http://localhost:6006/\n",
322
+ "\n",
323
+ "Dataset not found ⚠️, missing paths ['/content/datasets/coco128-seg/images/train2017']\n",
324
+ "Downloading https://ultralytics.com/assets/coco128-seg.zip to coco128-seg.zip...\n",
325
+ "100% 6.79M/6.79M [00:01<00:00, 6.73MB/s]\n",
326
+ "Dataset download success ✅ (1.9s), saved to \u001B[1m/content/datasets\u001B[0m\n",
327
+ "\n",
328
+ " from n params module arguments \n",
329
+ " 0 -1 1 3520 models.common.Conv [3, 32, 6, 2, 2] \n",
330
+ " 1 -1 1 18560 models.common.Conv [32, 64, 3, 2] \n",
331
+ " 2 -1 1 18816 models.common.C3 [64, 64, 1] \n",
332
+ " 3 -1 1 73984 models.common.Conv [64, 128, 3, 2] \n",
333
+ " 4 -1 2 115712 models.common.C3 [128, 128, 2] \n",
334
+ " 5 -1 1 295424 models.common.Conv [128, 256, 3, 2] \n",
335
+ " 6 -1 3 625152 models.common.C3 [256, 256, 3] \n",
336
+ " 7 -1 1 1180672 models.common.Conv [256, 512, 3, 2] \n",
337
+ " 8 -1 1 1182720 models.common.C3 [512, 512, 1] \n",
338
+ " 9 -1 1 656896 models.common.SPPF [512, 512, 5] \n",
339
+ " 10 -1 1 131584 models.common.Conv [512, 256, 1, 1] \n",
340
+ " 11 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest'] \n",
341
+ " 12 [-1, 6] 1 0 models.common.Concat [1] \n",
342
+ " 13 -1 1 361984 models.common.C3 [512, 256, 1, False] \n",
343
+ " 14 -1 1 33024 models.common.Conv [256, 128, 1, 1] \n",
344
+ " 15 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest'] \n",
345
+ " 16 [-1, 4] 1 0 models.common.Concat [1] \n",
346
+ " 17 -1 1 90880 models.common.C3 [256, 128, 1, False] \n",
347
+ " 18 -1 1 147712 models.common.Conv [128, 128, 3, 2] \n",
348
+ " 19 [-1, 14] 1 0 models.common.Concat [1] \n",
349
+ " 20 -1 1 296448 models.common.C3 [256, 256, 1, False] \n",
350
+ " 21 -1 1 590336 models.common.Conv [256, 256, 3, 2] \n",
351
+ " 22 [-1, 10] 1 0 models.common.Concat [1] \n",
352
+ " 23 -1 1 1182720 models.common.C3 [512, 512, 1, False] \n",
353
+ " 24 [17, 20, 23] 1 615133 models.yolo.Segment [80, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], 32, 128, [128, 256, 512]]\n",
354
+ "Model summary: 225 layers, 7621277 parameters, 7621277 gradients, 26.6 GFLOPs\n",
355
+ "\n",
356
+ "Transferred 367/367 items from yolov5s-seg.pt\n",
357
+ "\u001B[34m\u001B[1mAMP: \u001B[0mchecks passed ✅\n",
358
+ "\u001B[34m\u001B[1moptimizer:\u001B[0m SGD(lr=0.01) with parameter groups 60 weight(decay=0.0), 63 weight(decay=0.0005), 63 bias\n",
359
+ "\u001B[34m\u001B[1malbumentations: \u001B[0mBlur(p=0.01, blur_limit=(3, 7)), MedianBlur(p=0.01, blur_limit=(3, 7)), ToGray(p=0.01), CLAHE(p=0.01, clip_limit=(1, 4.0), tile_grid_size=(8, 8))\n",
360
+ "\u001B[34m\u001B[1mtrain: \u001B[0mScanning /content/datasets/coco128-seg/labels/train2017... 126 images, 2 backgrounds, 0 corrupt: 100% 128/128 [00:00<00:00, 1389.59it/s]\n",
361
+ "\u001B[34m\u001B[1mtrain: \u001B[0mNew cache created: /content/datasets/coco128-seg/labels/train2017.cache\n",
362
+ "\u001B[34m\u001B[1mtrain: \u001B[0mCaching images (0.1GB ram): 100% 128/128 [00:00<00:00, 238.86it/s]\n",
363
+ "\u001B[34m\u001B[1mval: \u001B[0mScanning /content/datasets/coco128-seg/labels/train2017.cache... 126 images, 2 backgrounds, 0 corrupt: 100% 128/128 [00:00<?, ?it/s]\n",
364
+ "\u001B[34m\u001B[1mval: \u001B[0mCaching images (0.1GB ram): 100% 128/128 [00:01<00:00, 98.90it/s]\n",
365
+ "\n",
366
+ "\u001B[34m\u001B[1mAutoAnchor: \u001B[0m4.27 anchors/target, 0.994 Best Possible Recall (BPR). Current anchors are a good fit to dataset ✅\n",
367
+ "Plotting labels to runs/train-seg/exp/labels.jpg... \n",
368
+ "Image sizes 640 train, 640 val\n",
369
+ "Using 2 dataloader workers\n",
370
+ "Logging results to \u001B[1mruns/train-seg/exp\u001B[0m\n",
371
+ "Starting training for 3 epochs...\n",
372
+ "\n",
373
+ " Epoch GPU_mem box_loss seg_loss obj_loss cls_loss Instances Size\n",
374
+ " 0/2 4.92G 0.0417 0.04646 0.06066 0.02126 192 640: 100% 8/8 [00:08<00:00, 1.10s/it]\n",
375
+ " Class Images Instances Box(P R mAP50 mAP50-95) Mask(P R mAP50 mAP50-95): 100% 4/4 [00:02<00:00, 1.81it/s]\n",
376
+ " all 128 929 0.737 0.649 0.715 0.492 0.719 0.617 0.658 0.408\n",
377
+ "\n",
378
+ " Epoch GPU_mem box_loss seg_loss obj_loss cls_loss Instances Size\n",
379
+ " 1/2 6.29G 0.04157 0.04503 0.05772 0.01777 208 640: 100% 8/8 [00:09<00:00, 1.21s/it]\n",
380
+ " Class Images Instances Box(P R mAP50 mAP50-95) Mask(P R mAP50 mAP50-95): 100% 4/4 [00:02<00:00, 1.87it/s]\n",
381
+ " all 128 929 0.756 0.674 0.738 0.506 0.725 0.64 0.68 0.422\n",
382
+ "\n",
383
+ " Epoch GPU_mem box_loss seg_loss obj_loss cls_loss Instances Size\n",
384
+ " 2/2 6.29G 0.0425 0.04793 0.06784 0.01863 161 640: 100% 8/8 [00:03<00:00, 2.02it/s]\n",
385
+ " Class Images Instances Box(P R mAP50 mAP50-95) Mask(P R mAP50 mAP50-95): 100% 4/4 [00:02<00:00, 1.88it/s]\n",
386
+ " all 128 929 0.736 0.694 0.747 0.522 0.769 0.622 0.683 0.427\n",
387
+ "\n",
388
+ "3 epochs completed in 0.009 hours.\n",
389
+ "Optimizer stripped from runs/train-seg/exp/weights/last.pt, 15.6MB\n",
390
+ "Optimizer stripped from runs/train-seg/exp/weights/best.pt, 15.6MB\n",
391
+ "\n",
392
+ "Validating runs/train-seg/exp/weights/best.pt...\n",
393
+ "Fusing layers... \n",
394
+ "Model summary: 165 layers, 7611485 parameters, 0 gradients, 26.4 GFLOPs\n",
395
+ " Class Images Instances Box(P R mAP50 mAP50-95) Mask(P R mAP50 mAP50-95): 100% 4/4 [00:06<00:00, 1.59s/it]\n",
396
+ " all 128 929 0.738 0.694 0.746 0.522 0.759 0.625 0.682 0.426\n",
397
+ " person 128 254 0.845 0.756 0.836 0.55 0.861 0.669 0.759 0.407\n",
398
+ " bicycle 128 6 0.475 0.333 0.549 0.341 0.711 0.333 0.526 0.322\n",
399
+ " car 128 46 0.612 0.565 0.539 0.257 0.555 0.435 0.477 0.171\n",
400
+ " motorcycle 128 5 0.73 0.8 0.752 0.571 0.747 0.8 0.752 0.42\n",
401
+ " airplane 128 6 1 0.943 0.995 0.732 0.92 0.833 0.839 0.555\n",
402
+ " bus 128 7 0.677 0.714 0.722 0.653 0.711 0.714 0.722 0.593\n",
403
+ " train 128 3 1 0.951 0.995 0.551 1 0.884 0.995 0.781\n",
404
+ " truck 128 12 0.555 0.417 0.457 0.285 0.624 0.417 0.397 0.277\n",
405
+ " boat 128 6 0.624 0.5 0.584 0.186 1 0.326 0.412 0.133\n",
406
+ " traffic light 128 14 0.513 0.302 0.411 0.247 0.435 0.214 0.376 0.251\n",
407
+ " stop sign 128 2 0.824 1 0.995 0.796 0.906 1 0.995 0.747\n",
408
+ " bench 128 9 0.75 0.667 0.763 0.367 0.724 0.585 0.698 0.209\n",
409
+ " bird 128 16 0.961 1 0.995 0.686 0.918 0.938 0.91 0.525\n",
410
+ " cat 128 4 0.771 0.857 0.945 0.752 0.76 0.8 0.945 0.728\n",
411
+ " dog 128 9 0.987 0.778 0.963 0.681 1 0.705 0.89 0.574\n",
412
+ " horse 128 2 0.703 1 0.995 0.697 0.759 1 0.995 0.249\n",
413
+ " elephant 128 17 0.916 0.882 0.93 0.691 0.811 0.765 0.829 0.537\n",
414
+ " bear 128 1 0.664 1 0.995 0.995 0.701 1 0.995 0.895\n",
415
+ " zebra 128 4 0.864 1 0.995 0.921 0.879 1 0.995 0.804\n",
416
+ " giraffe 128 9 0.883 0.889 0.94 0.683 0.845 0.778 0.78 0.463\n",
417
+ " backpack 128 6 1 0.59 0.701 0.372 1 0.474 0.52 0.252\n",
418
+ " umbrella 128 18 0.654 0.839 0.887 0.52 0.517 0.556 0.427 0.229\n",
419
+ " handbag 128 19 0.54 0.211 0.408 0.221 0.796 0.206 0.396 0.196\n",
420
+ " tie 128 7 0.864 0.857 0.857 0.577 0.925 0.857 0.857 0.534\n",
421
+ " suitcase 128 4 0.716 1 0.945 0.647 0.767 1 0.945 0.634\n",
422
+ " frisbee 128 5 0.708 0.8 0.761 0.643 0.737 0.8 0.761 0.501\n",
423
+ " skis 128 1 0.691 1 0.995 0.796 0.761 1 0.995 0.199\n",
424
+ " snowboard 128 7 0.918 0.857 0.904 0.604 0.32 0.286 0.235 0.137\n",
425
+ " sports ball 128 6 0.902 0.667 0.701 0.466 0.727 0.5 0.497 0.471\n",
426
+ " kite 128 10 0.586 0.4 0.511 0.231 0.663 0.394 0.417 0.139\n",
427
+ " baseball bat 128 4 0.359 0.5 0.401 0.169 0.631 0.5 0.526 0.133\n",
428
+ " baseball glove 128 7 1 0.519 0.58 0.327 0.687 0.286 0.455 0.328\n",
429
+ " skateboard 128 5 0.729 0.8 0.862 0.631 0.599 0.6 0.604 0.379\n",
430
+ " tennis racket 128 7 0.57 0.714 0.645 0.448 0.608 0.714 0.645 0.412\n",
431
+ " bottle 128 18 0.469 0.393 0.537 0.357 0.661 0.389 0.543 0.349\n",
432
+ " wine glass 128 16 0.677 0.938 0.866 0.441 0.53 0.625 0.67 0.334\n",
433
+ " cup 128 36 0.777 0.722 0.812 0.466 0.725 0.583 0.762 0.467\n",
434
+ " fork 128 6 0.948 0.333 0.425 0.27 0.527 0.167 0.18 0.102\n",
435
+ " knife 128 16 0.757 0.587 0.669 0.458 0.79 0.5 0.552 0.34\n",
436
+ " spoon 128 22 0.74 0.364 0.559 0.269 0.925 0.364 0.513 0.213\n",
437
+ " bowl 128 28 0.766 0.714 0.725 0.559 0.803 0.584 0.665 0.353\n",
438
+ " banana 128 1 0.408 1 0.995 0.398 0.539 1 0.995 0.497\n",
439
+ " sandwich 128 2 1 0 0.695 0.536 1 0 0.498 0.448\n",
440
+ " orange 128 4 0.467 1 0.995 0.693 0.518 1 0.995 0.663\n",
441
+ " broccoli 128 11 0.462 0.455 0.383 0.259 0.548 0.455 0.384 0.256\n",
442
+ " carrot 128 24 0.631 0.875 0.77 0.533 0.757 0.909 0.853 0.499\n",
443
+ " hot dog 128 2 0.555 1 0.995 0.995 0.578 1 0.995 0.796\n",
444
+ " pizza 128 5 0.89 0.8 0.962 0.796 1 0.778 0.962 0.766\n",
445
+ " donut 128 14 0.695 1 0.893 0.772 0.704 1 0.893 0.696\n",
446
+ " cake 128 4 0.826 1 0.995 0.92 0.862 1 0.995 0.846\n",
447
+ " chair 128 35 0.53 0.571 0.613 0.336 0.67 0.6 0.538 0.271\n",
448
+ " couch 128 6 0.972 0.667 0.833 0.627 1 0.62 0.696 0.394\n",
449
+ " potted plant 128 14 0.7 0.857 0.883 0.552 0.836 0.857 0.883 0.473\n",
450
+ " bed 128 3 0.979 0.667 0.83 0.366 1 0 0.83 0.373\n",
451
+ " dining table 128 13 0.775 0.308 0.505 0.364 0.644 0.231 0.25 0.0804\n",
452
+ " toilet 128 2 0.836 1 0.995 0.846 0.887 1 0.995 0.797\n",
453
+ " tv 128 2 0.6 1 0.995 0.846 0.655 1 0.995 0.896\n",
454
+ " laptop 128 3 0.822 0.333 0.445 0.307 1 0 0.392 0.12\n",
455
+ " mouse 128 2 1 0 0 0 1 0 0 0\n",
456
+ " remote 128 8 0.745 0.5 0.62 0.459 0.821 0.5 0.624 0.449\n",
457
+ " cell phone 128 8 0.686 0.375 0.502 0.272 0.488 0.25 0.28 0.132\n",
458
+ " microwave 128 3 0.831 1 0.995 0.722 0.867 1 0.995 0.592\n",
459
+ " oven 128 5 0.439 0.4 0.435 0.294 0.823 0.6 0.645 0.418\n",
460
+ " sink 128 6 0.677 0.5 0.565 0.448 0.722 0.5 0.46 0.362\n",
461
+ " refrigerator 128 5 0.533 0.8 0.783 0.524 0.558 0.8 0.783 0.527\n",
462
+ " book 128 29 0.732 0.379 0.423 0.196 0.69 0.207 0.38 0.131\n",
463
+ " clock 128 9 0.889 0.778 0.917 0.677 0.908 0.778 0.875 0.604\n",
464
+ " vase 128 2 0.375 1 0.995 0.995 0.455 1 0.995 0.796\n",
465
+ " scissors 128 1 1 0 0.0166 0.00166 1 0 0 0\n",
466
+ " teddy bear 128 21 0.813 0.829 0.841 0.457 0.826 0.678 0.786 0.422\n",
467
+ " toothbrush 128 5 0.806 1 0.995 0.733 0.991 1 0.995 0.628\n",
468
+ "Results saved to \u001B[1mruns/train-seg/exp\u001B[0m\n"
469
+ ]
470
+ }
471
+ ],
472
+ "source": [
473
+ "# Train YOLOv5s on COCO128 for 3 epochs\n",
474
+ "!python segment/train.py --img 640 --batch 16 --epochs 3 --data coco128-seg.yaml --weights yolov5s-seg.pt --cache"
475
+ ]
476
+ },
477
+ {
478
+ "cell_type": "markdown",
479
+ "metadata": {
480
+ "id": "15glLzbQx5u0",
481
+ "pycharm": {
482
+ "name": "#%% md\n"
483
+ }
484
+ },
485
+ "source": [
486
+ "# 4. Visualize"
487
+ ]
488
+ },
489
+ {
490
+ "cell_type": "markdown",
491
+ "metadata": {
492
+ "id": "nWOsI5wJR1o3",
493
+ "pycharm": {
494
+ "name": "#%% md\n"
495
+ }
496
+ },
497
+ "source": [
498
+ "## Comet Logging and Visualization 🌟 NEW\n",
499
+ "\n",
500
+ "[Comet](https://www.comet.com/site/lp/yolov5-with-comet/?utm_source=yolov5&utm_medium=partner&utm_campaign=partner_yolov5_2022&utm_content=yolov5_colab) is now fully integrated with YOLOv5. Track and visualize model metrics in real time, save your hyperparameters, datasets, and model checkpoints, and visualize your model predictions with [Comet Custom Panels](https://www.comet.com/docs/v2/guides/comet-dashboard/code-panels/about-panels/?utm_source=yolov5&utm_medium=partner&utm_campaign=partner_yolov5_2022&utm_content=yolov5_colab)! Comet makes sure you never lose track of your work and makes it easy to share results and collaborate across teams of all sizes!\n",
501
+ "\n",
502
+ "Getting started is easy:\n",
503
+ "```shell\n",
504
+ "pip install comet_ml # 1. install\n",
505
+ "export COMET_API_KEY=<Your API Key> # 2. paste API key\n",
506
+ "python train.py --img 640 --epochs 3 --data coco128.yaml --weights yolov5s.pt # 3. train\n",
507
+ "```\n",
508
+ "To learn more about all of the supported Comet features for this integration, check out the [Comet Tutorial](https://github.com/ultralytics/yolov5/tree/master/utils/loggers/comet). If you'd like to learn more about Comet, head over to our [documentation](https://www.comet.com/docs/v2/?utm_source=yolov5&utm_medium=partner&utm_campaign=partner_yolov5_2022&utm_content=yolov5_colab). Get started by trying out the Comet Colab Notebook:\n",
509
+ "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1RG0WOQyxlDlo5Km8GogJpIEJlg_5lyYO?usp=sharing)\n",
510
+ "\n",
511
+ "<a href=\"https://bit.ly/yolov5-readme-comet2\">\n",
512
+ "<img alt=\"Comet Dashboard\" src=\"https://user-images.githubusercontent.com/26833433/202851203-164e94e1-2238-46dd-91f8-de020e9d6b41.png\" width=\"1280\"/></a>"
513
+ ]
514
+ },
515
+ {
516
+ "cell_type": "markdown",
517
+ "metadata": {
518
+ "id": "Lay2WsTjNJzP",
519
+ "pycharm": {
520
+ "name": "#%% md\n"
521
+ }
522
+ },
523
+ "source": [
524
+ "## ClearML Logging and Automation 🌟 NEW\n",
525
+ "\n",
526
+ "[ClearML](https://cutt.ly/yolov5-notebook-clearml) is completely integrated into YOLOv5 to track your experimentation, manage dataset versions and even remotely execute training runs. To enable ClearML (check cells above):\n",
527
+ "\n",
528
+ "- `pip install clearml`\n",
529
+ "- run `clearml-init` to connect to a ClearML server (**deploy your own [open-source server](https://github.com/allegroai/clearml-server)**, or use our [free hosted server](https://cutt.ly/yolov5-notebook-clearml))\n",
530
+ "\n",
531
+ "You'll get all the great expected features from an experiment manager: live updates, model upload, experiment comparison etc. but ClearML also tracks uncommitted changes and installed packages for example. Thanks to that ClearML Tasks (which is what we call experiments) are also reproducible on different machines! With only 1 extra line, we can schedule a YOLOv5 training task on a queue to be executed by any number of ClearML Agents (workers).\n",
532
+ "\n",
533
+ "You can use ClearML Data to version your dataset and then pass it to YOLOv5 simply using its unique ID. This will help you keep track of your data without adding extra hassle. Explore the [ClearML Tutorial](https://github.com/ultralytics/yolov5/tree/master/utils/loggers/clearml) for details!\n",
534
+ "\n",
535
+ "<a href=\"https://cutt.ly/yolov5-notebook-clearml\">\n",
536
+ "<img alt=\"ClearML Experiment Management UI\" src=\"https://github.com/thepycoder/clearml_screenshots/raw/main/scalars.jpg\" width=\"1280\"/></a>"
537
+ ]
538
+ },
539
+ {
540
+ "cell_type": "markdown",
541
+ "metadata": {
542
+ "id": "-WPvRbS5Swl6",
543
+ "pycharm": {
544
+ "name": "#%% md\n"
545
+ }
546
+ },
547
+ "source": [
548
+ "## Local Logging\n",
549
+ "\n",
550
+ "Training results are automatically logged with [Tensorboard](https://www.tensorflow.org/tensorboard) and [CSV](https://github.com/ultralytics/yolov5/pull/4148) loggers to `runs/train`, with a new experiment directory created for each new training as `runs/train/exp2`, `runs/train/exp3`, etc.\n",
551
+ "\n",
552
+ "This directory contains train and val statistics, mosaics, labels, predictions and augmentated mosaics, as well as metrics and charts including precision-recall (PR) curves and confusion matrices. \n",
553
+ "\n",
554
+ "<img alt=\"Local logging results\" src=\"https://user-images.githubusercontent.com/26833433/183222430-e1abd1b7-782c-4cde-b04d-ad52926bf818.jpg\" width=\"1280\"/>\n"
555
+ ]
556
+ },
557
+ {
558
+ "cell_type": "markdown",
559
+ "metadata": {
560
+ "id": "Zelyeqbyt3GD",
561
+ "pycharm": {
562
+ "name": "#%% md\n"
563
+ }
564
+ },
565
+ "source": [
566
+ "# Environments\n",
567
+ "\n",
568
+ "YOLOv5 may be run in any of the following up-to-date verified environments (with all dependencies including [CUDA](https://developer.nvidia.com/cuda)/[CUDNN](https://developer.nvidia.com/cudnn), [Python](https://www.python.org/) and [PyTorch](https://pytorch.org/) preinstalled):\n",
569
+ "\n",
570
+ "- **Notebooks** with free GPU: <a href=\"https://bit.ly/yolov5-paperspace-notebook\"><img src=\"https://assets.paperspace.io/img/gradient-badge.svg\" alt=\"Run on Gradient\"></a> <a href=\"https://colab.research.google.com/github/ultralytics/yolov5/blob/master/tutorial.ipynb\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"></a> <a href=\"https://www.kaggle.com/ultralytics/yolov5\"><img src=\"https://kaggle.com/static/images/open-in-kaggle.svg\" alt=\"Open In Kaggle\"></a>\n",
571
+ "- **Google Cloud** Deep Learning VM. See [GCP Quickstart Guide](https://github.com/ultralytics/yolov5/wiki/GCP-Quickstart)\n",
572
+ "- **Amazon** Deep Learning AMI. See [AWS Quickstart Guide](https://github.com/ultralytics/yolov5/wiki/AWS-Quickstart)\n",
573
+ "- **Docker Image**. See [Docker Quickstart Guide](https://github.com/ultralytics/yolov5/wiki/Docker-Quickstart) <a href=\"https://hub.docker.com/r/ultralytics/yolov5\"><img src=\"https://img.shields.io/docker/pulls/ultralytics/yolov5?logo=docker\" alt=\"Docker Pulls\"></a>\n"
574
+ ]
575
+ },
576
+ {
577
+ "cell_type": "markdown",
578
+ "metadata": {
579
+ "id": "6Qu7Iesl0p54",
580
+ "pycharm": {
581
+ "name": "#%% md\n"
582
+ }
583
+ },
584
+ "source": [
585
+ "# Status\n",
586
+ "\n",
587
+ "![YOLOv5 CI](https://github.com/ultralytics/yolov5/actions/workflows/ci-testing.yml/badge.svg)\n",
588
+ "\n",
589
+ "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 ([val.py](https://github.com/ultralytics/yolov5/blob/master/val.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"
590
+ ]
591
+ },
592
+ {
593
+ "cell_type": "markdown",
594
+ "metadata": {
595
+ "id": "IEijrePND_2I",
596
+ "pycharm": {
597
+ "name": "#%% md\n"
598
+ }
599
+ },
600
+ "source": [
601
+ "# Appendix\n",
602
+ "\n",
603
+ "Additional content below."
604
+ ]
605
+ },
606
+ {
607
+ "cell_type": "code",
608
+ "execution_count": null,
609
+ "metadata": {
610
+ "id": "GMusP4OAxFu6",
611
+ "pycharm": {
612
+ "name": "#%%\n"
613
+ }
614
+ },
615
+ "outputs": [],
616
+ "source": [
617
+ "# YOLOv5 PyTorch HUB Inference (DetectionModels only)\n",
618
+ "import torch\n",
619
+ "\n",
620
+ "model = torch.hub.load('ultralytics/yolov5', 'yolov5s-seg') # yolov5n - yolov5x6 or custom\n",
621
+ "im = 'https://ultralytics.com/images/zidane.jpg' # file, Path, PIL.Image, OpenCV, nparray, list\n",
622
+ "results = model(im) # inference\n",
623
+ "results.print() # or .show(), .save(), .crop(), .pandas(), etc."
624
+ ]
625
+ }
626
+ ],
627
+ "metadata": {
628
+ "accelerator": "GPU",
629
+ "colab": {
630
+ "name": "YOLOv5 Segmentation Tutorial",
631
+ "provenance": [],
632
+ "toc_visible": true
633
+ },
634
+ "kernelspec": {
635
+ "display_name": "Python 3 (ipykernel)",
636
+ "language": "python",
637
+ "name": "python3"
638
+ },
639
+ "language_info": {
640
+ "codemirror_mode": {
641
+ "name": "ipython",
642
+ "version": 3
643
+ },
644
+ "file_extension": ".py",
645
+ "mimetype": "text/x-python",
646
+ "name": "python",
647
+ "nbconvert_exporter": "python",
648
+ "pygments_lexer": "ipython3",
649
+ "version": "3.7.12"
650
+ }
651
+ },
652
+ "nbformat": 4,
653
+ "nbformat_minor": 0
654
+ }
yolov5-code-main/segment/val.py ADDED
@@ -0,0 +1,473 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # YOLOv5 🚀 by Ultralytics, GPL-3.0 license
2
+ """
3
+ Validate a trained YOLOv5 segment model on a segment dataset
4
+
5
+ Usage:
6
+ $ bash data/scripts/get_coco.sh --val --segments # download COCO-segments val split (1G, 5000 images)
7
+ $ python segment/val.py --weights yolov5s-seg.pt --data coco.yaml --img 640 # validate COCO-segments
8
+
9
+ Usage - formats:
10
+ $ python segment/val.py --weights yolov5s-seg.pt # PyTorch
11
+ yolov5s-seg.torchscript # TorchScript
12
+ yolov5s-seg.onnx # ONNX Runtime or OpenCV DNN with --dnn
13
+ yolov5s-seg_openvino_label # OpenVINO
14
+ yolov5s-seg.engine # TensorRT
15
+ yolov5s-seg.mlmodel # CoreML (macOS-only)
16
+ yolov5s-seg_saved_model # TensorFlow SavedModel
17
+ yolov5s-seg.pb # TensorFlow GraphDef
18
+ yolov5s-seg.tflite # TensorFlow Lite
19
+ yolov5s-seg_edgetpu.tflite # TensorFlow Edge TPU
20
+ yolov5s-seg_paddle_model # PaddlePaddle
21
+ """
22
+
23
+ import argparse
24
+ import json
25
+ import os
26
+ import subprocess
27
+ import sys
28
+ from multiprocessing.pool import ThreadPool
29
+ from pathlib import Path
30
+
31
+ import numpy as np
32
+ import torch
33
+ from tqdm import tqdm
34
+
35
+ FILE = Path(__file__).resolve()
36
+ ROOT = FILE.parents[1] # YOLOv5 root directory
37
+ if str(ROOT) not in sys.path:
38
+ sys.path.append(str(ROOT)) # add ROOT to PATH
39
+ ROOT = Path(os.path.relpath(ROOT, Path.cwd())) # relative
40
+
41
+ import torch.nn.functional as F
42
+
43
+ from models.common import DetectMultiBackend
44
+ from models.yolo import SegmentationModel
45
+ from utils.callbacks import Callbacks
46
+ from utils.general import (LOGGER, NUM_THREADS, TQDM_BAR_FORMAT, Profile, check_dataset, check_img_size,
47
+ check_requirements, check_yaml, coco80_to_coco91_class, colorstr, increment_path,
48
+ non_max_suppression, print_args, scale_boxes, xywh2xyxy, xyxy2xywh)
49
+ from utils.metrics import ConfusionMatrix, box_iou
50
+ from utils.plots import output_to_target, plot_val_study
51
+ from utils.segment.dataloaders import create_dataloader
52
+ from utils.segment.general import mask_iou, process_mask, process_mask_native, scale_image
53
+ from utils.segment.metrics import Metrics, ap_per_class_box_and_mask
54
+ from utils.segment.plots import plot_images_and_masks
55
+ from utils.torch_utils import de_parallel, select_device, smart_inference_mode
56
+
57
+
58
+ def save_one_txt(predn, save_conf, shape, file):
59
+ # Save one txt result
60
+ gn = torch.tensor(shape)[[1, 0, 1, 0]] # normalization gain whwh
61
+ for *xyxy, conf, cls in predn.tolist():
62
+ xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist() # normalized xywh
63
+ line = (cls, *xywh, conf) if save_conf else (cls, *xywh) # label format
64
+ with open(file, 'a') as f:
65
+ f.write(('%g ' * len(line)).rstrip() % line + '\n')
66
+
67
+
68
+ def save_one_json(predn, jdict, path, class_map, pred_masks):
69
+ # Save one JSON result {"image_id": 42, "category_id": 18, "bbox": [258.15, 41.29, 348.26, 243.78], "score": 0.236}
70
+ from pycocotools.mask import encode
71
+
72
+ def single_encode(x):
73
+ rle = encode(np.asarray(x[:, :, None], order='F', dtype='uint8'))[0]
74
+ rle['counts'] = rle['counts'].decode('utf-8')
75
+ return rle
76
+
77
+ image_id = int(path.stem) if path.stem.isnumeric() else path.stem
78
+ box = xyxy2xywh(predn[:, :4]) # xywh
79
+ box[:, :2] -= box[:, 2:] / 2 # xy center to top-left corner
80
+ pred_masks = np.transpose(pred_masks, (2, 0, 1))
81
+ with ThreadPool(NUM_THREADS) as pool:
82
+ rles = pool.map(single_encode, pred_masks)
83
+ for i, (p, b) in enumerate(zip(predn.tolist(), box.tolist())):
84
+ jdict.append({
85
+ 'image_id': image_id,
86
+ 'category_id': class_map[int(p[5])],
87
+ 'bbox': [round(x, 3) for x in b],
88
+ 'score': round(p[4], 5),
89
+ 'segmentation': rles[i]})
90
+
91
+
92
+ def process_batch(detections, labels, iouv, pred_masks=None, gt_masks=None, overlap=False, masks=False):
93
+ """
94
+ Return correct prediction matrix
95
+ Arguments:
96
+ detections (array[N, 6]), x1, y1, x2, y2, conf, class
97
+ labels (array[M, 5]), class, x1, y1, x2, y2
98
+ Returns:
99
+ correct (array[N, 10]), for 10 IoU levels
100
+ """
101
+ if masks:
102
+ if overlap:
103
+ nl = len(labels)
104
+ index = torch.arange(nl, device=gt_masks.device).view(nl, 1, 1) + 1
105
+ gt_masks = gt_masks.repeat(nl, 1, 1) # shape(1,640,640) -> (n,640,640)
106
+ gt_masks = torch.where(gt_masks == index, 1.0, 0.0)
107
+ if gt_masks.shape[1:] != pred_masks.shape[1:]:
108
+ gt_masks = F.interpolate(gt_masks[None], pred_masks.shape[1:], mode='bilinear', align_corners=False)[0]
109
+ gt_masks = gt_masks.gt_(0.5)
110
+ iou = mask_iou(gt_masks.view(gt_masks.shape[0], -1), pred_masks.view(pred_masks.shape[0], -1))
111
+ else: # boxes
112
+ iou = box_iou(labels[:, 1:], detections[:, :4])
113
+
114
+ correct = np.zeros((detections.shape[0], iouv.shape[0])).astype(bool)
115
+ correct_class = labels[:, 0:1] == detections[:, 5]
116
+ for i in range(len(iouv)):
117
+ x = torch.where((iou >= iouv[i]) & correct_class) # IoU > threshold and classes match
118
+ if x[0].shape[0]:
119
+ matches = torch.cat((torch.stack(x, 1), iou[x[0], x[1]][:, None]), 1).cpu().numpy() # [label, detect, iou]
120
+ if x[0].shape[0] > 1:
121
+ matches = matches[matches[:, 2].argsort()[::-1]]
122
+ matches = matches[np.unique(matches[:, 1], return_index=True)[1]]
123
+ # matches = matches[matches[:, 2].argsort()[::-1]]
124
+ matches = matches[np.unique(matches[:, 0], return_index=True)[1]]
125
+ correct[matches[:, 1].astype(int), i] = True
126
+ return torch.tensor(correct, dtype=torch.bool, device=iouv.device)
127
+
128
+
129
+ @smart_inference_mode()
130
+ def run(
131
+ data,
132
+ weights=None, # model.pt path(s)
133
+ batch_size=32, # batch size
134
+ imgsz=640, # inference size (pixels)
135
+ conf_thres=0.001, # confidence threshold
136
+ iou_thres=0.6, # NMS IoU threshold
137
+ max_det=300, # maximum detections per image
138
+ task='val', # train, val, test, speed or study
139
+ device='', # cuda device, i.e. 0 or 0,1,2,3 or cpu
140
+ workers=8, # max dataloader workers (per RANK in DDP mode)
141
+ single_cls=False, # treat as single-class dataset
142
+ augment=False, # augmented inference
143
+ verbose=False, # verbose output
144
+ save_txt=False, # save results to *.txt
145
+ save_hybrid=False, # save label+prediction hybrid results to *.txt
146
+ save_conf=False, # save confidences in --save-txt labels
147
+ save_json=False, # save a COCO-JSON results file
148
+ project=ROOT / 'runs/val-seg', # save to project/name
149
+ name='exp', # save to project/name
150
+ exist_ok=False, # existing project/name ok, do not increment
151
+ half=True, # use FP16 half-precision inference
152
+ dnn=False, # use OpenCV DNN for ONNX inference
153
+ model=None,
154
+ dataloader=None,
155
+ save_dir=Path(''),
156
+ plots=True,
157
+ overlap=False,
158
+ mask_downsample_ratio=1,
159
+ compute_loss=None,
160
+ callbacks=Callbacks(),
161
+ ):
162
+ if save_json:
163
+ check_requirements('pycocotools>=2.0.6')
164
+ process = process_mask_native # more accurate
165
+ else:
166
+ process = process_mask # faster
167
+
168
+ # Initialize/load model and set device
169
+ training = model is not None
170
+ if training: # called by train.py
171
+ device, pt, jit, engine = next(model.parameters()).device, True, False, False # get model device, PyTorch model
172
+ half &= device.type != 'cpu' # half precision only supported on CUDA
173
+ model.half() if half else model.float()
174
+ nm = de_parallel(model).model[-1].nm # number of masks
175
+ else: # called directly
176
+ device = select_device(device, batch_size=batch_size)
177
+
178
+ # Directories
179
+ save_dir = increment_path(Path(project) / name, exist_ok=exist_ok) # increment run
180
+ (save_dir / 'labels' if save_txt else save_dir).mkdir(parents=True, exist_ok=True) # make dir
181
+
182
+ # Load model
183
+ model = DetectMultiBackend(weights, device=device, dnn=dnn, data=data, fp16=half)
184
+ stride, pt, jit, engine = model.stride, model.pt, model.jit, model.engine
185
+ imgsz = check_img_size(imgsz, s=stride) # check image size
186
+ half = model.fp16 # FP16 supported on limited backends with CUDA
187
+ nm = de_parallel(model).model.model[-1].nm if isinstance(model, SegmentationModel) else 32 # number of masks
188
+ if engine:
189
+ batch_size = model.batch_size
190
+ else:
191
+ device = model.device
192
+ if not (pt or jit):
193
+ batch_size = 1 # export.py models default to batch-size 1
194
+ LOGGER.info(f'Forcing --batch-size 1 square inference (1,3,{imgsz},{imgsz}) for non-PyTorch models')
195
+
196
+ # Data
197
+ data = check_dataset(data) # check
198
+
199
+ # Configure
200
+ model.eval()
201
+ cuda = device.type != 'cpu'
202
+ is_coco = isinstance(data.get('val'), str) and data['val'].endswith(f'coco{os.sep}val2017.txt') # COCO dataset
203
+ nc = 1 if single_cls else int(data['nc']) # number of classes
204
+ iouv = torch.linspace(0.5, 0.95, 10, device=device) # iou vector for mAP@0.5:0.95
205
+ niou = iouv.numel()
206
+
207
+ # Dataloader
208
+ if not training:
209
+ if pt and not single_cls: # check --weights are trained on --data
210
+ ncm = model.model.nc
211
+ assert ncm == nc, f'{weights} ({ncm} classes) trained on different --data than what you passed ({nc} ' \
212
+ f'classes). Pass correct combination of --weights and --data that are trained together.'
213
+ model.warmup(imgsz=(1 if pt else batch_size, 3, imgsz, imgsz)) # warmup
214
+ pad, rect = (0.0, False) if task == 'speed' else (0.5, pt) # square inference for benchmarks
215
+ task = task if task in ('train', 'val', 'test') else 'val' # path to train/val/test images
216
+ dataloader = create_dataloader(data[task],
217
+ imgsz,
218
+ batch_size,
219
+ stride,
220
+ single_cls,
221
+ pad=pad,
222
+ rect=rect,
223
+ workers=workers,
224
+ prefix=colorstr(f'{task}: '),
225
+ overlap_mask=overlap,
226
+ mask_downsample_ratio=mask_downsample_ratio)[0]
227
+
228
+ seen = 0
229
+ confusion_matrix = ConfusionMatrix(nc=nc)
230
+ names = model.names if hasattr(model, 'names') else model.module.names # get class names
231
+ if isinstance(names, (list, tuple)): # old format
232
+ names = dict(enumerate(names))
233
+ class_map = coco80_to_coco91_class() if is_coco else list(range(1000))
234
+ s = ('%22s' + '%11s' * 10) % ('Class', 'Images', 'Instances', 'Box(P', 'R', 'mAP50', 'mAP50-95)', 'Mask(P', 'R',
235
+ 'mAP50', 'mAP50-95)')
236
+ dt = Profile(), Profile(), Profile()
237
+ metrics = Metrics()
238
+ loss = torch.zeros(4, device=device)
239
+ jdict, stats = [], []
240
+ # callbacks.run('on_val_start')
241
+ pbar = tqdm(dataloader, desc=s, bar_format=TQDM_BAR_FORMAT) # progress bar
242
+ for batch_i, (im, targets, paths, shapes, masks) in enumerate(pbar):
243
+ # callbacks.run('on_val_batch_start')
244
+ with dt[0]:
245
+ if cuda:
246
+ im = im.to(device, non_blocking=True)
247
+ targets = targets.to(device)
248
+ masks = masks.to(device)
249
+ masks = masks.float()
250
+ im = im.half() if half else im.float() # uint8 to fp16/32
251
+ im /= 255 # 0 - 255 to 0.0 - 1.0
252
+ nb, _, height, width = im.shape # batch size, channels, height, width
253
+
254
+ # Inference
255
+ with dt[1]:
256
+ preds, protos, train_out = model(im) if compute_loss else (*model(im, augment=augment)[:2], None)
257
+
258
+ # Loss
259
+ if compute_loss:
260
+ loss += compute_loss((train_out, protos), targets, masks)[1] # box, obj, cls
261
+
262
+ # NMS
263
+ targets[:, 2:] *= torch.tensor((width, height, width, height), device=device) # to pixels
264
+ lb = [targets[targets[:, 0] == i, 1:] for i in range(nb)] if save_hybrid else [] # for autolabelling
265
+ with dt[2]:
266
+ preds = non_max_suppression(preds,
267
+ conf_thres,
268
+ iou_thres,
269
+ labels=lb,
270
+ multi_label=True,
271
+ agnostic=single_cls,
272
+ max_det=max_det,
273
+ nm=nm)
274
+
275
+ # Metrics
276
+ plot_masks = [] # masks for plotting
277
+ for si, (pred, proto) in enumerate(zip(preds, protos)):
278
+ labels = targets[targets[:, 0] == si, 1:]
279
+ nl, npr = labels.shape[0], pred.shape[0] # number of labels, predictions
280
+ path, shape = Path(paths[si]), shapes[si][0]
281
+ correct_masks = torch.zeros(npr, niou, dtype=torch.bool, device=device) # init
282
+ correct_bboxes = torch.zeros(npr, niou, dtype=torch.bool, device=device) # init
283
+ seen += 1
284
+
285
+ if npr == 0:
286
+ if nl:
287
+ stats.append((correct_masks, correct_bboxes, *torch.zeros((2, 0), device=device), labels[:, 0]))
288
+ if plots:
289
+ confusion_matrix.process_batch(detections=None, labels=labels[:, 0])
290
+ continue
291
+
292
+ # Masks
293
+ midx = [si] if overlap else targets[:, 0] == si
294
+ gt_masks = masks[midx]
295
+ pred_masks = process(proto, pred[:, 6:], pred[:, :4], shape=im[si].shape[1:])
296
+
297
+ # Predictions
298
+ if single_cls:
299
+ pred[:, 5] = 0
300
+ predn = pred.clone()
301
+ scale_boxes(im[si].shape[1:], predn[:, :4], shape, shapes[si][1]) # native-space pred
302
+
303
+ # Evaluate
304
+ if nl:
305
+ tbox = xywh2xyxy(labels[:, 1:5]) # target boxes
306
+ scale_boxes(im[si].shape[1:], tbox, shape, shapes[si][1]) # native-space labels
307
+ labelsn = torch.cat((labels[:, 0:1], tbox), 1) # native-space labels
308
+ correct_bboxes = process_batch(predn, labelsn, iouv)
309
+ correct_masks = process_batch(predn, labelsn, iouv, pred_masks, gt_masks, overlap=overlap, masks=True)
310
+ if plots:
311
+ confusion_matrix.process_batch(predn, labelsn)
312
+ stats.append((correct_masks, correct_bboxes, pred[:, 4], pred[:, 5], labels[:, 0])) # (conf, pcls, tcls)
313
+
314
+ pred_masks = torch.as_tensor(pred_masks, dtype=torch.uint8)
315
+ if plots and batch_i < 3:
316
+ plot_masks.append(pred_masks[:15]) # filter top 15 to plot
317
+
318
+ # Save/log
319
+ if save_txt:
320
+ save_one_txt(predn, save_conf, shape, file=save_dir / 'labels' / f'{path.stem}.txt')
321
+ if save_json:
322
+ pred_masks = scale_image(im[si].shape[1:],
323
+ pred_masks.permute(1, 2, 0).contiguous().cpu().numpy(), shape, shapes[si][1])
324
+ save_one_json(predn, jdict, path, class_map, pred_masks) # append to COCO-JSON dictionary
325
+ # callbacks.run('on_val_image_end', pred, predn, path, names, im[si])
326
+
327
+ # Plot images
328
+ if plots and batch_i < 3:
329
+ if len(plot_masks):
330
+ plot_masks = torch.cat(plot_masks, dim=0)
331
+ plot_images_and_masks(im, targets, masks, paths, save_dir / f'val_batch{batch_i}_labels.jpg', names)
332
+ plot_images_and_masks(im, output_to_target(preds, max_det=15), plot_masks, paths,
333
+ save_dir / f'val_batch{batch_i}_pred.jpg', names) # pred
334
+
335
+ # callbacks.run('on_val_batch_end')
336
+
337
+ # Compute metrics
338
+ stats = [torch.cat(x, 0).cpu().numpy() for x in zip(*stats)] # to numpy
339
+ if len(stats) and stats[0].any():
340
+ results = ap_per_class_box_and_mask(*stats, plot=plots, save_dir=save_dir, names=names)
341
+ metrics.update(results)
342
+ nt = np.bincount(stats[4].astype(int), minlength=nc) # number of targets per class
343
+
344
+ # Print results
345
+ pf = '%22s' + '%11i' * 2 + '%11.3g' * 8 # print format
346
+ LOGGER.info(pf % ('all', seen, nt.sum(), *metrics.mean_results()))
347
+ if nt.sum() == 0:
348
+ LOGGER.warning(f'WARNING ⚠️ no labels found in {task} set, can not compute metrics without labels')
349
+
350
+ # Print results per class
351
+ if (verbose or (nc < 50 and not training)) and nc > 1 and len(stats):
352
+ for i, c in enumerate(metrics.ap_class_index):
353
+ LOGGER.info(pf % (names[c], seen, nt[c], *metrics.class_result(i)))
354
+
355
+ # Print speeds
356
+ t = tuple(x.t / seen * 1E3 for x in dt) # speeds per image
357
+ if not training:
358
+ shape = (batch_size, 3, imgsz, imgsz)
359
+ LOGGER.info(f'Speed: %.1fms pre-process, %.1fms inference, %.1fms NMS per image at shape {shape}' % t)
360
+
361
+ # Plots
362
+ if plots:
363
+ confusion_matrix.plot(save_dir=save_dir, names=list(names.values()))
364
+ # callbacks.run('on_val_end')
365
+
366
+ mp_bbox, mr_bbox, map50_bbox, map_bbox, mp_mask, mr_mask, map50_mask, map_mask = metrics.mean_results()
367
+
368
+ # Save JSON
369
+ if save_json and len(jdict):
370
+ w = Path(weights[0] if isinstance(weights, list) else weights).stem if weights is not None else '' # weights
371
+ anno_json = str(Path('../datasets/coco/annotations/instances_val2017.json')) # annotations
372
+ pred_json = str(save_dir / f'{w}_predictions.json') # predictions
373
+ LOGGER.info(f'\nEvaluating pycocotools mAP... saving {pred_json}...')
374
+ with open(pred_json, 'w') as f:
375
+ json.dump(jdict, f)
376
+
377
+ try: # https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocoEvalDemo.ipynb
378
+ from pycocotools.coco import COCO
379
+ from pycocotools.cocoeval import COCOeval
380
+
381
+ anno = COCO(anno_json) # init annotations api
382
+ pred = anno.loadRes(pred_json) # init predictions api
383
+ results = []
384
+ for eval in COCOeval(anno, pred, 'bbox'), COCOeval(anno, pred, 'segm'):
385
+ if is_coco:
386
+ eval.params.imgIds = [int(Path(x).stem) for x in dataloader.dataset.im_files] # img ID to evaluate
387
+ eval.evaluate()
388
+ eval.accumulate()
389
+ eval.summarize()
390
+ results.extend(eval.stats[:2]) # update results (mAP@0.5:0.95, mAP@0.5)
391
+ map_bbox, map50_bbox, map_mask, map50_mask = results
392
+ except Exception as e:
393
+ LOGGER.info(f'pycocotools unable to run: {e}')
394
+
395
+ # Return results
396
+ model.float() # for training
397
+ if not training:
398
+ s = f"\n{len(list(save_dir.glob('labels/*.txt')))} labels saved to {save_dir / 'labels'}" if save_txt else ''
399
+ LOGGER.info(f"Results saved to {colorstr('bold', save_dir)}{s}")
400
+ final_metric = mp_bbox, mr_bbox, map50_bbox, map_bbox, mp_mask, mr_mask, map50_mask, map_mask
401
+ return (*final_metric, *(loss.cpu() / len(dataloader)).tolist()), metrics.get_maps(nc), t
402
+
403
+
404
+ def parse_opt():
405
+ parser = argparse.ArgumentParser()
406
+ parser.add_argument('--data', type=str, default=ROOT / 'data/coco128-seg.yaml', help='dataset.yaml path')
407
+ parser.add_argument('--weights', nargs='+', type=str, default=ROOT / 'yolov5s-seg.pt', help='model path(s)')
408
+ parser.add_argument('--batch-size', type=int, default=32, help='batch size')
409
+ parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=640, help='inference size (pixels)')
410
+ parser.add_argument('--conf-thres', type=float, default=0.001, help='confidence threshold')
411
+ parser.add_argument('--iou-thres', type=float, default=0.6, help='NMS IoU threshold')
412
+ parser.add_argument('--max-det', type=int, default=300, help='maximum detections per image')
413
+ parser.add_argument('--task', default='val', help='train, val, test, speed or study')
414
+ parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
415
+ parser.add_argument('--workers', type=int, default=8, help='max dataloader workers (per RANK in DDP mode)')
416
+ parser.add_argument('--single-cls', action='store_true', help='treat as single-class dataset')
417
+ parser.add_argument('--augment', action='store_true', help='augmented inference')
418
+ parser.add_argument('--verbose', action='store_true', help='report mAP by class')
419
+ parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
420
+ parser.add_argument('--save-hybrid', action='store_true', help='save label+prediction hybrid results to *.txt')
421
+ parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
422
+ parser.add_argument('--save-json', action='store_true', help='save a COCO-JSON results file')
423
+ parser.add_argument('--project', default=ROOT / 'runs/val-seg', help='save results to project/name')
424
+ parser.add_argument('--name', default='exp', help='save to project/name')
425
+ parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
426
+ parser.add_argument('--half', action='store_true', help='use FP16 half-precision inference')
427
+ parser.add_argument('--dnn', action='store_true', help='use OpenCV DNN for ONNX inference')
428
+ opt = parser.parse_args()
429
+ opt.data = check_yaml(opt.data) # check YAML
430
+ # opt.save_json |= opt.data.endswith('coco.yaml')
431
+ opt.save_txt |= opt.save_hybrid
432
+ print_args(vars(opt))
433
+ return opt
434
+
435
+
436
+ def main(opt):
437
+ check_requirements(requirements=ROOT / 'requirements.txt', exclude=('tensorboard', 'thop'))
438
+
439
+ if opt.task in ('train', 'val', 'test'): # run normally
440
+ if opt.conf_thres > 0.001: # https://github.com/ultralytics/yolov5/issues/1466
441
+ LOGGER.warning(f'WARNING ⚠️ confidence threshold {opt.conf_thres} > 0.001 produces invalid results')
442
+ if opt.save_hybrid:
443
+ LOGGER.warning('WARNING ⚠️ --save-hybrid returns high mAP from hybrid labels, not from predictions alone')
444
+ run(**vars(opt))
445
+
446
+ else:
447
+ weights = opt.weights if isinstance(opt.weights, list) else [opt.weights]
448
+ opt.half = torch.cuda.is_available() and opt.device != 'cpu' # FP16 for fastest results
449
+ if opt.task == 'speed': # speed benchmarks
450
+ # python val.py --task speed --data coco.yaml --batch 1 --weights yolov5n.pt yolov5s.pt...
451
+ opt.conf_thres, opt.iou_thres, opt.save_json = 0.25, 0.45, False
452
+ for opt.weights in weights:
453
+ run(**vars(opt), plots=False)
454
+
455
+ elif opt.task == 'study': # speed vs mAP benchmarks
456
+ # python val.py --task study --data coco.yaml --iou 0.7 --weights yolov5n.pt yolov5s.pt...
457
+ for opt.weights in weights:
458
+ f = f'study_{Path(opt.data).stem}_{Path(opt.weights).stem}.txt' # filename to save to
459
+ x, y = list(range(256, 1536 + 128, 128)), [] # x axis (image sizes), y axis
460
+ for opt.imgsz in x: # img-size
461
+ LOGGER.info(f'\nRunning {f} --imgsz {opt.imgsz}...')
462
+ r, _, t = run(**vars(opt), plots=False)
463
+ y.append(r + t) # results and times
464
+ np.savetxt(f, y, fmt='%10.4g') # save
465
+ subprocess.run(['zip', '-r', 'study.zip', 'study_*.txt'])
466
+ plot_val_study(x=x) # plot
467
+ else:
468
+ raise NotImplementedError(f'--task {opt.task} not in ("train", "val", "test", "speed", "study")')
469
+
470
+
471
+ if __name__ == '__main__':
472
+ opt = parse_opt()
473
+ main(opt)