YOLOV5入门教程2-detect.py文件

一.下载好文件后点击detect.py文件

import argparse
import csv
import os
import platform
import sys
from pathlib import Path
import torch

1. import argparse

argparse 是Python标准库中的一个模块,用于处理命令行参数。它可以让你的Python程序接收命令行输入,解析这些参数,并在程序内部使用。例如,在YOLO模型的训练或推理脚本中,常常会使用argparse来处理输入的配置文件路径、模型参数等。

2. import csv

csv 模块用于读取和写入CSV文件(Comma Separated Values,逗号分隔值文件)。在YOLO的使用场景中,可能会用它来处理标注文件或存储检测结果。

3. import os

os 模块提供了与操作系统进行交互的功能,比如文件路径的操作、执行系统命令、环境变量的访问等。在YOLO的代码中,os通常用于文件路径管理、创建文件夹或文件的读写操作。

4. import platform

platform 模块提供了访问底层平台数据(例如操作系统版本、硬件架构等)的能力。这个模块在YOLO代码中可能用于获取系统信息,以便在不同的操作系统环境下做出不同的配置或决策。

5. import sys

sys 模块提供了与Python解释器相关的功能,比如访问命令行参数、控制解释器的行为等。在YOLO代码中,sys通常用来终止程序、添加模块路径或处理异常等。

6. from pathlib import Path

Pathlib 是Python3中的一个面向对象的文件和路径操作库。Path 类是其中的核心类,它为文件和目录路径的处理提供了更方便和直观的方法。相较于传统的os.pathPathlib的使用更符合现代Python代码的风格。在YOLO代码中,Path 可以用于文件路径的创建、检查文件是否存在、遍历目录等操作。

7. import torch

torch 是PyTorch的核心模块。PyTorch是一个开源的深度学习框架,广泛用于计算机视觉、自然语言处理等领域。YOLO模型的实现和训练可以使用PyTorch来进行,它提供了张量计算(类似于NumPy)、自动微分、模型定义和训练等功能。

FILE = Path(__file__).resolve()  # 获取当前脚本的绝对路径,并消除任何符号链接
ROOT = FILE.parents[0]  # 获取当前脚本所在目录,即项目的根目录
if str(ROOT) not in sys.path:
    sys.path.append(str(ROOT))  # 如果根目录不在sys.path中,将其添加到sys.path,以便模块导入
ROOT = Path(os.path.relpath(ROOT, Path.cwd()))  # 将根目录路径转换为相对于当前工作目录的相对路径

这段代码的目的是确保当前脚本的所在目录(即项目的根目录)被正确添加到Python的模块搜索路径(sys.path)中。这样可以确保在项目中导入其他模块时不会出现路径问题。最后一步将根目录路径转换为相对路径,可能是为了使路径表示更简洁或更便于跨平台使用。

这样的设置在大型项目中很常见,尤其是需要在不同的脚本间共享模块和文件时,确保路径正确、代码可以跨环境运行。

from models.common import DetectMultiBackend  # 导入用于处理多后端(如不同硬件加速器)的检测模型类
from utils.datasets import IMG_FORMATS, VID_FORMATS, LoadImages, LoadStreams  # 导入支持的图像、视频格式及加载数据流的工具
from utils.general import (LOGGER, check_file, check_img_size, check_imshow, check_requirements, colorstr,
                           increment_path, non_max_suppression, print_args, scale_coords, strip_optimizer, xyxy2xywh)
# 导入各种通用工具函数,包括日志、文件检查、图像大小检查、非极大值抑制、坐标转换等
from utils.plots import Annotator, colors, save_one_box  # 导入绘图工具,用于注释和保存检测框
from utils.torch_utils import select_device, time_sync  # 导入设备选择工具(如GPU/CPU)和时间同步工具

各模块作用总结

  1. models.common:

    • DetectMultiBackend: 用于处理不同后端的检测模型类,如支持在不同硬件加速器上运行(CPU、GPU、TPU等)。
  2. utils.datasets:

    • IMG_FORMATS: 支持的图像格式列表(如.jpg.png)。
    • VID_FORMATS: 支持的视频格式列表(如.mp4.avi)。
    • LoadImages: 用于加载图像文件的类。
    • LoadStreams: 用于加载视频流或摄像头数据流的类。
  3. utils.general:

    • 包含各种通用工具函数:
      • LOGGER: 日志工具,用于记录信息。
      • check_file: 检查文件是否存在。
      • check_img_size: 检查并调整图像大小,以确保与模型输入大小兼容。
      • check_imshow: 检查是否支持显示窗口(通常在无显示的环境中使用)。
      • check_requirements: 检查依赖项是否满足。
      • colorstr: 用于着色字符串输出的工具。
      • increment_path: 生成不重复的路径,用于保存文件。
      • non_max_suppression: 实现非极大值抑制算法,用于去除重叠的检测框。
      • print_args: 打印命令行参数。
      • scale_coords: 缩放坐标,以适应原始图像尺寸。
      • strip_optimizer: 移除PyTorch模型中的优化器信息(用于导出模型)。
      • xyxy2xywh: 坐标转换函数,将xyxy格式(左上角和右下角坐标)转换为xywh格式(中心点和宽高)。
  4. utils.plots:

    • Annotator: 用于在图像上绘制检测框和标签的工具类。
    • colors: 定义了一组用于绘图的颜色。
    • save_one_box: 用于保存单个检测框区域的图像。
  5. utils.torch_utils:

    • select_device: 用于选择计算设备(如GPU或CPU)。
    • time_sync: 用于时间测量和同步,通常用于计算执行时间。

