Skip to content

简单实用工具

code with perspective

ultralytics包附带了多种实用工具,可以支持、增强和加速您的工作流程。还有更多可用的工具,但这里有一些对大多数开发者有用的工具。它们也是学习编程时的绝佳参考点。



观看: Ultralytics实用工具 | 自动注释、探索者API和数据集转换

数据

自动标注 / 注释

数据集注释是一个非常耗费资源和时间的过程。如果您有一个在合理数据量上训练的YOLO目标检测模型,您可以使用它和SAM来自动注释额外的数据(分割格式)。

from ultralytics.data.annotator import auto_annotate

auto_annotate(  # (1)!
    data="path/to/new/data",
    det_model="yolo11n.pt",
    sam_model="mobile_sam.pt",
    device="cuda",
    output_dir="path/to/save_labels",
)
  1. 此函数不返回任何内容

  2. 查看annotator.auto_annotate的参考部分以了解更多关于该函数如何操作的信息。

  3. 结合使用segments2boxes函数来生成目标检测边界框

将分割掩码转换为YOLO格式

分割掩码到YOLO格式

用于将分割掩码图像数据集转换为YOLO分割格式。此函数将包含二进制格式掩码图像的目录转换为YOLO分割格式。

转换后的掩码将保存在指定的输出目录中。

from ultralytics.data.converter import convert_segment_masks_to_yolo_seg

# 这里的classes是数据集中总类别数,对于COCO数据集我们有80个类别
convert_segment_masks_to_yolo_seg(masks_dir="path/to/masks_dir", output_dir="path/to/output_dir", classes=80)

将COCO转换为YOLO格式

用于将COCO JSON注释转换为适当的YOLO格式。对于目标检测(边界框)数据集,use_segmentsuse_keypoints都应为False

from ultralytics.data.converter import convert_coco

convert_coco(  # (1)!
    "../datasets/coco/annotations/",
    use_segments=False,
    use_keypoints=False,
    cls91to80=True,
)
  1. 此函数不返回任何内容

有关convert_coco函数的更多信息,访问参考页面

获取边界框尺寸

from ultralytics.utils.plotting import Annotator
from ultralytics import YOLO
import cv2

model = YOLO('yolo11n.pt')  # 加载预训练或微调模型

# 处理图像
source = cv2.imread('path/to/image.jpg')
results = model(source)

# 提取结果
annotator = Annotator(source, example=model.names)

for box in results[0].boxes.xyxy.cpu():
    width, height, area = annotator.get_bbox_dimension(box)
    print("边界框宽度 {}, 高度 {}, 面积 {}".format(
        width.item(), height.item(), area.item()))

将边界框转换为分割

使用现有的x y w h边界框数据,使用yolo_bbox2segment函数转换为分割。图像和注释文件需要按如下方式组织:

data
|__ images
    ├─ 001.jpg
    ├─ 002.jpg
    ├─ ..
    └─ NNN.jpg
|__ labels
    ├─ 001.txt
    ├─ 002.txt
    ├─ ..
    └─ NNN.txt
from ultralytics.data.converter import yolo_bbox2segment

yolo_bbox2segment(  # (1)!
    im_dir="path/to/images",
    save_dir=None,  # 保存到图像目录中的"labels-segment"
    sam_model="sam_b.pt",
)
  1. 此函数不返回任何内容 访问 yolo_bbox2segment 参考页面 以获取有关该函数的更多信息。

将分割转换为边界框

如果你有一个使用分割数据集格式的数据集,你可以使用此函数轻松地将这些分割转换为直立(或水平)边界框(x y w h 格式)。

import numpy as np

from ultralytics.utils.ops import segments2boxes

segments = np.array(
    [
        [805, 392, 797, 400, ..., 808, 714, 808, 392],
        [115, 398, 113, 400, ..., 150, 400, 149, 298],
        [267, 412, 265, 413, ..., 300, 413, 299, 412],
    ]
)

