LabelMe的安装、实例分割数据集、数据格式转换(VOC转yolo)并划分 详细教程

目录
- labelMe是什么
- AnaConda的安装
- labelMe安装
- 数据标注
- 一步到位:数据格式转换并进行数据集划分(训练、测试、验证)
labelMe是什么
LabelMe 是个可以绘制多边形、矩形、圆形、直线、点的一套标记工具,可用于分类、目标检测、语义分割、实例分割任务上的数据标注。
AnaConda的安装
可参考这篇博客
Anaconda、Pytorch安装教程(全网最详细版,包含所有遇到的问题解决方案)-CSDN博客
labelMe安装
首先安装LabelMe,打开Anaconda Prompt 执行以下指令:
首先进入自己在AnaConda中创建的虚拟环境(注意:your_env是你自己的环境名)
conda activate your_env
pip install labelme

接着输入labelme 会出现以下UI 介面
labelme

点选Open Dir 选择要标记的图片文件夹

数据标注
- 使用创造多边形功能

- 将目标框选为一个闭合多边形,输入(选择)deer标签

- 将标记好的图片保存至目标文件夹(可以自定义一个文件夹),然后标记下一张图片(按D快捷键即可切换下一张)
一步到位:数据格式转换并进行数据集划分(训练、测试、验证)
将VOC格式数据集转换为YOLO格式数据集
执行以下脚本将VOC格式数据集转换为YOLO格式数据集。
但是需要注意的是:
- 转换之后的数据集只有Images和labels两个文件。还需要执行第二节中的脚本进行数据集划分,将总的数据集划分为训练、验证、测试数据集;
- 使用的话,需要修改 class_mapping 中类别名和对应标签,还有VOC数据集路径、YOLO数据集路径。
- 随机将数据集按照0.7-0.2-0.1的比例划分为训练、验证、测试数据集。
import os
import shutil
import random
import xml.etree.ElementTree as ET
from tqdm import tqdm# VOC格式数据集路径 (根据自己的VOC数据集路径进行调整)
voc_data_path = 'E:\\DataSet\\helmet-VOC'
voc_annotations_path = os.path.join(voc_data_path, 'Annotations')
voc_images_path = os.path.join(voc_data_path, 'JPEGImages')# YOLO格式数据集保存路径(根据自己的yolo数据集路径进行调整)
yolo_data_path = 'E:\\DataSet\\helmet-YOLO'
yolo_images_path = os.path.join(yolo_data_path, 'images')
yolo_labels_path = os.path.join(yolo_data_path, 'labels')# 创建YOLO格式数据集目录
os.makedirs(yolo_images_path, exist_ok=True)
os.makedirs(yolo_labels_path, exist_ok=True)# 类别映射 (可以根据自己的数据集进行调整)
class_mapping = {'head': 0,'helmet': 1,'person': 2,# 添加更多类别...
}def convert_voc_to_yolo(voc_annotation_file, yolo_label_file):tree = ET.parse(voc_annotation_file)root = tree.getroot()size = root.find('size')width = float(size.find('width').text)height = float(size.find('height').text)with open(yolo_label_file, 'w') as f:for obj in root.findall('object'):cls = obj.find('name').textif cls not in class_mapping:continuecls_id = class_mapping[cls]xmlbox = obj.find('bndbox')xmin = float(xmlbox.find('xmin').text)ymin = float(xmlbox.find('ymin').text)xmax = float(xmlbox.find('xmax').text)ymax = float(xmlbox.find('ymax').text)x_center = (xmin + xmax) / 2.0 / widthy_center = (ymin + ymax) / 2.0 / heightw = (xmax - xmin) / widthh = (ymax - ymin) / heightf.write(f"{cls_id} {x_center} {y_center} {w} {h}\n")# 遍历VOC数据集的Annotations目录,进行转换
print("开始VOC到YOLO格式转换...")
for voc_annotation in tqdm(os.listdir(voc_annotations_path)):if voc_annotation.endswith('.xml'):voc_annotation_file = os.path.join(voc_annotations_path, voc_annotation)image_id = os.path.splitext(voc_annotation)[0]voc_image_file = os.path.join(voc_images_path, f"{image_id}.png")yolo_label_file = os.path.join(yolo_labels_path, f"{image_id}.txt")yolo_image_file = os.path.join(yolo_images_path, f"{image_id}.png")convert_voc_to_yolo(voc_annotation_file, yolo_label_file)if os.path.exists(voc_image_file):shutil.copy(voc_image_file, yolo_image_file)print("VOC到YOLO格式转换完成!")# 划分数据集
train_images_path = os.path.join(yolo_data_path, 'train', 'images')
train_labels_path = os.path.join(yolo_data_path, 'train', 'labels')
val_images_path = os.path.join(yolo_data_path, 'val', 'images')
val_labels_path = os.path.join(yolo_data_path, 'val', 'labels')
test_images_path = os.path.join(yolo_data_path, 'test', 'images')
test_labels_path = os.path.join(yolo_data_path, 'test', 'labels')os.makedirs(train_images_path, exist_ok=True)
os.makedirs(train_labels_path, exist_ok=True)
os.makedirs(val_images_path, exist_ok=True)
os.makedirs(val_labels_path, exist_ok=True)
os.makedirs(test_images_path, exist_ok=True)
os.makedirs(test_labels_path, exist_ok=True)# 获取所有图片文件名(不包含扩展名)
image_files = [f[:-4] for f in os.listdir(yolo_images_path) if f.endswith('.png')]# 随机打乱文件顺序
random.shuffle(image_files)# 划分数据集比例
train_ratio = 0.7
val_ratio = 0.2
test_ratio = 0.1train_count = int(train_ratio * len(image_files))
val_count = int(val_ratio * len(image_files))
test_count = len(image_files) - train_count - val_counttrain_files = image_files[:train_count]
val_files = image_files[train_count:train_count + val_count]
test_files = image_files[train_count + val_count:]# 移动文件到相应的目录
def move_files(files, src_images_path, src_labels_path, dst_images_path, dst_labels_path):for file in tqdm(files):src_image_file = os.path.join(src_images_path, f"{file}.png")src_label_file = os.path.join(src_labels_path, f"{file}.txt")dst_image_file = os.path.join(dst_images_path, f"{file}.png")dst_label_file = os.path.join(dst_labels_path, f"{file}.txt")if os.path.exists(src_image_file) and os.path.exists(src_label_file):shutil.move(src_image_file, dst_image_file)shutil.move(src_label_file, dst_label_file)# 移动训练集文件
print("移动训练集文件...")
move_files(train_files, yolo_images_path, yolo_labels_path, train_images_path, train_labels_path)
# 移动验证集文件
print("移动验证集文件...")
move_files(val_files, yolo_images_path, yolo_labels_path, val_images_path, val_labels_path)
# 移动测试集文件
print("移动测试集文件...")
move_files(test_files, yolo_images_path, yolo_labels_path, test_images_path, test_labels_path)print("数据集划分完成!")# 删除原始的 images 和 labels 文件夹
shutil.rmtree(yolo_images_path)
shutil.rmtree(yolo_labels_path)print("原始 images 和 labels 文件夹删除完成!")
如果我的内容对你有帮助,请辛苦动动您的手指为我点赞,评论,收藏。感谢大家!!