总结

这段代码导入了YOLO项目中用于模型加载、数据处理、推理后处理、绘图和设备管理的各种自定义模块和函数。通过这些工具,开发者可以高效地进行图像和视频的检测任务,处理检测结果并进行可视化。

def main(opt):

    check_requirements(ROOT / "requirements.txt", exclude=("tensorboard", "thop"))
    run(**vars(opt))


if __name__ == "__main__":
    opt = parse_opt()
    main(opt)
  • def main(opt):
    定义了一个名为 main 的函数,它接收一个参数 opt,这个参数通常是解析后的命令行选项和配置。

  • check_requirements(ROOT / "requirements.txt", exclude=("tensorboard", "thop"))

    • check_requirements: 这个函数用于检查项目所需的依赖项是否已安装。
    • ROOT / "requirements.txt": 指定依赖项列表所在的文件路径(通常是requirements.txt)。
    • exclude=("tensorboard", "thop"): 指定检查依赖时要排除的库,这意味着在这个场景中,即使tensorboardthop没有安装,也不会影响程序的运行。
  • run(**vars(opt))

    • run: 通常是项目中实际执行检测任务的主要函数。
    • vars(opt): 将 opt 对象(通常是 argparse.Namespace 对象)转换为字典,然后使用 ** 运算符将字典解包为关键字参数传递给 run 函数。这允许 run 函数直接接收并处理命令行参数。
  • if __name__ == "__main__":
    这是Python脚本的标准结构,用于检查当前模块是否是被直接运行的(而不是被导入到其他模块中)。如果条件为真,表示脚本是作为主程序运行。

  • opt = parse_opt()
    这里调用了 parse_opt 函数,通常这个函数用于解析命令行参数,并返回一个包含这些参数的对象 opt

  • main(opt)
    将解析后的参数对象 opt 传递给 main 函数,从而开始执行主要的程序逻辑。

总结

这段代码是一个YOLO项目的主程序入口,它的流程大致如下:

  1. 解析命令行参数。
  2. 检查并确保运行该脚本所需的依赖项已安装(排除了tensorboardthop)。
  3. 调用主要的运行函数 run 来执行YOLO模型的推理任务,传入解析后的参数。
def parse_opt():
    parser = argparse.ArgumentParser()
    parser.add_argument("--weights", nargs="+", type=str, default=ROOT / "yolov5s.pt", help="model path or triton URL")
    parser.add_argument("--source", type=str, default=ROOT / "data/images", help="file/dir/URL/glob/screen/0(webcam)")
    parser.add_argument("--data", type=str, default=ROOT / "data/coco128.yaml", help="(optional) dataset.yaml path")
    parser.add_argument("--imgsz", "--img", "--img-size", nargs="+", type=int, default=[640], help="inference size h,w")
    parser.add_argument("--conf-thres", type=float, default=0.25, help="confidence threshold")
    parser.add_argument("--iou-thres", type=float, default=0.45, help="NMS IoU threshold")
    parser.add_argument("--max-det", type=int, default=1000, help="maximum detections per image")
    parser.add_argument("--device", default="", help="cuda device, i.e. 0 or 0,1,2,3 or cpu")
    parser.add_argument("--view-img", action="store_true", help="show results")
    parser.add_argument("--save-txt", action="store_true", help="save results to *.txt")
    parser.add_argument("--save-csv", action="store_true", help="save results in CSV format")
    parser.add_argument("--save-conf", action="store_true", help="save confidences in --save-txt labels")
    parser.add_argument("--save-crop", action="store_true", help="save cropped prediction boxes")
    parser.add_argument("--nosave", action="store_true", help="do not save images/videos")
    parser.add_argument("--classes", nargs="+", type=int, help="filter by class: --classes 0, or --classes 0 2 3")
    parser.add_argument("--agnostic-nms", action="store_true", help="class-agnostic NMS")
    parser.add_argument("--augment", action="store_true", help="augmented inference")
    parser.add_argument("--visualize", action="store_true", help="visualize features")
    parser.add_argument("--update", action="store_true", help="update all models")
    parser.add_argument("--project", default=ROOT / "runs/detect", help="save results to project/name")
    parser.add_argument("--name", default="exp", help="save results to project/name")
    parser.add_argument("--exist-ok", action="store_true", help="existing project/name ok, do not increment")
    parser.add_argument("--line-thickness", default=3, type=int, help="bounding box thickness (pixels)")
    parser.add_argument("--hide-labels", default=False, action="store_true", help="hide labels")
    parser.add_argument("--hide-conf", default=False, action="store_true", help="hide confidences")
    parser.add_argument("--half", action="store_true", help="use FP16 half-precision inference")
    parser.add_argument("--dnn", action="store_true", help="use OpenCV DNN for ONNX inference")
    parser.add_argument("--vid-stride", type=int, default=1, help="video frame-rate stride")
    opt = parser.parse_args()
    opt.imgsz *= 2 if len(opt.imgsz) == 1 else 1  # expand
    print_args(vars(opt))
    return opt

