目标检测之YOLOV11自定义数据预处理——从原始标注到YOLO-OBB格式转换与验证

该文章已生成可运行项目,

前言

从前面的文章《目标检测之YOLOV11的环境搭建》,可知,现在的yolo版本发布,与其说是一个好的算法,不如说是一个平台,不带集成了检测,分类,分割等系列的方法,同时还包括了这个算法的所有的过程,包括训练,验证,预测以及导出,这让我想起之前用yolo obb进行虾苗计数时候的种种,在配置源码的时候的过程是比较复杂的,obb这块当时是没有集成在ultralytics平台的,现在的版本种已经自动存在obb的方法的,因此我想再次用yolo obb对之前的虾苗检测重新做一次。
之前做过的例子请参考:
目标检测之YoloV5+旋转目标

一、背景与问题引入

在使用YOLOv11进行目标检测(尤其是旋转框检测,OBB)时,数据格式的适配是关键步骤。原始的标注格式是:x1 y1 x2 y2 x3 y3 x4 y4 class_name difficulty,而YOLO-OBB要求输入class_index x1 y1 x2 y2 x3 y3 x4 y4的特定格式,其中x1 y1 x2 y2 x3 y3 x4 y4是目标四个角点指定边界框,其坐标在 0 和 1 之间归一化,因此需要做一个简单的转换,当前这个的前提是我已经对原始数据进行了标注啦。

二、核心步骤:原始标注→YOLO-OBB格式转换

1. 原始标注分析

原始标注格式为:x1 y1 x2 y2 x3 y3 x4 y4 class_name difficulty(8个真实坐标+类别名+难度),在我的标签txt文件中是这样的:

947.1667987930293 472.63887625737107 519.8770434482032 545.9859254267041 503.1668012069706 448.6389237426289 930.4565565517969 375.2918745732959 shrimp 0

。YOLO-OBB要求格式为:class_index x1_norm y1_norm x2_norm y2_norm x3_norm y3_norm x4_norm y4_norm(类别索引+8个归一化坐标)。

2. 转换代码解析

核心逻辑如下:

# 关键步骤1:读取图片尺寸(用于归一化)
img = cv2.imread(image_path)
img_width, img_height = img.shape[1], img.shape[0]

# 关键步骤2:坐标归一化(x_real/img_width, y_real/img_height)
normalized_coords = []
for i in range(0, 8, 2):
    x_real = coords[i]
    y_real = coords[i+1]
    x_norm = x_real / img_width
    y_norm = y_real / img_height
    normalized_coords.extend([x_norm, y_norm])

# 关键步骤3:写入YOLO格式(固定class_index=0,因你的数据仅一类)
yolo_line = "0 " + " ".join(map(str, normalized_coords))

具体代码如下:

import os
import cv2
from pathlib import Path

def convert_label(original_label_dir: str, image_dir: str, output_dir: str) -> None:
    """
    将原始标注转换为YOLO-OBB格式
    
    Args:
        original_label_dir: 原始标注txt文件所在目录
        image_dir: 对应图片所在目录(与txt文件名前缀一致)
        output_dir: YOLO-OBB格式标注输出目录
    """
    # 创建输出目录(若不存在)
    os.makedirs(output_dir, exist_ok=True)

    # 遍历原始标注目录下的所有txt文件
    for txt_path in Path(original_label_dir).glob("*.txt"):
        # 获取图片路径(假设txt与图片同名,仅后缀不同)
        image_name = txt_path.stem + ".jpg"  # 假设图片是jpg格式,可根据实际情况修改
        image_path = os.path.join(image_dir, image_name)

        # 读取图片尺寸
        if not os.path.exists(image_path):
            print(f"警告:图片 {
     
     image_path} 不存在,跳过标注文件 {
     
     txt_path}")
            continue
        img = cv2.imread(image_path)
        if img is None
本文章已经生成可运行项目
评论 11
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值