segments2boxes([s.reshape(-1, 2) for s in segments])
# >>> array([[ 741.66, 631.12, 133.31, 479.25],
#           [ 146.81, 649.69, 185.62, 502.88],
#           [ 281.81, 636.19, 118.12, 448.88]],
#           dtype=float32) # xywh 边界框

要了解此函数的工作原理,请访问参考页面

实用工具

图像压缩

压缩单个图像文件以减小其大小,同时保持其宽高比和质量。如果输入图像小于最大尺寸,则不会调整其大小。

from pathlib import Path

from ultralytics.data.utils import compress_one_image

for f in Path("path/to/dataset").rglob("*.jpg"):
    compress_one_image(f)  # (1)!
  1. 此函数不返回任何内容

自动分割数据集

自动将数据集分割为 train/val/test 分割,并将结果分割保存到 autosplit_*.txt 文件中。此函数将使用随机采样,这在使用 fraction 参数进行训练时不包括在内。

from ultralytics.data.utils import autosplit

autosplit(  # (1)!
    path="path/to/images",
    weights=(0.9, 0.1, 0.0),  # (训练, 验证, 测试) 分数分割
    annotated_only=False,  # 当为 True 时仅分割带有标注文件的图像
)
  1. 此函数不返回任何内容

有关此函数的更多详细信息,请参阅参考页面

分割多边形到二值掩码

将单个多边形(作为列表)转换为指定图像大小的二值掩码。多边形的形式为 [N, 2],其中 N 是定义多边形轮廓的 (x, y) 点的数量。

警告

N 必须始终 为偶数。

import numpy as np

from ultralytics.data.utils import polygon2mask

imgsz = (1080, 810)
polygon = np.array([805, 392, 797, 400, ..., 808, 714, 808, 392])  # (238, 2)

mask = polygon2mask(
    imgsz,  # 元组
    [polygon],  # 输入为列表
    color=255,  # 8 位二值
    downsample_ratio=1,
)

边界框

边界框(水平)实例

要管理边界框数据,Bboxes 类将帮助在框坐标格式之间转换、缩放框尺寸、计算面积、包含偏移量等!

import numpy as np

from ultralytics.utils.instance import Bboxes

boxes = Bboxes(
    bboxes=np.array(
        [
            [22.878, 231.27, 804.98, 756.83],
            [48.552, 398.56, 245.35, 902.71],
            [669.47, 392.19, 809.72, 877.04],
            [221.52, 405.8, 344.98, 857.54],
            [0, 550.53, 63.01, 873.44],
            [0.0584, 254.46, 32.561, 324.87],
        ]
    ),
    format="xyxy",
)

boxes.areas()
# >>> array([ 4.1104e+05,       99216,       68000,       55772,       20347,      2288.5])

boxes.convert("xywh")
print(boxes.bboxes)
# >>> array(
#     [[ 413.93, 494.05,  782.1, 525.56],
#      [ 146.95, 650.63,  196.8, 504.15],
#      [  739.6, 634.62, 140.25, 484.85],
#      [ 283.25, 631.67, 123.46, 451.74],
#      [ 31.505, 711.99,  63.01, 322.91],
#      [  16.31, 289.67, 32.503,  70.41]]
# )

有关更多可用属性和方法,请参阅 Bboxes 参考部分

提示

以下许多函数(以及更多)可以通过 Bboxes 访问,但如果你更喜欢直接使用这些函数,请参阅下一小节,了解如何独立导入这些函数。

缩放边界框

当放大或缩小图像时,可以使用 ultralytics.utils.ops.scale_boxes 适当地缩放相应的边界框坐标以匹配。

import cv2 as cv
import numpy as np

from ultralytics.utils.ops import scale_boxes

image = cv.imread("ultralytics/assets/bus.jpg")
h, w, c = image.shape
resized = cv.resize(image, None, (), fx=1.2, fy=1.2)
new_h, new_w, _ = resized.shape