parse_opt 函数参数功能总结

  1. 模型与设备相关

    • --weights: 指定模型权重文件的路径或Triton URL,支持多个路径输入。默认使用 yolov5s.pt
    • --device: 指定运行推理时使用的计算设备,例如 GPU (0) 或 CPU。如果未指定,程序会自动选择适当的设备。
    • --half: 启用FP16半精度推理,加速推理过程。此选项仅在支持FP16的设备上有效。
    • --dnn: 使用OpenCV的DNN模块进行ONNX模型推理。
  2. 输入与输出数据相关

    • --source: 指定输入数据源,可以是文件、目录、URL、通配符、屏幕截图或摄像头(0 表示摄像头)。默认使用 data/images
    • --data: 指定数据集配置文件的路径,默认使用 coco128.yaml
    • --imgsz: 指定推理时输入图像的大小,可以是单一值(正方形)或宽高两个值。默认是 640。
    • --project: 结果保存的主目录,默认为 runs/detect
    • --name: 结果保存的子目录名称,默认为 exp
    • --exist-ok: 允许覆盖现有的项目/名称目录,而不自动增加序号。
  3. 推理控制相关

    • --conf-thres: 置信度阈值,低于该值的检测结果会被忽略。默认值为 0.25。
    • --iou-thres: 非极大值抑制(NMS)的IoU阈值,默认值为 0.45。
    • --max-det: 每张图像的最大检测数,默认值为 1000。
    • --classes: 通过类别ID过滤检测结果,可以指定一个或多个类别。
    • --agnostic-nms: 启用类别无关的非极大值抑制(NMS),即忽略类别区分进行NMS处理。
    • --augment: 启用增强推理,如多尺度测试,以提高模型的鲁棒性。
    • --visualize: 可视化中间特征图,用于调试和理解模型的工作原理。
    • --vid-stride: 视频帧率的步长,控制处理视频时的帧间隔。默认值为 1。
  4. 结果输出控制

    • --view-img: 显示检测结果图像。
    • --save-txt: 将检测结果保存为文本文件(.txt)。
    • --save-csv: 将检测结果保存为CSV格式文件。
    • --save-conf: 在保存的标签文件中包括置信度信息。
    • --save-crop: 保存裁剪后的预测框图像。
    • --nosave: 不保存检测结果图像或视频文件。
    • --line-thickness: 指定绘制边界框的线条厚度,默认是 3 像素。
    • --hide-labels: 隐藏检测框上的标签文字。
    • --hide-conf: 隐藏检测框上的置信度数值。
  5. 模型管理

    • --update: 更新所有模型权重至最新版本。

总结

通过这些命令行参数,用户可以灵活控制YOLO模型的推理过程,指定输入输出路径、调整推理细节、选择计算设备以及配置输出选项。这些参数为模型应用提供了丰富的自定义选项,适用于多种场景和需求。

def run(
    weights=ROOT / "yolov5s.pt",  # model path or triton URL
    source=ROOT / "data/images",  # file/dir/URL/glob/screen/0(webcam)
    data=ROOT / "data/coco128.yaml",  # dataset.yaml path
    imgsz=(640, 640),  # inference size (height, width)
    conf_thres=0.25,  # confidence threshold
    iou_thres=0.45,  # NMS IOU threshold
    max_det=1000,  # maximum detections per image
    device="",  # cuda device, i.e. 0 or 0,1,2,3 or cpu
    view_img=False,  # show results
    save_txt=False,  # save results to *.txt
    save_csv=False,  # save results in CSV format
    save_conf=False,  # save confidences in --save-txt labels
    save_crop=False,  # save cropped prediction boxes
    nosave=False,  # do not save images/videos
    classes=None,  # filter by class: --class 0, or --class 0 2 3
    agnostic_nms=False,  # class-agnostic NMS
    augment=False,  # augmented inference
    visualize=False,  # visualize features
    update=False,  # update all models
    project=ROOT / "runs/detect",  # save results to project/name
    name="exp",  # save results to project/name
    exist_ok=False,  # existing project/name ok, do not increment
    line_thickness=3,  # bounding box thickness (pixels)
    hide_labels=False,  # hide labels
    hide_conf=False,  # hide confidences
    half=False,  # use FP16 half-precision inference
    dnn=False,  # use OpenCV DNN for ONNX inference
    vid_stride=1,  # video frame-rate stride
):

