Compare commits

..

10 Commits

@ -0,0 +1,13 @@
# Train/val/test sets as
## 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: /home/xdobro23/data/yolov8_16bit/ # dataset root dir
train: images/train # train images (relative to 'path') 128 images
val: images/val # val images (relative to 'path') 128 images
# test: # test images (optional)
# Classes
nc: 1 # number of classes
names: ['green'] # class names
ch: 1

@ -0,0 +1,6 @@
from ultralytics import YOLO
# Load a model
model = YOLO('yolov8s.yaml')
results = model.train(data='data.yaml', save_period=10, epochs=5000, batch=10, imgsz=1504, patience=100, device=1)

@ -163,7 +163,7 @@ class Mosaic(BaseMixTransform):
# Place img in img4 # Place img in img4
if i == 0: # top left if i == 0: # top left
img4 = np.full((s * 2, s * 2, img.shape[2]), 114, dtype=np.uint8) # base image with 4 tiles img4 = np.full((s * 2, s * 2, 1), 114, dtype=np.float32) # base image with 4 tiles
x1a, y1a, x2a, y2a = max(xc - w, 0), max(yc - h, 0), xc, yc # xmin, ymin, xmax, ymax (large image) x1a, y1a, x2a, y2a = max(xc - w, 0), max(yc - h, 0), xc, yc # xmin, ymin, xmax, ymax (large image)
x1b, y1b, x2b, y2b = w - (x2a - x1a), h - (y2a - y1a), w, h # xmin, ymin, xmax, ymax (small image) x1b, y1b, x2b, y2b = w - (x2a - x1a), h - (y2a - y1a), w, h # xmin, ymin, xmax, ymax (small image)
elif i == 1: # top right elif i == 1: # top right
@ -176,7 +176,7 @@ class Mosaic(BaseMixTransform):
x1a, y1a, x2a, y2a = xc, yc, min(xc + w, s * 2), min(s * 2, yc + h) x1a, y1a, x2a, y2a = xc, yc, min(xc + w, s * 2), min(s * 2, yc + h)
x1b, y1b, x2b, y2b = 0, 0, min(w, x2a - x1a), min(y2a - y1a, h) x1b, y1b, x2b, y2b = 0, 0, min(w, x2a - x1a), min(y2a - y1a, h)
img4[y1a:y2a, x1a:x2a] = img[y1b:y2b, x1b:x2b] # img4[ymin:ymax, xmin:xmax] img4[y1a:y2a, x1a:x2a, 0] = img[y1b:y2b, x1b:x2b] # img4[ymin:ymax, xmin:xmax]
padw = x1a - x1b padw = x1a - x1b
padh = y1a - y1b padh = y1a - y1b
@ -199,7 +199,7 @@ class Mosaic(BaseMixTransform):
# Place img in img9 # Place img in img9
if i == 0: # center if i == 0: # center
img9 = np.full((s * 3, s * 3, img.shape[2]), 114, dtype=np.uint8) # base image with 4 tiles img9 = np.full((s * 3, s * 3, 1), 114, dtype=np.float32) # base image with 4 tiles
h0, w0 = h, w h0, w0 = h, w
c = s, s, s + w, s + h # xmin, ymin, xmax, ymax (base) coordinates c = s, s, s + w, s + h # xmin, ymin, xmax, ymax (base) coordinates
elif i == 1: # top elif i == 1: # top
@ -223,7 +223,7 @@ class Mosaic(BaseMixTransform):
x1, y1, x2, y2 = (max(x, 0) for x in c) # allocate coords x1, y1, x2, y2 = (max(x, 0) for x in c) # allocate coords
# Image # Image
img9[y1:y2, x1:x2] = img[y1 - padh:, x1 - padw:] # img9[ymin:ymax, xmin:xmax] img9[y1:y2, x1:x2, 0] = img[y1 - padh:, x1 - padw:] # img9[ymin:ymax, xmin:xmax]
hp, wp = h, w # height, width previous for next iteration hp, wp = h, w # height, width previous for next iteration
# Labels assuming imgsz*2 mosaic size # Labels assuming imgsz*2 mosaic size
@ -485,6 +485,7 @@ class RandomHSV:
def __call__(self, labels): def __call__(self, labels):
"""Applies random horizontal or vertical flip to an image with a given probability.""" """Applies random horizontal or vertical flip to an image with a given probability."""
img = labels['img'] img = labels['img']
return labels # TODO:
if self.hgain or self.sgain or self.vgain: if self.hgain or self.sgain or self.vgain:
r = np.random.uniform(-1, 1, 3) * [self.hgain, self.sgain, self.vgain] + 1 # random gains r = np.random.uniform(-1, 1, 3) * [self.hgain, self.sgain, self.vgain] + 1 # random gains
hue, sat, val = cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2HSV)) hue, sat, val = cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2HSV))
@ -712,7 +713,7 @@ class Format:
def __call__(self, labels): def __call__(self, labels):
"""Return formatted image, classes, bounding boxes & keypoints to be used by 'collate_fn'.""" """Return formatted image, classes, bounding boxes & keypoints to be used by 'collate_fn'."""
img = labels.pop('img') img = labels.pop('img')
h, w = img.shape[:2] h, w = img.shape[0], img.shape[1]
cls = labels.pop('cls') cls = labels.pop('cls')
instances = labels.pop('instances') instances = labels.pop('instances')
instances.convert_bbox(format=self.bbox_format) instances.convert_bbox(format=self.bbox_format)
@ -906,5 +907,5 @@ class ToTensor:
im = np.ascontiguousarray(im.transpose((2, 0, 1))[::-1]) # HWC to CHW -> BGR to RGB -> contiguous im = np.ascontiguousarray(im.transpose((2, 0, 1))[::-1]) # HWC to CHW -> BGR to RGB -> contiguous
im = torch.from_numpy(im) # to torch im = torch.from_numpy(im) # to torch
im = im.half() if self.half else im.float() # uint8 to fp16/32 im = im.half() if self.half else im.float() # uint8 to fp16/32
im /= 255.0 # 0-255 to 0.0-1.0 im /= 65535
return im return im