xyxy_boxes = np.array(
    [
        [22.878, 231.27, 804.98, 756.83],
        [48.552, 398.56, 245.35, 902.71],
        [669.47, 392.19, 809.72, 877.04],
        [221.52, 405.8, 344.98, 857.54],
        [0, 550.53, 63.01, 873.44],
        [0.0584, 254.46, 32.561, 324.87],
    ]
)

new_boxes = scale_boxes(
    img1_shape=(h, w),  # 原始图像尺寸
    boxes=xyxy_boxes,  # 原始图像中的边界框
    img0_shape=(new_h, new_w),  # 调整大小后的图像尺寸(缩放到)
    ratio_pad=None,
    padding=False,
    xywh=False,
)

print(new_boxes)  # (1)!
# >>> array(
#     [[  27.454,  277.52,  965.98,   908.2],
#     [   58.262,  478.27,  294.42,  1083.3],
#     [   803.36,  470.63,  971.66,  1052.4],
#     [   265.82,  486.96,  413.98,    1029],
#     [        0,  660.64,  75.612,  1048.1],
#     [   0.0701,  305.35,  39.073,  389.84]]
# )
1. 缩放至新图像尺寸的边界框

边界框格式转换

XYXY → XYWH

将边界框坐标从 (x1, y1, x2, y2) 格式转换为 (x, y, width, height) 格式,其中 (x1, y1) 是左上角,(x2, y2) 是右下角。

import numpy as np

from ultralytics.utils.ops import xyxy2xywh

xyxy_boxes = np.array(
    [
        [22.878, 231.27, 804.98, 756.83],
        [48.552, 398.56, 245.35, 902.71],
        [669.47, 392.19, 809.72, 877.04],
        [221.52, 405.8, 344.98, 857.54],
        [0, 550.53, 63.01, 873.44],
        [0.0584, 254.46, 32.561, 324.87],
    ]
)
xywh = xyxy2xywh(xyxy_boxes)

print(xywh)
# >>> array(
#     [[ 413.93,  494.05,   782.1, 525.56],
#     [  146.95,  650.63,   196.8, 504.15],
#     [   739.6,  634.62,  140.25, 484.85],
#     [  283.25,  631.67,  123.46, 451.74],
#     [  31.505,  711.99,   63.01, 322.91],
#     [   16.31,  289.67,  32.503,  70.41]]
# )

所有边界框转换

from ultralytics.utils.ops import (
    ltwh2xywh,
    ltwh2xyxy,
    xywh2ltwh,  # xywh → 左上角, w, h
    xywh2xyxy,
    xywhn2xyxy,  # 归一化 → 像素
    xyxy2ltwh,  # xyxy → 左上角, w, h
    xyxy2xywhn,  # 像素 → 归一化
)

for func in (ltwh2xywh, ltwh2xyxy, xywh2ltwh, xywh2xyxy, xywhn2xyxy, xyxy2ltwh, xyxy2xywhn):
    print(help(func))  # 打印函数文档字符串

查看每个函数的文档字符串或访问 ultralytics.utils.ops 参考页面 以阅读有关每个函数的更多信息。

绘图

绘制注释

Ultralytics 包含一个 Annotator 类,可用于注释任何类型的数据。它在使用 目标检测边界框姿态关键点定向边界框 时最为简单。

水平边界框

import cv2 as cv
import numpy as np

from ultralytics.utils.plotting import Annotator, colors

names = {  # (1)!
    0: "person",
    5: "bus",
    11: "stop sign",
}

image = cv.imread("ultralytics/assets/bus.jpg")
ann = Annotator(
    image,
    line_width=None,  # 默认自动尺寸
    font_size=None,  # 默认自动尺寸
    font="Arial.ttf",  # 必须与 ImageFont 兼容
    pil=False,  # 使用 PIL,否则使用 OpenCV
)