run 函数参数功能总结

  1. 模型与设备相关

    • weights: 模型权重文件的路径或Triton URL,默认为 yolov5s.pt
    • device: 指定运行推理的设备,例如 GPU(如 0)或 CPU。默认为空字符串,表示自动选择设备。
    • half: 启用FP16半精度推理,通常用于加速推理过程。
    • dnn: 使用OpenCV的DNN模块进行ONNX模型推理。
  2. 输入与输出数据相关

    • source: 输入数据源,可以是文件、目录、URL、通配符、屏幕截图或摄像头(使用 0 表示摄像头)。默认路径为 data/images
    • data: 数据集配置文件的路径,默认为 coco128.yaml
    • imgsz: 推理时输入图像的大小,以 (height, width) 的形式指定。默认大小为 (640, 640)
    • project: 结果保存的主目录,默认为 runs/detect
    • name: 结果保存的子目录名称,默认为 exp
  3. 推理控制相关

    • conf_thres: 置信度阈值,低于该值的检测结果将被忽略。默认值为 0.25。
    • iou_thres: 非极大值抑制(NMS)的IoU阈值,默认值为 0.45。
    • max_det: 每张图像的最大检测数,默认值为 1000。
    • classes: 通过类别ID过滤检测结果,可以指定一个或多个类别。
    • agnostic_nms: 启用类别无关的NMS,即忽略类别进行NMS处理。
    • augment: 启用增强推理,如多尺度测试,以提高模型的鲁棒性。
    • visualize: 可视化中间特征图,用于调试和理解模型的工作原理。
    • vid_stride: 视频帧率的步长,控制处理视频时的帧间隔。默认值为 1。
  4. 结果输出控制

    • view_img: 显示检测结果图像。
    • save_txt: 将检测结果保存为文本文件(.txt)。
    • save_csv: 将检测结果保存为CSV格式文件。
    • save_conf: 在保存的标签文件中包括置信度信息。
    • save_crop: 保存裁剪后的预测框图像。
    • nosave: 不保存检测结果图像或视频文件。
    • line_thickness: 指定绘制边界框的线条厚度,默认是3个像素。
    • hide_labels: 隐藏检测框上的标签文字。
    • hide_conf: 隐藏检测框上的置信度数值。
  5. 模型管理

    • update: 更新所有模型权重至最新版本。
    • exist_ok: 允许覆盖现有的项目/名称目录,而不会自动增加序号。

总结

run 函数通过这些参数来灵活地配置YOLO模型的运行环境,涵盖了从模型加载、设备选择、输入输出控制到结果保存等多方面的需求。它使得YOLOv5在推理过程中能够适应各种不同的应用场景,同时确保结果的准确性和可用性。

    source = str(source)
    save_img = not nosave and not source.endswith(".txt")  # save inference images
    is_file = Path(source).suffix[1:] in (IMG_FORMATS + VID_FORMATS)
    is_url = source.lower().startswith(("rtsp://", "rtmp://", "http://", "https://"))
    webcam = source.isnumeric() or source.endswith(".streams") or (is_url and not is_file)
    screenshot = source.lower().startswith("screen")
    if is_url and is_file:
        source = check_file(source)  # download

这段代码的主要功能是对输入源 (source) 进行检查和分类,以便根据其类型正确处理和配置YOLO模型的推理过程。具体来说,它:

  1. 转换和识别输入源类型

    • 将输入源转换为字符串格式。
    • 判断输入源是否是文件、URL、摄像头、截图等类型。
  2. 设定保存策略

    • 根据输入源类型和用户选项(如 nosave)决定是否保存推理结果图像。
  3. 处理URL输入

    • 如果输入是URL且指向文件(如在线图像或视频),则下载文件以供本地处理。
    # Directories
    save_dir = increment_path(Path(project) / name, exist_ok=exist_ok)  # increment run
    (save_dir / "labels" if save_txt else save_dir).mkdir(parents=True, exist_ok=True)  # make dir

这段代码的主要功能是为保存推理结果创建和管理目录:

  1. 自动创建保存目录:通过 increment_path 函数,根据指定的 projectname 参数,创建一个保存推理结果的目录。如果目录已存在且不允许覆盖(exist_ok=False),则会自动在目录名后加上数字递增(如 exp, exp1, exp2 等),确保新结果不会覆盖旧的检测结果。

  2. 设置输出文件路径:根据用户选项(如 save_txt),决定是否在保存目录中创建额外的子目录。例如,如果选择保存检测结果的文本文件(save_txt=True),则会在主目录下创建一个名为 labels 的子目录。

  3. 保证目录存在:使用 mkdir 方法确保所需的所有目录都存在,即使父级目录不存在,也会递归创建所有必要的路径。这为保存推理结果(如图像、视频、标签文件等)提供了必要的存储位置。

    # Load model
    device = select_device(device)
    model = DetectMultiBackend(weights, device=device, dnn=dnn, data=data, fp16=half)
    stride, names, pt = model.stride, model.names, model.pt
    imgsz = check_img_size(imgsz, s=stride)  # check image size

这段代码的主要目的是加载YOLO模型并准备推理环境:

  1. 选择计算设备:使用 select_device 函数选择合适的设备(如GPU或CPU)来运行推理。
  2. 加载YOLO模型:通过 DetectMultiBackend 类加载YOLO模型权重,并根据输入参数配置模型(例如设备类型、数据集配置、是否使用FP16半精度、以及是否启用OpenCV的DNN模块)。
  3. 提取模型信息:获取模型的步长(stride)、类别名称(names)和格式类型(pt)。
  4. 检查输入图像大小:使用 check_img_size 函数验证并调整输入图像尺寸,确保其符合模型步长的要求。
    # Dataloader
    bs = 1  # batch_size
    if webcam:
        view_img = check_imshow(warn=True)
        dataset = LoadStreams(source, img_size=imgsz, stride=stride, auto=pt, vid_stride=vid_stride)
        bs = len(dataset)
    elif screenshot:
        dataset = LoadScreenshots(source, img_size=imgsz, stride=stride, auto=pt)
    else:
        dataset = LoadImages(source, img_size=imgsz, stride=stride, auto=pt, vid_stride=vid_stride)
    vid_path, vid_writer = [None] * bs, [None] * bs