@ -249,7 +249,8 @@ class LoadImages:
else: else:
# Read image # Read image
self.count += 1 self.count += 1
im0 = cv2.imread(path) # BGR print("Grayscale image loading...")
im0 = cv2.imread(path, cv2.IMREAD_GRAYSCALE) # BGR
if im0 is None: if im0 is None:
raise FileNotFoundError(f'Image Not Found {path}') raise FileNotFoundError(f'Image Not Found {path}')
s = f'image {self.count}/{self.nf} {path}: ' s = f'image {self.count}/{self.nf} {path}: '

@ -122,7 +122,8 @@ class BasePredictor:
not_tensor = not isinstance(im, torch.Tensor) not_tensor = not isinstance(im, torch.Tensor)
if not_tensor: if not_tensor:
im = np.stack(self.pre_transform(im)) im = np.stack(self.pre_transform(im))
im = im[..., ::-1].transpose((0, 3, 1, 2)) # BGR to RGB, BHWC to BCHW, (n, 3, h, w) im = np.expand_dims(im, -1)
im = im[..., ::].transpose((0, 3, 1, 2)) # BGR to RGB, BHWC to BCHW, (n, 3, h, w)
im = np.ascontiguousarray(im) # contiguous im = np.ascontiguousarray(im) # contiguous
im = torch.from_numpy(im) im = torch.from_numpy(im)
@ -236,7 +237,7 @@ class BasePredictor:
# Warmup model # Warmup model
if not self.done_warmup: if not self.done_warmup:
self.model.warmup(imgsz=(1 if self.model.pt or self.model.triton else self.dataset.bs, 3, *self.imgsz)) self.model.warmup(imgsz=(1 if self.model.pt or self.model.triton else self.dataset.bs, 1, *self.imgsz))
self.done_warmup = True self.done_warmup = True
self.seen, self.windows, self.batch, profilers = 0, [], None, (ops.Profile(), ops.Profile(), ops.Profile()) self.seen, self.windows, self.batch, profilers = 0, [], None, (ops.Profile(), ops.Profile(), ops.Profile())

@ -157,7 +157,7 @@ class BaseValidator:
self.dataloader = self.dataloader or self.get_dataloader(self.data.get(self.args.split), self.args.batch) self.dataloader = self.dataloader or self.get_dataloader(self.data.get(self.args.split), self.args.batch)
model.eval() model.eval()
model.warmup(imgsz=(1 if pt else self.args.batch, 3, imgsz, imgsz)) # warmup model.warmup(imgsz=(1 if pt else self.args.batch, 1, imgsz, imgsz)) # warmup
dt = Profile(), Profile(), Profile(), Profile() dt = Profile(), Profile(), Profile(), Profile()
n_batches = len(self.dataloader) n_batches = len(self.dataloader)

@ -53,7 +53,7 @@ class DetectionTrainer(BaseTrainer):
def preprocess_batch(self, batch): def preprocess_batch(self, batch):
"""Preprocesses a batch of images by scaling and converting to float.""" """Preprocesses a batch of images by scaling and converting to float."""
batch['img'] = batch['img'].to(self.device, non_blocking=True).float() / 255 batch['img'] = batch['img'].to(self.device, non_blocking=True).float() / 65535.0 # uint16 to float16
return batch return batch
def set_model_attributes(self): def set_model_attributes(self):

@ -44,7 +44,7 @@ class DetectionValidator(BaseValidator):
def preprocess(self, batch): def preprocess(self, batch):
"""Preprocesses batch of images for YOLO training.""" """Preprocesses batch of images for YOLO training."""
batch['img'] = batch['img'].to(self.device, non_blocking=True) batch['img'] = batch['img'].to(self.device, non_blocking=True)
batch['img'] = (batch['img'].half() if self.args.half else batch['img'].float()) / 255 batch['img'] = (batch['img'].half() if self.args.half else batch['img'].float()) / 65535.0 # uint16 to float16
for k in ['batch_idx', 'cls', 'bboxes']: for k in ['batch_idx', 'cls', 'bboxes']:
batch[k] = batch[k].to(self.device) batch[k] = batch[k].to(self.device)

@ -445,7 +445,7 @@ class AutoBackend(nn.Module):
""" """
return torch.tensor(x).to(self.device) if isinstance(x, np.ndarray) else x return torch.tensor(x).to(self.device) if isinstance(x, np.ndarray) else x
def warmup(self, imgsz=(1, 3, 640, 640)): def warmup(self, imgsz=(1, 1, 640, 640)):
""" """
Warm up the model by running one forward pass with a dummy input. Warm up the model by running one forward pass with a dummy input.

@ -448,6 +448,7 @@ def check_amp(model):
Returns: Returns:
(bool): Returns True if the AMP functionality works correctly with YOLOv8 model, else False. (bool): Returns True if the AMP functionality works correctly with YOLOv8 model, else False.
""" """
return False
device = next(model.parameters()).device # get model device device = next(model.parameters()).device # get model device
if device.type in ('cpu', 'mps'): if device.type in ('cpu', 'mps'):
return False # AMP only used on CUDA devices return False # AMP only used on CUDA devices

Loading…
Cancel
Save