xyxy_boxes = np.array(
    [
        [5, 22.878, 231.27, 804.98, 756.83],  # class-idx x1 y1 x2 y2
        [0, 48.552, 398.56, 245.35, 902.71],
        [0, 669.47, 392.19, 809.72, 877.04],
        [0, 221.52, 405.8, 344.98, 857.54],
        [0, 0, 550.53, 63.01, 873.44],
        [11, 0.0584, 254.46, 32.561, 324.87],
    ]
)

for nb, box in enumerate(xyxy_boxes):
    c_idx, *box = box
    label = f"{str(nb).zfill(2)}:{names.get(int(c_idx))}"
    ann.box_label(box, label, color=colors(c_idx, bgr=True))

image_with_bboxes = ann.result()
  1. 名称可以从 model.names 中获取,当 处理检测结果

定向边界框 (OBB)

import cv2 as cv
import numpy as np

from ultralytics.utils.plotting import Annotator, colors

obb_names = {10: "small vehicle"}
obb_image = cv.imread("datasets/dota8/images/train/P1142__1024__0___824.jpg")
obb_boxes = np.array(
    [
        [0, 635, 560, 919, 719, 1087, 420, 803, 261],  # class-idx x1 y1 x2 y2 x3 y2 x4 y4
        [0, 331, 19, 493, 260, 776, 70, 613, -171],
        [9, 869, 161, 886, 147, 851, 101, 833, 115],
    ]
)
ann = Annotator(
    obb_image,
    line_width=None,  # 默认自动尺寸
    font_size=None,  # 默认自动尺寸
    font="Arial.ttf",  # 必须与 ImageFont 兼容
    pil=False,  # 使用 PIL,否则使用 OpenCV
)
for obb in obb_boxes:
    c_idx, *obb = obb
    obb = np.array(obb).reshape(-1, 4, 2).squeeze()
    label = f"{obb_names.get(int(c_idx))}"
    ann.box_label(
        obb,
        label,
        color=colors(c_idx, True),
        rotated=True,
    )

image_with_obb = ann.result()

边界框圆形注释 圆形标签

import cv2

from ultralytics import YOLO
from ultralytics.utils.plotting import Annotator

model = YOLO("yolo11s.pt")
names = model.names
cap = cv2.VideoCapture("path/to/video/file.mp4")

w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
writer = cv2.VideoWriter("Ultralytics circle annotation.avi", cv2.VideoWriter_fourcc(*"MJPG"), fps, (w, h))

while True:
    ret, im0 = cap.read()
    if not ret:
        break

    annotator = Annotator(im0)
    results = model.predict(im0)
    boxes = results[0].boxes.xyxy.cpu()
    clss = results[0].boxes.cls.cpu().tolist()

    for box, cls in zip(boxes, clss):
        annotator.circle_label(box, label=names[int(cls)])

    writer.write(im0)
    cv2.imshow("Ultralytics circle annotation", im0)

    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

writer.release()
cap.release()
cv2.destroyAllWindows()

边界框文本标注 文本标签

import cv2

from ultralytics import YOLO
from ultralytics.utils.plotting import Annotator

model = YOLO("yolo11s.pt")
names = model.names
cap = cv2.VideoCapture("path/to/video/file.mp4")

w, h, fps = (int(cap.get(x)) for x in (cv2.CAP_PROP_FRAME_WIDTH, cv2.CAP_PROP_FRAME_HEIGHT, cv2.CAP_PROP_FPS))
writer = cv2.VideoWriter("Ultralytics text annotation.avi", cv2.VideoWriter_fourcc(*"MJPG"), fps, (w, h))