这段代码的主要功能是为YOLO模型的推理过程准备数据加载器(Dataloader)。根据输入源的不同类型,代码会选择合适的方法来加载图像或视频流,具体步骤如下:

  1. 设置批处理大小:定义 bs = 1 表示每次处理的批量大小默认为1。

  2. 处理摄像头输入

    • 如果输入源是摄像头(webcam 为 True),调用 check_imshow() 函数检查是否可以显示图像,并设置 view_img 变量。
    • 使用 LoadStreams 类来加载实时视频流,传入图像大小、步长、自动模式和视频帧率参数。
  3. 处理截图输入

    • 如果输入源是截图(screenshot 为 True),使用 LoadScreenshots 类加载指定的截图,传入相应的参数。
  4. 处理文件输入

    • 如果输入源是图像或视频文件,使用 LoadImages 类加载这些文件,传入图像大小、步长、自动模式和视频帧率参数。
  5. 初始化视频路径及写入器

    • 为每个批次的图像或视频初始化路径(vid_path)和视频写入器(vid_writer),这些变量将用于保存检测结果。

模型最关键的推理步骤

    # Run inference
    model.warmup(imgsz=(1 if pt or model.triton else bs, 3, *imgsz))  # warmup
    seen, windows, dt = 0, [], (Profile(device=device), Profile(device=device), Profile(device=device))#seen 用于记录已处理图像的计数,windows 可以用于存储计算结果的窗口,dt 则是用于性能分析的时间记录器。

    for path, im, im0s, vid_cap, s in dataset:
        with dt[0]:
            im = torch.from_numpy(im).to(model.device)
            im = im.half() if model.fp16 else im.float()  # uint8 to fp16/32
            im /= 255  # 0 - 255 to 0.0 - 1.0
            if len(im.shape) == 3:
                im = im[None]  # expand for batch dim
            if model.xml and im.shape[0] > 1:
                ims = torch.chunk(im, im.shape[0], 0)

这段代码来自 YOLOv5 的 detect.py 文件,主要负责模型推理过程中的图像预处理和准备。以下是该代码的总结:

主要功能

  1. 模型预热

    • 通过 model.warmup 方法进行预热,确保模型在实际推理前优化性能。
  2. 初始化变量

    • 记录已处理图像数(seen),用于存储结果的窗口(windows),以及性能分析的时间记录器(dt)。
  3. 数据集处理

    • 遍历数据集中的每个图像或视频帧,以便进行推理。
  4. 图像转化和归一化

    • 使用 PyTorch 将输入图像从 NumPy 数组转换为张量,调整数据类型(半精度或单精度),并将像素值归一化到 [0, 1] 的范围。
  5. 批次处理

    • 如果输入的图像为 3 维,扩展为批次格式。如果模型要求 XML 格式并且输入包含多个图像,则拆分为单独的图像处理。
        # Inference
        with dt[1]: 使用性能分析工具 dt[1] 开始记录推理所耗费的时间。
            visualize = increment_path(save_dir / Path(path).stem, mkdir=True) if visualize else False #如果开启了可视化,使用 increment_path 方法创建一个用于保存结果的目录路径。Path(path).stem 获取文件名的基本部分,以避免文件名冲突。
            if model.xml and im.shape[0] > 1:
                pred = None
                for image in ims:
                    if pred is None:
                        pred = model(image, augment=augment, visualize=visualize).unsqueeze(0)
                    else:
                        pred = torch.cat((pred, model(image, augment=augment, visualize=visualize).unsqueeze(0)), dim=0)
                pred = [pred, None]
            else:
                pred = model(im, augment=augment, visualize=visualize)

推理过程总结

  1. 推理时间测量:使用性能分析工具开始记录推理过程的时间。

  2. 可视化设置

    • 如果启用可视化,创建结果保存路径,以确保结果不会覆盖。
  3. 多图像推理

    • 当处理多个图像时,循环遍历每幅图像,分别进行推理。
    • 将每幅图像的推理结果合并为一个张量,便于后续处理。
  4. 单图像推理

    • 如果只有一幅图像,直接调用模型进行推理

代码逻辑说明

  • 增强与可视化选项

    • 在调用推理时,有提供 augment 和 visualize 参数,这意味着模型可以根据需要进行数据增强(如翻转、缩放等),并能够在进行推理的同时可视化结果。这在训练阶段和推理阶段都是非常有用的功能,可以帮助提升模型的鲁棒性和分析效果。
  • 灵活性

    • 这段代码的设计展示了很高的灵活性,能够根据输入图像的数量和类型(单幅或多幅)采取不同的推理策略。这种灵活性在实际应用中非常重要,比如在视频分析、电商商品检测等场景中,输入图像的数量可能差异很大。
        with dt[2]:#使用性能分析工具 dt[2] 开始记录后处理步骤所需的时间。这有助于评估整个推理过程中的性能瓶颈,尤其是在处理大量检测结果时。
            pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det) #这一行代码调用了 non_max_suppression 函数,对模型预测的结果应用 NMS。NMS 是一种常用的目标检测后处理技术,旨在消除重复的检测框,从而保留最可能真实的检测框。

