|
1 | 1 | # Run Ultralytics YOLOv8 pretrained model
|
2 | 2 |
|
3 |
| -YouTube tutorial link: [YOLOv8: Real-Time Object Detection Simplified](https://youtu.be/vegL__weCxY) |
| 3 | +YouTube tutorial link: |
| 4 | +- [YOLOv8: Real-Time Object Detection Simplified](https://youtu.be/vegL__weCxY); |
| 5 | +- [YOLOv8: Customizing Object Detector training](https://youtu.be/ysYiV1CbCyY); |
4 | 6 |
|
5 | 7 | First, I recommend you to install the required packages in a virtual environment:
|
6 | 8 | ```bash
|
7 |
| -mltu==1.2.3 |
| 9 | +mltu==1.2.5 |
8 | 10 | ultralytics==8.1.28
|
9 | 11 | torch==2.0.0
|
10 | 12 | torchvision==0.15.1
|
@@ -134,5 +136,175 @@ while True:
|
134 | 136 | break
|
135 | 137 |
|
136 | 138 | cap.release()
|
| 139 | +cv2.destroyAllWindows() |
| 140 | +``` |
| 141 | + |
| 142 | +## Customize YoloV8 Object Detector training: |
| 143 | +```python |
| 144 | +import os |
| 145 | +import time |
| 146 | +import torch |
| 147 | +from mltu.preprocessors import ImageReader |
| 148 | +from mltu.annotations.images import CVImage |
| 149 | +from mltu.transformers import ImageResizer, ImageShowCV2, ImageNormalizer |
| 150 | +from mltu.augmentors import RandomBrightness, RandomRotate, RandomErodeDilate, RandomSharpen, \ |
| 151 | + RandomMirror, RandomFlip, RandomGaussianBlur, RandomSaltAndPepper, RandomDropBlock, RandomMosaic, RandomElasticTransform |
| 152 | +from mltu.torch.model import Model |
| 153 | +from mltu.torch.dataProvider import DataProvider |
| 154 | +from mltu.torch.yolo.annotation import VOCAnnotationReader |
| 155 | +from mltu.torch.yolo.preprocessors import YoloPreprocessor |
| 156 | +from mltu.torch.yolo.loss import v8DetectionLoss |
| 157 | +from mltu.torch.yolo.metrics import YoloMetrics |
| 158 | +from mltu.torch.yolo.optimizer import build_optimizer, AccumulativeOptimizer |
| 159 | +from mltu.torch.callbacks import EarlyStopping, ModelCheckpoint, TensorBoard, Model2onnx, WarmupCosineDecay |
| 160 | + |
| 161 | +from ultralytics.nn.tasks import DetectionModel |
| 162 | +from ultralytics.engine.model import Model as BaseModel |
| 163 | + |
| 164 | +# https://www.kaggle.com/datasets/andrewmvd/car-plate-detection |
| 165 | +annotations_path = "Datasets/car-plate-detection/annotations" |
| 166 | + |
| 167 | +# Create a dataset from the annotations, the dataset is a list of lists where each list contains the [image path, annotation path] |
| 168 | +dataset = [[None, os.path.join(annotations_path, f)] for f in os.listdir(annotations_path)] |
| 169 | + |
| 170 | +# Make sure torch can see GPU device, it is not recommended to train with CPU |
| 171 | +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
| 172 | + |
| 173 | +img_size = 416 |
| 174 | +labels = {0: "licence"} |
| 175 | + |
| 176 | +# Create a data provider for the dataset |
| 177 | +data_provider = DataProvider( |
| 178 | + dataset=dataset, |
| 179 | + skip_validation=True, |
| 180 | + batch_size=16, |
| 181 | + data_preprocessors=[ |
| 182 | + VOCAnnotationReader(labels=labels), |
| 183 | + ImageReader(CVImage), |
| 184 | + ], |
| 185 | + transformers=[ |
| 186 | + # ImageShowCV2(), |
| 187 | + ImageResizer(img_size, img_size), |
| 188 | + ImageNormalizer(transpose_axis=True), |
| 189 | + ], |
| 190 | + batch_postprocessors=[ |
| 191 | + YoloPreprocessor(device, img_size) |
| 192 | + ], |
| 193 | + numpy=False, |
| 194 | +) |
| 195 | + |
| 196 | +# split the dataset into train and test |
| 197 | +train_data_provider, val_data_provider = data_provider.split(0.9, shuffle=False) |
| 198 | + |
| 199 | +# Attaach augmentation to the train data provider |
| 200 | +train_data_provider.augmentors = [ |
| 201 | + RandomBrightness(), |
| 202 | + RandomErodeDilate(), |
| 203 | + RandomSharpen(), |
| 204 | + RandomMirror(), |
| 205 | + RandomFlip(), |
| 206 | + RandomElasticTransform(), |
| 207 | + RandomGaussianBlur(), |
| 208 | + RandomSaltAndPepper(), |
| 209 | + RandomRotate(angle=10), |
| 210 | + RandomDropBlock(), |
| 211 | + RandomMosaic(), |
| 212 | +] |
| 213 | + |
| 214 | +base_model = BaseModel("yolov8n.pt") |
| 215 | +# Create a YOLO model |
| 216 | +model = DetectionModel('yolov8n.yaml', nc=len(labels)) |
| 217 | + |
| 218 | +# Load the weight from base model |
| 219 | +try: model.load_state_dict(base_model.model.state_dict(), strict=False) |
| 220 | +except: pass |
| 221 | + |
| 222 | +model.to(device) |
| 223 | + |
| 224 | +for k, v in model.named_parameters(): |
| 225 | + if any(x in k for x in [".dfl"]): |
| 226 | + print("freezing", k) |
| 227 | + v.requires_grad = False |
| 228 | + elif not v.requires_grad: |
| 229 | + v.requires_grad = True |
| 230 | + |
| 231 | +lr = 1e-3 |
| 232 | +optimizer = build_optimizer(model.model, name="AdamW", lr=lr, weight_decay=0.0, momentum=0.937, decay=0.0005) |
| 233 | +optimizer = AccumulativeOptimizer(optimizer, 16, 64) |
| 234 | + |
| 235 | +# create model object that will handle training and testing of the network |
| 236 | +model = Model( |
| 237 | + model, |
| 238 | + optimizer, |
| 239 | + v8DetectionLoss(model), |
| 240 | + metrics=[YoloMetrics(nc=len(labels))], |
| 241 | + log_errors=False, |
| 242 | + output_path=f"Models/11_Yolov8/{int(time.time())}", |
| 243 | + clip_grad_norm=10.0, |
| 244 | + ema=True, |
| 245 | +) |
| 246 | + |
| 247 | +modelCheckpoint = ModelCheckpoint(monitor="val_fitness", mode="max", save_best_only=True, verbose=True) |
| 248 | +tensorBoard = TensorBoard() |
| 249 | +earlyStopping = EarlyStopping(monitor="val_fitness", mode="max", patience=31, verbose=True) |
| 250 | +model2onnx = Model2onnx(input_shape=(1, 3, img_size, img_size), verbose=True, opset_version=14, |
| 251 | + dynamic_axes = {"input": {0: "batch_size", 2: "height", 3: "width"}, |
| 252 | + "output": {0: "batch_size", 2: "anchors"}}, |
| 253 | + metadata={"classes": labels}) |
| 254 | +warmupCosineDecayBias = WarmupCosineDecay(lr_after_warmup=lr, final_lr=lr, initial_lr=0.1, |
| 255 | + warmup_steps=len(train_data_provider), warmup_epochs=10, ignore_param_groups=[1, 2]) # lr0 |
| 256 | +warmupCosineDecay = WarmupCosineDecay(lr_after_warmup=lr, final_lr=lr/10, initial_lr=1e-7, |
| 257 | + warmup_steps=len(train_data_provider), warmup_epochs=10, decay_epochs=190, ignore_param_groups=[0]) # lr1 and lr2 |
| 258 | + |
| 259 | +# Train the model |
| 260 | +history = model.fit( |
| 261 | + train_data_provider, |
| 262 | + test_dataProvider=val_data_provider, |
| 263 | + epochs=200, |
| 264 | + callbacks=[ |
| 265 | + modelCheckpoint, |
| 266 | + tensorBoard, |
| 267 | + earlyStopping, |
| 268 | + model2onnx, |
| 269 | + warmupCosineDecayBias, |
| 270 | + warmupCosineDecay |
| 271 | + ] |
| 272 | + ) |
| 273 | +``` |
| 274 | + |
| 275 | +## Test Custom trained YoloV8 Object Detector: |
| 276 | +```python |
| 277 | +import os |
| 278 | +import cv2 |
| 279 | +from mltu.annotations.detections import Detections |
| 280 | +from mltu.torch.yolo.detectors.onnx_detector import Detector as OnnxDetector |
| 281 | + |
| 282 | +# https://www.kaggle.com/datasets/andrewmvd/car-plate-detection |
| 283 | +images_path = "Datasets/car-plate-detection/images" |
| 284 | + |
| 285 | +input_width, input_height = 416, 416 |
| 286 | +confidence_threshold = 0.5 |
| 287 | +iou_threshold = 0.5 |
| 288 | + |
| 289 | +detector = OnnxDetector("Models/11_Yolov8/1714135287/model.onnx", input_width, input_height, confidence_threshold, iou_threshold, force_cpu=False) |
| 290 | + |
| 291 | +for image_path in os.listdir(images_path): |
| 292 | + |
| 293 | + frame = cv2.imread(os.path.join(images_path, image_path)) |
| 294 | + |
| 295 | + # Perform Yolo object detection |
| 296 | + detections: Detections = detector(frame) |
| 297 | + |
| 298 | + # Apply the detections to the frame |
| 299 | + frame = detections.applyToFrame(frame) |
| 300 | + |
| 301 | + # Print the FPS |
| 302 | + print(detector.fps) |
| 303 | + |
| 304 | + # Display the output image |
| 305 | + cv2.imshow("Object Detection", frame) |
| 306 | + if cv2.waitKey(0) & 0xFF == ord('q'): |
| 307 | + break |
| 308 | + |
137 | 309 | cv2.destroyAllWindows()
|
138 | 310 | ```
|
0 commit comments