while True:
    ret, im0 = cap.read()
    if not ret:
        break

    annotator = Annotator(im0)
    results = model.predict(im0)
    boxes = results[0].boxes.xyxy.cpu()
    clss = results[0].boxes.cls.cpu().tolist()

    for box, cls in zip(boxes, clss):
        annotator.text_label(box, label=names[int(cls)])

    writer.write(im0)
    cv2.imshow("Ultralytics text annotation", im0)

    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

writer.release()
cap.release()
cv2.destroyAllWindows()

更多信息请参见 Annotator 参考页面

杂项

代码性能分析

使用 with 语句或作为装饰器检查代码运行/处理的时间。

from ultralytics.utils.ops import Profile

with Profile(device="cuda:0") as dt:
    pass  # 要测量的操作

print(dt)
# >>> "Elapsed time is 9.5367431640625e-07 s"

Ultralytics 支持的格式

想要或需要以编程方式使用 Ultralytics 支持的 图像或视频格式?如果需要,请使用这些常量。

from ultralytics.data.utils import IMG_FORMATS, VID_FORMATS

print(IMG_FORMATS)
# {'tiff', 'pfm', 'bmp', 'mpo', 'dng', 'jpeg', 'png', 'webp', 'tif', 'jpg'}

print(VID_FORMATS)
# {'avi', 'mpg', 'wmv', 'mpeg', 'm4v', 'mov', 'mp4', 'asf', 'mkv', 'ts', 'gif', 'webm'}

使可整除

计算最接近 x 的整数,使其在除以 y 时可整除。

from ultralytics.utils.ops import make_divisible

make_divisible(7, 3)
# >>> 9
make_divisible(7, 2)
# >>> 8

常见问题

Ultralytics 包中包含哪些工具可以增强 机器学习 工作流程?

Ultralytics 包包含多种旨在简化并优化机器学习工作流程的工具。关键工具包括用于标注数据集的 自动标注,使用 convert_coco 将 COCO 格式转换为 YOLO 格式,压缩图像,以及数据集自动分割。这些工具旨在减少手动工作量,确保一致性,并提高数据处理效率。

如何使用 Ultralytics 自动标注我的数据集?

如果你有一个预训练的 Ultralytics YOLO 目标检测模型,你可以将其与 SAM 模型一起使用,以自动标注你的数据集为分割格式。示例如下:

from ultralytics.data.annotator import auto_annotate

auto_annotate(
    data="path/to/new/data",
    det_model="yolo11n.pt",
    sam_model="mobile_sam.pt",
    device="cuda",
    output_dir="path/to/save_labels",
)

更多详情请查看 auto_annotate 参考部分

如何在 Ultralytics 中将 COCO 数据集标注转换为 YOLO 格式?

要将 COCO JSON 标注转换为 YOLO 格式用于目标检测,你可以使用 convert_coco 工具。示例代码如下:

from ultralytics.data.converter import convert_coco

convert_coco(
    "../datasets/coco/annotations/",
    use_segments=False,
    use_keypoints=False,
    cls91to80=True,
)

更多信息请访问 convert_coco 参考页面

Ultralytics 包中 YOLO 数据探索器的用途是什么?

YOLO 探索器8.1.0 更新中引入的一个强大工具,用于增强数据集理解。它允许你使用文本查询在数据集中查找对象实例,从而更容易分析和管理数据。该工具提供了对数据集组成和分布的宝贵见解,有助于改进模型训练和性能。

如何在 Ultralytics 中将边界框转换为分割?

要将现有的边界框数据(以 x y w h 格式)转换为分割,你可以使用 yolo_bbox2segment 函数。确保你的文件按图像和标签分别组织在不同的目录中。

from ultralytics.data.converter import yolo_bbox2segment

yolo_bbox2segment(
    im_dir="path/to/images",
    save_dir=None,  # 保存到图像目录中的"labels-segment"文件夹
    sam_model="sam_b.pt",
)
更多信息,请访问 yolo_bbox2segment 参考页面


📅 Created 7 months ago ✏️ Updated 1 day ago

Comments