YOLO V8-Detection 【批量图片推理】 推理详解及部署实现

前言

在实际处理过程中,我们使用YOLO V8进行推理时,通常会针对一张图片进行推理。如果需要对多张图片进行推理,则可以通过一个循环来实现对图片逐张进行推理。

单张图片推理时需要注意图片的尺寸必须是32的倍数,否则可能导致推理失败。在下面的示例中,我们展示了如何使用PyTorch和Ultralytics库进行单张图片的推理:

import torch
from ultralytics import YOLO

# Load a pretrained YOLOv8n model
model = YOLO('yolov8n.pt')

# Create a random torch tensor of BCHW shape (1, 3, 640, 640) with values in range [0, 1] and type float32
source = torch.rand(1, 3, 640, 640, dtype=torch.float32)

# Run inference on the source
results = model(source)  # list of Results objects

批量图片推理时也需要注意图片的尺寸必须是32的倍数。在下面的示例中,我们展示了如何使用PyTorch和Ultralytics库进行多张图片的批量推理:

import torch
from ultralytics import YOLO

# Load a pretrained YOLOv8n model
model = YOLO('yolov8n.pt')

# Create a random torch tensor of BCHW shape (1, 3, 640, 640) with values in range [0, 1] and type float32
source = torch.rand(4, 3, 640, 640, dtype=torch.float32)

# Run inference on the source
results = model(source)  # list of Results objects

需要注意的是,在批量推理时,虽然一次推理了多张图片,但实际处理方式仍然是通过循环进行的。在下面的文章中,我们将介绍如何使用更高效的方式进行批量推理,以获得更快的推理速度和更好的性能。

下面我们介绍如何将【单张图片推理】检测代码给修改成 【批量图片推理】代码,进行批量推理。

一、批量推理的前处理

原始代码

@staticmethod
def letterbox(im, new_shape=(640, 640), color=(114, 114, 114), scaleup=True, stride=32):
    # Resize and pad image while meeting stride-multiple constraints
    shape = im.shape[:2]  # current shape [height, width]
    if isinstance(new_shape, int):
        new_shape = (new_shape, new_shape)

    # Scale ratio (new / old)
    r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
    if not scaleup:  # only scale down, do not scale up (for better val mAP)
        r = min(r, 1.0)

    # Compute padding
    ratio = r, r  # width, height ratios
    new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
    dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]  # wh padding
    # minimum rectangle
    dw, dh = np.mod(dw, stride), np.mod(dh, stride)  # wh padding
    dw /= 2  # divide padding into 2 sides
    dh /= 2

    if shape[::-1] != new_unpad:  # resize
        im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)

    top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
    left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
    im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)  # add border
    return im, ratio, (dw, dh)

def precess_image(self, img_src, img_size, half, device):
    # Padded resize
    img = self.letterbox(img_src, img_size)[0]
    # Convert
    img = img.transpose((2, 0, 1))[::-1]  # HWC to CHW, BGR to RGB
    img = np.ascontiguousarray(img)
    img = torch.from_numpy(img).to(device)

    img = img.half() if half else img.float()  # uint8 to fp16/32
    img = img / 255  # 0 - 255 to 0.0 - 1.0
    if len(img.shape) == 3:
        img = img[None]  # expand for batch dim
    return img

处理方式

我们要先知道在原始处理方式中是如何操作的:

它包含以下步骤:

  • self.pre_transform:即 letterbox 添加灰条

  • img.transpose((2, 0, 1))[::-1]:HWC to CHW, BGR to RGB

  • torch.from_numpy:to Tensor

  • img.float() :uint8 to fp32

  • im /= 255:除以 255,归一化

  • img[None]:增加维度

在上述处理过程中我们最主要进行修改的就是 self.pre_transform 里面的操作,其余部分都是可以直接进行批量操作的。

letterbox 中最主要的操作就是下面两个函数,使用 opencv 进行实现的。我们要进行批量操作,那么 opencv 库是不能实现的,进行批量操作一般会用 广播机制 或者 tensor操作 来实现。

im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) 

由于最终输入到模型里面的是一个tensor,所以在这里我们使用 tensor的操作方式进行实现。

尺寸修改

原始方法:
im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)

现在方法:
resized_tensor = F.interpolate(image_tensor, size=new_unpad, mode='bilinear', align_corners=False)

两者的实现效果:

原始方法:(1176, 1956, 3) --》(385, 640, 3)

现在方法:(1176, 1956, 3) --》(385, 640, 3)

添加边框

原始方式:
im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) 

现在方法:
padded_tensor = F.pad(resized_tensor, (top, bottom, left, right), mode='constant', value=padding_value)

两者的实现效果:

原始方法:(385, 640, 3) --》(416, 640, 3)

现在方法:(385, 640, 3) --》(416, 640, 3)

修改后的代码

def tensor_process(self, image_cv):
    img_shape = image_cv.shape[1:]
    new_shape = 
### 准备工作 为了能够在Ubuntu系统上顺利运行YOLOv11模型进行推理,前期准备工作至关重要。这包括但不限于操作系统的准备、依赖库的安装以及环境变量的设置等[^1]。 ### 安装必要的软件包 在开始之前,确保已经更新了系统的软件源列表并升级现有的软件包至最新版本: ```bash sudo apt update && sudo apt upgrade -y ``` 接着,安装一些基础工具和库,这些对于后续的操作非常重要: ```bash sudo apt install git python3-pip libgl1-mesa-glx -y pip3 install --upgrade pip ``` 上述命令会帮助建立一个稳定的基础开发平台[^2]。 ### 创建Python虚拟环境 推荐创建一个新的Python虚拟环境来进行项目开发,可以有效避免不同项目的依赖冲突问题。这里采用`venv`模块作为例子展示如何创建虚拟环境: ```bash python3 -m venv yolov11-env source yolov11-env/bin/activate ``` 激活后的环境中,默认使用的Python解释器及相关库均独立于全局环境之外[^3]。 ### 下载并配置YOLOv11 获取YOLOv11的相关资源通常有两种方式:一是通过官方仓库克隆;二是直接下载预编译好的权重文件。假设选择前者,则可以通过Git轻松完成此过程: ```bash git clone https://github.com/example/yolov11.git # 假设这是YOLOv11的GitHub地址 cd yolov11 ``` 之后按照README.md中的指导进一步调整参数设定或是导入特定的数据集用于测试目的[^4]。 ### 安装所需的Python库 进入所克隆下来的目录后,依据项目需求文档说明来安装必需的第三方库。一般情况下,可以直接利用requirements.txt文件批量处理: ```bash pip install -r requirements.txt ``` 如果遇到权限错误提示,可能需要加上`--user`选项或者使用管理员权限重试一次。 ### 执行推理任务 当一切就绪之后,就可以编写简单的脚本来调用训练完毕的YOLOv11模型执行图像或视频流上的对象检测任务了。下面给出一段基本框架供参考: ```python from models.experimental import attempt_load import torch weights_path = 'path/to/best.pt' # 替换成实际路径 device = 'cuda' if torch.cuda.is_available() else 'cpu' model = attempt_load(weights=weights_path, map_location=device) def detect_objects(image): results = model(image) return results.pandas().xyxy[0] if __name__ == '__main__': img = ... # 加载待测图片的方式取决于具体应用场景 detections = detect_objects(img) print(detections[['xmin', 'ymin', 'xmax', 'ymax', 'confidence', 'class']]) ``` 这段代码展示了加载模型、定义预测函数以及打印输出边界框坐标的过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牧锦程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值