《------往期经典推荐------》
二、机器学习实战专栏【链接】 ,已更新31期,欢迎关注,持续更新中~~
三、深度学习【Pytorch】专栏【链接】
四、【Stable Diffusion绘画系列】专栏【链接】
五、YOLOv8改进专栏【链接】,持续更新中~~
六、YOLO性能对比专栏【链接】,持续更新中~
《------正文------》
目录
引言
对象检测中的数据增强是一种通过对现有图像应用各种变换来人为增加训练数据集的大小和多样性的技术。这有助于提高我们的对象检测模型的鲁棒性和泛化能力,使其在看不见的数据上表现得更好。用于常规图像分类的图像增强与用于对象检测的图像增强之间的主要区别在于,还必须随图像一起增强边界框位置。
数据增强重要性
为什么图像增强对目标检测很重要:
- 有限的数据: 对象检测数据集的创建可能既昂贵又耗时。增强有助于从现有数据中创建更多的训练数据,减少过度拟合并提高模型性能,特别是在数据有限的情况下。
- 对变化的鲁棒性: 真实世界的图像表现出很多变化(不同的照明,角度,大小,位置)。增强使模型在训练过程中暴露于这些变化,使其对这些变化更加鲁棒。
- 泛化: 通过在更多样化的数据集上进行训练,模型可以学习更好地泛化到看不见的图像。它不太可能偏向于训练集的特定特征。
常见数据增强方式
用于对象检测的常见图像增强技术:
- 几何变换:
- 旋转: 将图像旋转一定角度。边界框也必须相应地旋转。
- 缩放(缩放): 放大或缩小图像。边界框必须按比例缩放。
- 平移(平移): 水平或垂直移动图像。边界框必须移动相同的量。
- 翻转: 水平或垂直翻转图像。边界框必须相应地翻转。在物体检测中,水平翻转比垂直翻转更常见。
- 裁剪: 随机裁剪图像的一部分。如果边界框部分位于裁剪区域之外,则可能需要对其进行调整或将其丢弃。
光度变换:
- 亮度调整: 改变图像的亮度。
- 对比度调整: 改变图像的对比度。
- 色调调整: 改变图像的色调。
- 饱和度调整: 改变图像的饱和度。
- 添加噪波: 向图像添加随机噪波
其他技术:
- MixUp: 通过将两个图像混合在一起来创建新图像。边界框也相应地混合。
- CutOut: 随机屏蔽图像的矩形区域。这可以帮助模型学习关注对象的不同部分。
- **随机擦除:**类 似于剪切,但掩蔽区域填充随机值。
注意事项
目标检测增强的关键考虑因素:
- 边界框调整: 最关键的方面是,每当你变换图像时,你也必须变换相应的边界框。如果我们旋转图像,你需要旋转边界框。如果我们缩放图像,您需要缩放边界框。如果我们裁剪图像,您可能需要调整或丢弃部分落在裁剪区域之外的边界框
- 保持对象完整性: 小心可能会显著扭曲对象的增强。例如,过度旋转或缩放可能会使对象无法识别。
- 数据增强库: Albumentations、Imgaug和TensorFlow的
tf.image
模块等库提供了在正确处理边界框的同时轻松应用这些增强的功能。
数据增强实现代码
python
import albumentations as A
import cv2
import os
import random
def augment_data(image_folder, annotation_folder, output_image_folder, output_annotation_folder, num_augmentations_per_image=3):
"""
Augments images and their corresponding annotations for object detection.
Args:
image_folder: 包含图像的文件夹路径。
annotation_folder: 包含标注文件的文件夹路径(.txt 文件,YOLO 格式)。
output_image_folder: 保存增强后图像的文件夹路径。
output_annotation_folder: 保存增强后标注文件的文件夹路径。
num_augmentations_per_image: 每张图像生成的增强的次数。
"""
if not os.path.exists(output_image_folder):
os.makedirs(output_image_folder)
if not os.path.exists(output_annotation_folder):
os.makedirs(output_annotation_folder)
# Define augmentations (customize as needed)
transform = A.Compose([
A.HorizontalFlip(p=0.5),
A.RandomRotate90(p=0.5),
A.ShiftScaleRotate(shift_limit=0.05, scale_limit=0.05, rotate_limit=15, p=0.5),
A.RandomBrightnessContrast(p=0.3),
A.RGBShift(r_shift_limit=20, g_shift_limit=20, b_shift_limit=20, p=0.2), # Color shifts
A.RandomCrop(width=400, height=400, always_apply=False, p=0.3), # Example crop. Adjust size.
A.CLAHE(p=0.2), # Contrast Limited Adaptive Histogram Equalization
A.Blur(blur_limit=3, p=0.2) # Add blur
], bbox_params=A.BboxParams(format='yolo', label_fields=['class_labels']))
for filename in os.listdir(image_folder):
if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
image_path = os.path.join(image_folder, filename)
image = cv2.imread(image_path)
if image is None:
print(f"Warning: Could not read image {filename}. Skipping.")
continue
annotation_filename = os.path.splitext(filename)[0] + ".txt"
annotation_path = os.path.join(annotation_folder, annotation_filename)
if not os.path.exists(annotation_path):
print(f"Warning: Annotation file {annotation_filename} not found for {filename}. Skipping.")
continue
try:
with open(annotation_path, 'r') as f:
bboxes = []
class_labels = [] # Store class labels for each bounding box
for line in f:
parts = line.strip().split()
class_id = int(parts[0])
x_center = float(parts[1])
y_center = float(parts[2])
width = float(parts[3])
height = float(parts[4])
bboxes.append([x_center, y_center, width, height, class_id]) # Include class label
class_labels.append(class_id) # Append class label
for i in range(num_augmentations_per_image):
augmented = transform(image=image, bboxes=bboxes, class_labels=class_labels)
augmented_image = augmented['image']
augmented_bboxes = augmented['bboxes']
augmented_class_labels = augmented['class_labels']
new_filename = f"{os.path.splitext(filename)[0]}_aug{i}.jpg" # Consistent jpg output
output_image_path = os.path.join(output_image_folder, new_filename)
cv2.imwrite(output_image_path, augmented_image)
new_annotation_filename = f"{os.path.splitext(filename)[0]}_aug{i}.txt"
output_annotation_path = os.path.join(output_annotation_folder, new_annotation_filename)
with open(output_annotation_path, 'w') as outfile:
for bbox, class_label in zip(augmented_bboxes, augmented_class_labels):
x_center, y_center, width, height, _ = bbox # Extract without class label
outfile.write(f"{class_label} {x_center} {y_center} {width} {height}\n")
except FileNotFoundError:
print(f"Warning: Annotation file {annotation_filename} not found. Skipping.")
except ValueError:
print(f"Warning: Invalid annotation format in {annotation_filename}. Skipping.")
except Exception as e:
print(f"An error occurred processing {filename}: {e}")
# Example usage:
image_folder = "path/to/your/image/folder"
annotation_folder = "path/to/your/annotation/folder"
output_image_folder = "path/to/output/augmented/images"
output_annotation_folder = "path/to/output/augmented/annotations"
augment_data(image_folder, annotation_folder, output_image_folder, output_annotation_folder)
print("Data augmentation complete.")

好了,这篇文章就介绍到这里,喜欢的小伙伴感谢给点个赞和关注,更多精彩内容持续更新~~
关于本篇文章大家有任何建议或意见,欢迎在评论区留言交流!