NMS 参数说明

  • pred:输入的预测结果。它通常是模型对输入图像的初步检测结果,包含图像中所有的边界框、置信度分数和类别信息。

  • conf_thres:置信度阈值。只有当检测框的置信度超过这个阈值时,框才会被认为是有效的检测。这样可以过滤掉低信度的检测。

  • iou_thres:交并比(Intersection over Union, IoU)阈值。在多个检测框重叠的情况下,IoU 用于判断哪些框是重复的。只有当 IoU 超过这个阈值时,才会认为是重复框。

  • classes:可选参数,指定要考虑的类别。如果只对特定类别进行检测,可以将不相关类别的检测框排除在外。

  • agnostic_nms:如果为 True,则 NMS 将在所有类别之间进行,而不是在类别内部进行抑制。这意味着即使检测框来自不同的类别,只要它们的置信度足够高,就会相互比较并进行抑制。

  • max_det:最大检测框数。这个参数定义了对每张图像最大保留多少个检测框,有助于限制输出的数量。

NMS 的作用

  • 提升准确率:NMS 通过删除重叠的预测框,可以防止模型给出多个检测框对于同一目标的情况,从而提高了检测的准确性。

  • 减少输出:经过 NMS 处理后,模型输出的检测框数量会显著减少,这对后续处理和视觉效果的展示至关重要。

预测第二重要的部分,预测过程

        # Process predictions
        for i, det in enumerate(pred):  # 这行代码通过 enumerate 函数遍历模型返回的预测结果 pred。pred 通常是一个列表,其中每个元素对应一张图片的检测结果,i 是当前图像的索引,det 是当前图像的检测框信息。
            seen += 1 #每处理一幅图像,seen 计数器就增加1,表示已经处理过的图像数量。这在整个推理流程中有助于监控图像处理的进度
            if webcam:  # batch_size >= 1
                p, im0, frame = path[i], im0s[i].copy(), dataset.count
                s += f"{i}: "
            else:
                p, im0, frame = path, im0s.copy(), getattr(dataset, "frame", 0)
  • if webcam: 这一条件判断检查输入是否来自网络摄像头(即实时视频流)。如果是,执行相应的处理:

    • p 保存当前图像的路径(对于视频流,路径通常暂时无用)。
    • im0 复制当前图像的原始数据,通常用于后续结果的显示或保存。
    • frame 变量跟踪当前帧的数量。
    • s += f"{i}: " 用于构建输出字符串(可能用于调试或信息记录)。
  • 如果输入不是来自网络摄像头,则处理整个图像的结果:

    • p 仍然保存路径(在批量处理时可能为相同),而 im0 复制原始图像数据。
    • frame 则使用 getattr 从数据集中获取当前帧的数量,默认为0。这保证了在没有帧信息时不会引起错误。

重要性

  • 灵活性:此段代码区分了不同输入来源(网络摄像头与预存图像或视频),并根据输入类型采取不同的处理方式。这样的设计增强了代码的灵活性和可扩展性。

  • 进度跟踪:通过更新 seen 计数和构建输出字符串,代码能够对处理进度进行跟踪,这在推理过程中有助于反馈执行状态。

p = Path(p)  # to Path
save_path = str(save_dir / p.name)  # im.jpg
txt_path = str(save_dir / "labels" / p.stem) + ("" if dataset.mode == "image" else f"_{frame}")  # im.txt
s += "%gx%g " % im.shape[2:]  # print string
gn = torch.tensor(im0.shape)[[1, 0, 1, 0]]  # normalization gain whwh
imc = im0.copy() if save_crop else im0  # for save_crop
annotator = Annotator(im0, line_width=line_thickness, example=str(names))

