# Ultralytics YOLO 🚀, AGPL-3.0 license from ultralytics.engine.predictor import BasePredictor from ultralytics.engine.results import Results from ultralytics.utils import ops import numpy as np import torch class DetectionPredictor(BasePredictor): """ A class extending the BasePredictor class for prediction based on a detection model. Example: ```python from ultralytics.utils import ASSETS from ultralytics.models.yolo.detect import DetectionPredictor args = dict(model='yolov8n.pt', source=ASSETS) predictor = DetectionPredictor(overrides=args) predictor.predict_cli() ``` """ def preprocess(self, im): """ Prepares input image before inference. Args: im (torch.Tensor | List(np.ndarray)): BCHW for tensor, [(HWC) x B] for list. """ not_tensor = not isinstance(im, torch.Tensor) if not_tensor: im = np.stack(self.pre_transform(im)) im_rgb = im.copy() # for i in range(im.shape[3] // 3): # start_idx = i * 3 # channel_idx = list(range(start_idx, start_idx + 3)) # im_rgb[..., channel_idx] = im[..., channel_idx][:, :, ::-1] # BGR to RGB im = im_rgb.transpose((0, 3, 1, 2)) # BHWC to BCHW im = np.ascontiguousarray(im) # contiguous im = torch.from_numpy(im) im = im.to(self.device) im = im.half() if self.model.fp16 else im.float() # uint8 to fp16/32 if not_tensor: im /= 255 # 0 - 255 to 0.0 - 1.0 return im def postprocess(self, preds, img, orig_imgs): """Post-processes predictions and returns a list of Results objects.""" preds = ops.non_max_suppression( preds, self.args.conf, self.args.iou, agnostic=self.args.agnostic_nms, max_det=self.args.max_det, classes=self.args.classes, ) if not isinstance(orig_imgs, list): # input images are a torch.Tensor, not a list orig_imgs = ops.convert_torch2numpy_batch(orig_imgs) results = [] for i, pred in enumerate(preds): orig_img = orig_imgs[i] pred[:, :4] = ops.scale_boxes(img.shape[2:], pred[:, :4], orig_img.shape) # pred = self.fliplr(pred, orig_img.shape[1]) img_path = self.batch[0][i] results.append(Results(orig_img, path=img_path, names=self.model.names, boxes=pred)) return results def fliplr(self, pred, w): """Reverses the order of the bounding boxes and segments horizontally.""" bboxes = pred.clone() if True: # "xyxy" x1 = bboxes[:, 0].clone() x2 = bboxes[:, 2].clone() bboxes[:, 0] = w - x2 bboxes[:, 2] = w - x1 else: bboxes[:, 0] = w - bboxes[:, 0] return bboxes