YOLOv8数据增强是否包含标签增强?透视增强标签生成疑问
YOLOv8透视增强与标签同步方案
一、YOLOv8自带增强的核心结论
YOLOv8的内置数据增强(包括透视变换Perspective)会自动同步变换标签,但前提是你的标签格式要匹配对应的任务类型:
- 你的标签是4个点的四边形坐标,属于多边形标注,不能用YOLOv8默认的目标检测(Detection)任务,需要切换到实例分割(Segmentation)任务,因为只有分割任务支持多边形标签的同步增强。
二、适配YOLOv8增强的步骤
转换标签格式
把你现有的Class_type, x1 min, y1 min, x2 min, y2 min, x3 min, y3 min, x4 min, y4 min格式,改成YOLO分割任务要求的格式:- 每行对应一个目标,格式为:
class_id x1 y1 x2 y2 x3 y3 x4 y4 - 坐标需要归一化(除以图像的宽度和高度,把绝对坐标转成0-1之间的相对值)
比如原图像宽640、高480,x1=100,就计算为100/640=0.15625。
- 每行对应一个目标,格式为:
启用透视增强训练
训练时指定分割模型,开启增强并设置透视强度:from ultralytics import YOLO # 加载分割预训练模型 model = YOLO('yolov8s-seg.pt') # 训练时启用增强,perspective参数控制透视变换强度(0-1之间) model.train(data='data.yaml', augment=True, perspective=0.05)这种方式是实时增强,训练过程中动态生成增强数据和对应标签,不需要提前保存到本地。
三、提前保存增强数据与标签的方案
如果需要把增强后的图片和标签永久保存,而非训练时实时生成,可以用YOLOv8的数据集类手动处理:
from ultralytics.data import YOLODataset from ultralytics.data.augment import Compose, Perspective import cv2 import os # 定义增强管道 augment_pipeline = Compose([Perspective(scale=0.05)]) # 加载自定义数据集(需配置好data.yaml) dataset = YOLODataset(data='data.yaml', augment=augment_pipeline) # 创建保存目录 save_img_dir = 'augmented_images' save_label_dir = 'augmented_labels' os.makedirs(save_img_dir, exist_ok=True) os.makedirs(save_label_dir, exist_ok=True) # 遍历处理并保存 for idx, (img, targets) in enumerate(dataset): # 保存增强后的图片 img_save_path = os.path.join(save_img_dir, f'aug_{idx}.png') cv2.imwrite(img_save_path, img) # 保存变换后的标签 label_save_path = os.path.join(save_label_dir, f'aug_{idx}.txt') with open(label_save_path, 'w') as f: for cls, seg in zip(targets['cls'], targets['segments']): # seg是归一化的多边形坐标,直接写入即可 line = f"{int(cls)} {' '.join(map(str, seg))}\n" f.write(line)
四、手动实现透视增强的替代方案
如果不想依赖YOLOv8的模块,用OpenCV直接写代码也能实现:
import cv2 import numpy as np import os def apply_perspective_aug(img_path, label_path, save_img_path, save_label_path): img = cv2.imread(img_path) h, w = img.shape[:2] # 随机生成透视变换的四角偏移(可调整offset控制增强幅度) offset = 25 src_points = np.float32([[0,0], [w,0], [w,h], [0,h]]) dst_points = np.float32([ [np.random.randint(-offset, offset), np.random.randint(-offset, offset)], [w + np.random.randint(-offset, offset), np.random.randint(-offset, offset)], [w + np.random.randint(-offset, offset), h + np.random.randint(-offset, offset)], [np.random.randint(-offset, offset), h + np.random.randint(-offset, offset)] ]) # 计算透视变换矩阵并变换图像 M = cv2.getPerspectiveTransform(src_points, dst_points) aug_img = cv2.warpPerspective(img, M, (w, h)) # 读取并变换标签坐标 with open(label_path, 'r') as f: lines = f.readlines() aug_labels = [] for line in lines: parts = list(map(float, line.strip().split(','))) cls = parts[0] # 提取原始4个点 points = np.float32([[parts[1], parts[2]], [parts[3], parts[4]], [parts[5], parts[6]], [parts[7], parts[8]]]) # 透视变换点坐标 transformed_points = cv2.perspectiveTransform(points.reshape(-1,1,2), M).reshape(-1,2) # 拼接成原标签格式 aug_line = f"{int(cls)}, {', '.join(map(str, transformed_points.flatten()))}" aug_labels.append(aug_line) # 保存结果 cv2.imwrite(save_img_path, aug_img) with open(save_label_path, 'w') as f: f.write('\n'.join(aug_labels)) # 遍历数据集批量处理 src_img_dir = 'original_images' src_label_dir = 'original_labels' aug_img_dir = 'augmented_images' aug_label_dir = 'augmented_labels' os.makedirs(aug_img_dir, exist_ok=True) os.makedirs(aug_label_dir, exist_ok=True) for img_name in os.listdir(src_img_dir): if img_name.endswith('.png'): base_name = os.path.splitext(img_name)[0] apply_perspective_aug( os.path.join(src_img_dir, img_name), os.path.join(src_label_dir, f'{base_name}.txt'), os.path.join(aug_img_dir, f'{base_name}_aug.png'), os.path.join(aug_label_dir, f'{base_name}_aug.txt') )
内容的提问来源于stack exchange,提问作者masut
相关产品推荐
相关产品推荐

