开源项目实战学习之YOLO11:ultralytics-cfg-datasets-VOC、xView.yaml文件(八)
👉 点击关注不迷路
👉 点击关注不迷路
👉 点击关注不迷路
文章大纲
- `VOC.yaml`
- `xView.yaml`
- VOC.yaml
- 用途: 主要用于配置
与 Pascal VOC 数据集相关的信息
,以便在 YOLO 框架等目标检测任务中使用该数据集进行模型训练、评估和推理。 - 内容: 通常包含数据集的路径信息,例如训练集、验证集和测试集图像及标注文件的存放路径;还包括类别名称的映射列表,明确数据集中不同目标的类别,如人、车、猫、狗等常见物体类别。
- 应用场景: 是一个
较为经典的目标检测数据集,适用于作为基准测试或小规模项目的训练集
,比如在一些学术研究中,用于初步验证目标检测算法的有效性;也可用于一些对精度要求不是极高,但对检测速度有一定要求的小型应用场景,如简单的室内物体检测等
。
- 用途: 主要用于配置
- xView.yaml
- 用途: 用于配置 xView 数据集相关信息,为在 YOLO 框架下处理该数据集提供配置支持。
- 内容: 包含数据集的路径,指出训练集、验证集等数据的存储位置;定义了数据集中的各类别,
xView 数据集包含 60 个类别的 100 多万个对象实例
;可能还包含一些关于数据预处理、标注转换等相关的配置信息。 - 应用场景:
xView 数据集是可公开获取的最大高空图像数据集之一,图像由卫星采集,分辨率较高
。其应用场景主要集中在遥感领域,如军事和国防侦察,可用于监测军事设施、部队部署等
;环境监测方面,能监测森林覆盖变化、土地利用变化等
;以及基础设施测绘和管理,对城市中的建筑物、道路等
基础设施进行监测和管理。
VOC.yaml
-
# parent # ├── ultralytics # └── datasets # └── VOC ← downloads here (2.8 GB) # 描述了数据集的下载位置,建议将VOC数据集下载到ultralytics/datasets/VOC目录下,数据集大小约为2.8GBpath: ../datasets/VOC # 指定数据集的根路径,这里表示相对于当前配置文件所在位置的上一级目录的datasets/VOC目录train:- images/train2012- images/train2007- images/val2012- images/val2007 # 定义训练集的图像路径,这些路径是相对于上面指定的path路径的,包含了2012年和2007年的训练集和验证集图像路径,共16551张图像val:- images/test2007 # 定义验证集的图像路径,相对于path路径,这里使用了2007年的测试集图像作为验证集,共4952张图像test:- images/test2007 # 定义测试集的图像路径,相对于path路径,这里同样使用了2007年的测试集图像,标注为可选# Classes names:0: aeroplane # 索引0对应的类别名称为“aeroplane”,在数据集中用于标识飞机类别1: bicycle # 索引1对应的类别名称为“bicycle”,表示自行车类别2: bird # 索引2对应的类别名称为“bird”,代表鸟类别3: boat # 索引3对应的类别名称为“boat”,用于表示船类别4: bottle # 索引4对应的类别名称为“bottle”,表示瓶子类别5: bus # 索引5对应的类别名称为“bus”,代表公共汽车类别6: car # 索引6对应的类别名称为“car”,表示汽车类别7: cat # 索引7对应的类别名称为“cat”,代表猫类别8: chair # 索引8对应的类别名称为“chair”,表示椅子类别9: cow # 索引9对应的类别名称为“cow”,代表牛类别10: diningtable # 索引10对应的类别名称为“diningtable”,表示餐桌类别11: dog # 索引11对应的类别名称为“dog”,代表狗类别12: horse # 索引12对应的类别名称为“horse”,表示马类别13: motorbike # 索引13对应的类别名称为“motorbike”,代表摩托车类别14: person # 索引14对应的类别名称为“person”,表示人类别15: pottedplant # 索引15对应的类别名称为“pottedplant”,表示盆栽植物类别16: sheep # 索引16对应的类别名称为“sheep”,代表羊类别17: sofa # 索引17对应的类别名称为“sofa”,表示沙发类别18: train # 索引18对应的类别名称为“train”,代表火车类别19: tvmonitor # 索引19对应的类别名称为“tvmonitor”,表示电视监视器类别 # 定义数据集中的类别名称,每个数字对应一个类别,共20个类别download: |import xml.etree.ElementTree as ETfrom pathlib import Pathfrom tqdm import tqdmfrom ultralytics.utils.downloads import download# 导入必要的模块,用于解析XML文件、处理文件路径、显示进度条以及下载数据集def convert_label(path, lb_path, year, image_id):# 函数功能:将VOC格式的XML标注文件转换为YOLO格式,通过提取边界框和类别ID实现def convert_box(size, box):dw, dh = 1.0 / size[0], 1.0 / size[1]x, y, w, h = (box[0] + box[1]) / 2.0 - 1, (box[2] + box[3]) / 2.0 - 1, box[1] - box[0], box[3] - box[2]return x * dw, y * dh, w * dw, h * dh# 内部函数,将边界框的坐标从VOC格式(xmin, xmax, ymin, ymax)转换为YOLO格式(中心x, 中心y, 宽度, 高度),并进行归一化in_file = open(path / f"VOC{year}/Annotations/{image_id}.xml")out_file = open(lb_path, "w")# 打开VOC格式的XML标注文件用于读取,打开一个新文件用于写入转换后的YOLO格式标注tree = ET.parse(in_file)root = tree.getroot()size = root.find("size")w = int(size.find("width").text)h = int(size.find("height").text)# 解析XML文件,获取根节点,然后找到图像尺寸信息,提取图像的宽度和高度names = list(yaml["names"].values()) # names list# 获取所有类别的名称列表,这些名称来自于yaml配置文件中的"names"字段for obj in root.iter("object"):cls = obj.find("name").textif cls in names and int(obj.find("difficult").text) != 1:xmlbox = obj.find("bndbox")bb = convert_box((w, h), [float(xmlbox.find(x).text) for x in ("xmin", "xmax", "ymin", "ymax")])cls_id = names.index(cls) # class idout_file.write(" ".join(str(a) for a in (cls_id, *bb)) + "\n")# 遍历XML文件中的每个目标对象,获取其类别名称,检查是否在类别列表中且不是困难样本,# 然后获取边界框信息,转换为YOLO格式,得到类别ID,并将类别ID和边界框信息写入新文件# Downloaddir = Path(yaml["path"]) # dataset root dirurl = "https://github.com/ultralytics/assets/releases/download/v0.0.0/"urls = [f"{url}VOCtrainval_06-Nov-2007.zip", # 446MB, 5012 imagesf"{url}VOCtest_06-Nov-2007.zip", # 438MB, 4953 imagesf"{url}VOCtrainval_11-May-2012.zip", # 1.95GB, 17126 images]# 获取数据集根目录路径,定义下载的基础URL,以及要下载的数据集压缩包的URL列表download(urls, dir=dir / "images", curl=True, threads=3, exist_ok=True) # download and unzip over existing (required)# 使用提供的下载函数,从指定的URL列表下载数据集压缩包,并解压到指定目录(dir / "images"),# 使用curl方式下载,开启3个线程,允许覆盖已存在的文件# Convertpath = dir / "images/VOCdevkit"for year, image_set in ("2012", "train"), ("2012", "val"), ("2007", "train"), ("2007", "val"), ("2007", "test"):imgs_path = dir / "images" / f"{image_set}{year}"lbs_path = dir / "labels" / f"{image_set}{year}"imgs_path.mkdir(exist_ok=True, parents=True)lbs_path.mkdir(exist_ok=True, parents=True)# 定义VOC开发工具包路径,遍历不同年份和数据集划分(训练集、验证集、测试集)的组合,# 分别定义图像文件和标注文件的目标路径,并创建相应的目录(如果不存在)with open(path / f"VOC{year}/ImageSets/Main/{image_set}.txt") as f:image_ids = f.read().strip().split()# 打开包含图像ID列表的文本文件,读取内容并处理成图像ID列表for id in tqdm(image_ids, desc=f"{image_set}{year}"):f = path / f"VOC{year}/JPEGImages/{id}.jpg" # old img pathlb_path = (lbs_path / f.name).with_suffix(".txt") # new label pathf.rename(imgs_path / f.name) # move imageconvert_label(path, lb_path, year, id) # convert labels to YOLO format# 遍历图像ID列表,显示处理进度条,获取原始图像文件路径和新的标注文件路径,# 将图像文件移动到目标图像路径,然后调用convert_label函数将标注文件转换为YOLO格式
xView.yaml
-
# 数据集根路径,这里设置为相对于当前文件所在目录的上一级目录下的datasets/xView目录 path: ../datasets/xView # 训练集图像路径,通过指定的文本文件(autosplit_train.txt)来确定训练集图像,该文件中每行可能是一个图像的路径 train: images/autosplit_train.txt # 验证集图像路径,同样通过指定的文本文件(autosplit_val.txt)来确定验证集图像 val: images/autosplit_val.txt # Classes names:0: Fixed-wing Aircraft # 索引0对应的类别名称为“Fixed-wing Aircraft”,表示固定翼飞机1: Small Aircraft # 索引1对应的类别名称为“Small Aircraft”,表示小型飞机2: Cargo Plane # 索引2对应的类别名称为“Cargo Plane”,表示货机3: Helicopter # 索引3对应的类别名称为“Helicopter”,表示直升机4: Passenger Vehicle # 索引4对应的类别名称为“Passenger Vehicle”,表示乘用车5: Small Car # 索引5对应的类别名称为“Small Car”,表示小型汽车6: Bus # 索引6对应的类别名称为“Bus”,表示公共汽车7: Pickup Truck # 索引7对应的类别名称为“Pickup Truck”,表示皮卡8: Utility Truck # 索引8对应的类别名称为“Utility Truck”,表示多功能卡车9: Truck # 索引9对应的类别名称为“Truck”,表示卡车10: Cargo Truck # 索引10对应的类别名称为“Cargo Truck”,表示货运卡车11: Truck w/Box # 索引11对应的类别名称为“Truck w/Box”,表示带车厢的卡车12: Truck Tractor # 索引12对应的类别名称为“Truck Tractor”,表示牵引车13: Trailer # 索引13对应的类别名称为“Trailer”,表示拖车14: Truck w/Flatbed # 索引14对应的类别名称为“Truck w/Flatbed”,表示平板卡车15: Truck w/Liquid # 索引15对应的类别名称为“Truck w/Liquid”,表示液体运输卡车16: Crane Truck # 索引16对应的类别名称为“Crane Truck”,表示起重机卡车17: Railway Vehicle # 索引17对应的类别名称为“Railway Vehicle”,表示铁路车辆18: Passenger Car # 索引18对应的类别名称为“Passenger Car”,表示客车19: Cargo Car # 索引19对应的类别名称为“Cargo Car”,表示货车20: Flat Car # 索引20对应的类别名称为“Flat Car”,表示平板车21: Tank car # 索引21对应的类别名称为“Tank car”,表示罐车22: Locomotive # 索引22对应的类别名称为“Locomotive”,表示火车头23: Maritime Vessel # 索引23对应的类别名称为“Maritime Vessel”,表示海上船只24: Motorboat # 索引24对应的类别名称为“Motorboat”,表示摩托艇25: Sailboat # 索引25对应的类别名称为“Sailboat”,表示帆船26: Tugboat # 索引26对应的类别名称为“Tugboat”,表示拖船27: Barge # 索引27对应的类别名称为“Barge”,表示驳船28: Fishing Vessel # 索引28对应的类别名称为“Fishing Vessel”,表示渔船29: Ferry # 索引29对应的类别名称为“Ferry”,表示渡轮30: Yacht # 索引30对应的类别名称为“Yacht”,表示游艇31: Container Ship # 索引31对应的类别名称为“Container Ship”,表示集装箱船32: Oil Tanker # 索引32对应的类别名称为“Oil Tanker”,表示油轮33: Engineering Vehicle # 索引33对应的类别名称为“Engineering Vehicle”,表示工程车辆34: Tower crane # 索引34对应的类别名称为“Tower crane”,表示塔式起重机35: Container Crane # 索引35对应的类别名称为“Container Crane”,表示集装箱起重机36: Reach Stacker # 索引36对应的类别名称为“Reach Stacker”,表示正面吊运机37: Straddle Carrier # 索引37对应的类别名称为“Straddle Carrier”,表示跨运车38: Mobile Crane # 索引38对应的类别名称为“Mobile Crane”,表示移动式起重机39: Dump Truck # 索引39对应的类别名称为“Dump Truck”,表示自卸卡车40: Haul Truck # 索引40对应的类别名称为“Haul Truck”,表示矿用卡车41: Scraper/Tractor # 索引41对应的类别名称为“Scraper/Tractor”,表示铲运机/拖拉机42: Front loader/Bulldozer # 索引42对应的类别名称为“Front loader/Bulldozer”,表示前装机/推土机43: Excavator # 索引43对应的类别名称为“Excavator”,表示挖掘机44: Cement Mixer # 索引44对应的类别名称为“Cement Mixer”,表示水泥搅拌车45: Ground Grader # 索引45对应的类别名称为“Ground Grader”,表示平地机46: Hut/Tent # 索引46对应的类别名称为“Hut/Tent”,表示小屋/帐篷47: Shed # 索引47对应的类别名称为“Shed”,表示棚屋48: Building # 索引48对应的类别名称为“Building”,表示建筑物49: Aircraft Hangar # 索引49对应的类别名称为“Aircraft Hangar”,表示飞机库50: Damaged Building # 索引50对应的类别名称为“Damaged Building”,表示受损建筑物51: Facility # 索引51对应的类别名称为“Facility”,表示设施52: Construction Site # 索引52对应的类别名称为“Construction Site”,表示建筑工地53: Vehicle Lot # 索引53对应的类别名称为“Vehicle Lot”,表示停车场54: Helipad # 索引54对应的类别名称为“Helipad”,表示直升机停机坪55: Storage Tank # 索引55对应的类别名称为“Storage Tank”,表示储罐56: Shipping container lot # 索引56对应的类别名称为“Shipping container lot”,表示集装箱堆场57: Shipping Container # 索引57对应的类别名称为“Shipping Container”,表示集装箱58: Pylon # 索引58对应的类别名称为“Pylon”,表示塔架59: Tower # 索引59对应的类别名称为“Tower”,表示塔download: |import jsonimport osfrom pathlib import Pathimport numpy as npfrom PIL import Imagefrom tqdm import tqdmfrom ultralytics.data.utils import autosplitfrom ultralytics.utils.ops import xyxy2xywhn# 导入所需的模块和函数,用于处理JSON数据、文件和目录操作、数值计算、图像操作、进度条显示、数据自动分割以及坐标转换def convert_labels(fname=Path("xView/xView_train.geojson")):# 函数功能:将xView的geoJSON格式标注转换为YOLO格式,将类别映射到索引0 - 59,并保存为文本文件path = fname.parentwith open(fname, encoding="utf-8") as f:print(f"Loading {fname}...")data = json.load(f)# 打开geoJSON文件,读取其中的数据并解析为Python字典# Make dirslabels = Path(path / "labels" / "train")os.system(f"rm -rf {labels}")labels.mkdir(parents=True, exist_ok=True)# 创建保存YOLO格式标注文件的目录,如果目录已存在则先删除再创建# xView classes 11-94 to 0-59xview_class2index = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, -1, 3, -1, 4, 5, 6, 7, 8, -1, 9, 10, 11,12, 13, 14, 15, -1, -1, 16, 17, 18, 19, 20, 21, 22, -1, 23, 24, 25, -1, 26, 27, -1, 28, -1,29, 30, 31, 32, 33, 34, 35, 36, 37, -1, 38, 39, 40, 41, 42, 43, 44, 45, -1, -1, -1, -1, 46,47, 48, 49, -1, 50, 51, -1, 52, -1, -1, -1, 53, 54, -1, 55, -1, -1, 56, -1, 57, -1, 58, 59]# 定义一个列表,用于将xView数据集中原始的类别编号(11 - 94)映射到0 - 59的索引,-1表示该原始类别不使用shapes = {}for feature in tqdm(data["features"], desc=f"Converting {fname}"):p = feature["properties"]if p["bounds_imcoords"]:id = p["image_id"]file = path / "train_images" / idif file.exists(): # 1395.tif missingtry:box = np.array([int(num) for num in p["bounds_imcoords"].split(",")])assert box.shape[0] == 4, f"incorrect box shape {box.shape[0]}"cls = p["type_id"]cls = xview_class2index[int(cls)] # xView class to 0-60assert 59 >= cls >= 0, f"incorrect class index {cls}"# 从标注数据中提取边界框坐标和类别ID,进行有效性检查,并将类别ID映射到0 - 59的索引# Write YOLO labelif id not in shapes:shapes[id] = Image.open(file).sizebox = xyxy2xywhn(box[None].astype(np.float), w=shapes[id][0], h=shapes[id][1], clip=True)with open((labels / id).with_suffix(".txt"), "a", encoding="utf-8") as f:f.write(f"{cls} {' '.join(f'{x:.6f}' for x in box[0])}\n") # write label.txt# 如果图像尺寸信息不存在,则读取图像获取尺寸。将边界框坐标从xyxy格式转换为xywhn格式,并写入YOLO格式的标注文件except Exception as e:print(f"WARNING: skipping one label for {file}: {e}")# 如果在处理过程中出现异常,打印警告信息并跳过当前标注dir = Path(yaml["path"]) # dataset root dir# 获取数据集根目录路径,这里的yaml需要在实际运行环境中正确定义# Convert labelsconvert_labels(dir / "xView_train.geojson")# 调用convert_labels函数,将xView_train.geojson中的标注转换为YOLO格式# Move imagesimages = Path(dir / "images")images.mkdir(parents=True, exist_ok=True)Path(dir / "train_images").rename(dir / "images" / "train")Path(dir / "val_images").rename(dir / "images" / "val")# 创建images目录,将train_images目录重命名为images/train,将val_images目录重命名为images/val# Splitautosplit(dir / "images" / "train")# 对images/train目录下的图像进行自动分割,可能是将其划分为训练集和验证集(具体分割逻辑取决于autosplit函数的实现)