这段代码的主要功能是为检测结果准备保存路径和相关信息,并进行必要的处理和初始化,具体步骤如下:

  1. 路径处理

    • 将传入的路径 p 转换为 Path 对象,以便后续操作变得更加便捷。
    • 创建保存图像的完整路径 save_path,其格式为 save_dir 目录下的图像文件名(p.name)。
  2. 文本文件路径创建

    • 创建用于保存检测结果标签的文件路径 txt_path
      • 该路径位于 save_dir/labels 目录,文件名与图像文件相同,但扩展名改为 .txt
      • 如果数据集模式是图像,则不附加任何后缀;如果是视频帧,则在文件名后加上帧数(_frame)。
  3. 图像尺寸格式化

    • 使用字符串格式化将当前图像的宽度和高度(im.shape[2:])添加到字符串 s 中,以便于打印或记录。
  4. 归一化处理

    • 创建一个归一化增益张量 gn,它根据输入图像的形状计算宽高归一化比例。这里的 torch.tensor(im0.shape)[[1, 0, 1, 0]] 生成了一个包含宽高比例的张量。
  5. 图像复制

    • 如果启用了裁剪选项(save_crop),则复制原始图像 im0,用于保存裁剪后的图像。
  6. 注释器初始化

    • 创建 Annotator 对象,用于在图像上绘制检测结果的框和标签。对象的初始化使用原始图像 im0、指定的线条宽度 line_thickness,以及类别名称列表 names 作为参数。
            if len(det):
                # Rescale boxes from img_size to im0 size
                det[:, :4] = scale_boxes(im.shape[2:], det[:, :4], im0.shape).round()

                # Print results
                for c in det[:, 5].unique():
                    n = (det[:, 5] == c).sum()  # detections per class
                    s += f"{n} {names[int(c)]}{'s' * (n > 1)}, "  # add to string

                # Write results
                for *xyxy, conf, cls in reversed(det):
                    c = int(cls)  # integer class
                    label = names[c] if hide_conf else f"{names[c]}"
                    confidence = float(conf)
                    confidence_str = f"{confidence:.2f}"

                    if save_csv:
                        write_to_csv(p.name, label, confidence_str)

                    if save_txt:  # Write to file
                        xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist()  # normalized xywh
                        line = (cls, *xywh, conf) if save_conf else (cls, *xywh)  # label format
                        with open(f"{txt_path}.txt", "a") as f:
                            f.write(("%g " * len(line)).rstrip() % line + "\n")

                    if save_img or save_crop or view_img:  # Add bbox to image
                        c = int(cls)  # integer class
                        label = None if hide_labels else (names[c] if hide_conf else f"{names[c]} {conf:.2f}")
                        annotator.box_label(xyxy, label, color=colors(c, True))
                    if save_crop:
                        save_one_box(xyxy, imc, file=save_dir / "crops" / names[c] / f"{p.stem}.jpg", BGR=True)

            # Stream results
            im0 = annotator.result()
            if view_img:
                if platform.system() == "Linux" and p not in windows:
                    windows.append(p)
                    cv2.namedWindow(str(p), cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIO)  # allow window resize (Linux)
                    cv2.resizeWindow(str(p), im0.shape[1], im0.shape[0])
                cv2.imshow(str(p), im0)
                cv2.waitKey(1)  # 1 millisecond

这段代码的核心功能是处理YOLO模型输出的检测结果,并根据用户的设定执行后续操作。具体步骤如下:

  1. 检测结果处理

    • 首先检查检测结果 det 是否为空(len(det))。
    • 如果有检测结果,将检测框的坐标从图像大小缩放到原始图像大小,使用 scale_boxes 函数进行调整。
  2. 打印检测结果

    • 遍历检测结果中每个唯一的类别(det[:, 5].unique()),统计每个类别的检测数量,并将信息拼接到字符串 s 中,格式为 {数量} {类别名称}{'s'}(如有多个则加上"s")。
  3. 写入检测结果

    • 遍历每个检测框,提取坐标(xyxy)、置信度(conf)和类别(cls)。
    • 创建标签,决定是否包含置信度信息。
    • 将检测信息写入 CSV 或文本文件,根据选项 save_csv 和 save_txt 进行存储:
      • 如果保存为文本文件,首先转换坐标格式(xyxy2xywh)为规范的 xywh 格式,并进行归一化。
      • 根据是否保存置信度,生成相应格式的行并写入文件。
  4. 绘制检测框

    • 如果用户选择保存图像、裁剪图像或查看图像,调用 annotator.box_label 方法在图像上绘制检测框和标签。
  5. 裁剪保存

    • 如果用户选择裁剪(save_crop),则将裁剪后的预测框保存到对应的文件夹中。
  6. 结果流处理

    • 通过 annotator.result() 获取处理后的图像(im0)。
    • 如果用户选择查看图像(view_img),则使用 OpenCV 显示结果:
      • 在 Linux 系统中,检查是否需要创建一个新的可调节窗口。
      • 使用 cv2.imshow 函数展示带有检测结果的图像,并通过 cv2.waitKey(1) 确保窗口能快速刷新。

            # Save results (image with detections)
            if save_img:
                if dataset.mode == "image":
                    cv2.imwrite(save_path, im0)
                else:  # 'video' or 'stream'
                    if vid_path[i] != save_path:  # new video
                        vid_path[i] = save_path
                        if isinstance(vid_writer[i], cv2.VideoWriter):
                            vid_writer[i].release()  # release previous video writer
                        if vid_cap:  # video
                            fps = vid_cap.get(cv2.CAP_PROP_FPS)
                            w = int(vid_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
                            h = int(vid_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
                        else:  # stream
                            fps, w, h = 30, im0.shape[1], im0.shape[0]
                        save_path = str(Path(save_path).with_suffix(".mp4"))  # force *.mp4 suffix on results videos
                        vid_writer[i] = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))
                    vid_writer[i].write(im0)

        # Print time (inference-only)
        LOGGER.info(f"{s}{'' if len(det) else '(no detections), '}{dt[1].dt * 1E3:.1f}ms")

    # Print results
    t = tuple(x.t / seen * 1e3 for x in dt)  # speeds per image
    LOGGER.info(f"Speed: %.1fms pre-process, %.1fms inference, %.1fms NMS per image at shape {(1, 3, *imgsz)}" % t)
    if save_txt or save_img:
        s = f"\n{len(list(save_dir.glob('labels/*.txt')))} labels saved to {save_dir / 'labels'}" if save_txt else ""
        LOGGER.info(f"Results saved to {colorstr('bold', save_dir)}{s}")
    if update:
        strip_optimizer(weights[0])  # update model (to fix SourceChangeWarning)

这段代码的主要功能是保存YOLO推理结果,记录推理时间,并进行一些模型更新操作。具体步骤包括:

  1. 保存检测结果图像

    • 如果 save_img 为True,根据数据集的模式决定如何保存图像:
      • 对于图像模式:使用 OpenCV 的 cv2.imwrite 函数将检测结果图像保存到指定路径 save_path
      • 对于视频或流模式
        • 如果当前视频路径 vid_path[i] 不等于 save_path,说明需要开启一个新的视频写入器(VideoWriter)。
        • 释放之前的视频写入器(如果存在),并根据视频或流的属性获取帧率和宽高(fpswh)。
        • 强制将结果视频的路径后缀设置为 .mp4,然后初始化新的 VideoWriter 对象。
        • 使用 vid_writer[i].write(im0) 将当前的图像帧写入视频文件。
  2. 输出推理时间

    • 使用 LOGGER.info 输出结果字符串和推理时间。记录的信息包括每个检测的相关字符串 s,如果没有检测结果,输出相应的提示,记录推理持续时间(以毫秒为单位)。
  3. 打印总体结果统计

    • 计算每张图像的速度,包括预处理、推理和非极大值抑制(NMS)的时长,记录其在日志中。
  4. 结果保存提示

    • 如果启用了保存文本或图像,输出保存标签数量的提示信息,表明结果保存的位置。
  5. 模型更新

    • 如果设置了 update 选项,则调用 strip_optimizer(weights[0]) 函数更新模型,主要用于解决源更改警告问题。

detect.py 是YOLO模型用于目标检测的主要脚本。其主要功能可总结为以下几个部分:

  1. 命令行参数解析

    • 使用 argparse 解析命令行传入的参数,包括模型权重、输入数据源、数据集配置、图像大小、置信度阈值、输出控制选项等,以支持灵活的用户配置。
  2. 环境和依赖设置

    • 确保必要的目录存在,并根据命令行参数设置结果保存路径。
  3. 模型加载

    • 选择计算设备(例如GPU或CPU),并通过指定的权重加载YOLO模型。模型参数如步长、类别名称等会被提取用于后续推理。
  4. 数据加载

    • 定义数据加载器。根据输入源的类型(图像、视频、实时流等)选择合适的加载方式。支持对多个输入源的处理。
  5. 推理过程

    • 对输入数据进行推理,得到检测结果。包括:
      • 检测框调整,确保检测框坐标与原始图像大小相匹配。
      • 结果统计和标签生成,根据每个类别的检测数量和置信度生成标签信息。
  6. 结果保存

    • 将处理后的检测结果保存为图像、文本文件或CSV文件。支持选项控制输出结果的格式与内容(例如,是否保存置信度信息、是否裁剪目标等)。
  7. 结果可视化

    • 可以选择在窗口中显示检测结果,便于实时查看。
  8. 性能监控和结果日志

    • 记录推理速度和时间,提供推理过程的性能信息。
  9. 模型更新

    • 选项控制时,支持更新模型以确保使用最新的权重。

YOLOv5是一种用于目标检测的深度学习模型,可以用于数字识别等任务。下面是一个简单的教程,从安装YOLOv5开始逐步介绍。 1. 安装YOLOv5: - 首先,确保你已经安装了Python和PyTorch。 - 打开终端或命令提示符,使用以下命令克隆YOLOv5的代码库: ``` git clone https://github.com/ultralytics/yolov5.git ``` - 进入克隆的代码库目录: ``` cd yolov5 ``` - 安装所需的Python依赖项: ``` pip install -r requirements.txt ``` 2. 准备数据: - 准备包含数字的图像数据集。可以使用自己的数据集或者使用公开可用的数据集。 - 将图像数据集划分为训练集和测试集,并将其放置在适当的文件夹中。 3. 训练模型: - 在终端或命令提示符中运行以下命令来训练模型: ``` python train.py --img 640 --batch 16 --epochs 50 --data your_data.yaml --cfg models/yolov5s.yaml --weights yolov5s.pt ``` 其中,`--img`指定输入图像的大小,`--batch`指定批量大小,`--epochs`指定训练的轮数,`--data`指定数据集的配置文件,`--cfg`指定模型的配置文件,`--weights`指定预训练的权重文件。 4. 测试模型: - 在终端或命令提示符中运行以下命令来测试模型: ``` python test.py --img 640 --batch 16 --data your_data.yaml --weights runs/train/exp/weights/best.pt ``` 其中,`--img`指定输入图像的大小,`--batch`指定批量大小,`--data`指定数据集的配置文件,`--weights`指定训练得到的权重文件。 5. 进行数字识别: - 使用训练得到的模型进行数字识别。可以使用以下命令来对单张图像进行识别: ``` python detect.py --source your_image.jpg --weights runs/train/exp/weights/best.pt ``` 其中,`--source`指定输入图像的路径,`--weights`指定训练得到的权重文件。 希望这个简单的教程能帮助你入门YOLOv5实现数字识别。如果有任何问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值