ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

VisDrone数据集转COCO格式:从TXT到JSON的完整转换指南

VisDrone数据集转COCO格式:从TXT到JSON的完整转换指南 简介在计算机视觉领域数据标注格式的统一是模型训练与迁移的基础。COCOCommon Objects in Context格式因其结构清晰、生态完善已成为目标检测与实例分割任务的事实标准。其核心原理在于通过结构化的JSON文件将图像元信息、类别定义及实例标注如边界框、分割掩码有机整合形成自包含的数据描述。这种设计极大提升了数据集的互操作性使得在COCO上预训练的模型如YOLO、Faster R-CNN能够便捷地迁移到新任务。对于无人机视觉任务中广泛使用的VisDrone数据集其提供的TXT格式标注与COCO标准不兼容这阻碍了先进模型的直接应用。因此将VisDrone的TXT标注转换为COCO JSON格式成为连接无人机航拍图像处理与主流深度学习框架的关键技术环节。通过编写转换脚本实现坐标归一化到绝对像素值的映射、类别ID系统的重建以及数据结构封装开发者可以无缝利用MMDetection、Detectron2等框架的丰富工具链在小目标检测等复杂场景下高效开展模型训练与评估。1. 从VisDrone到COCO一个无人机视觉任务的“翻译”过程如果你处理过无人机航拍图像的目标检测任务大概率听说过VisDrone这个数据集。它由天津大学等机构发布包含了大量在复杂城市、乡村、交通枢纽等场景下采集的无人机图像标注了行人、车辆、自行车等十类目标是研究无人机视角下小目标、密集目标检测的宝贵资源。然而当你兴冲冲地下载了VisDrone数据集准备用上那些在COCO数据集上预训练好的、性能强悍的检测模型比如YOLO、Faster R-CNN、DETR时往往会遇到第一个拦路虎格式不兼容。VisDrone数据集提供的标注文件是.txt格式遵循着“类别ID 中心x 中心y 宽 高”的规范并且坐标是相对于图像宽高归一化的。而COCOCommon Objects in Context格式作为当前目标检测、实例分割领域事实上的“标准交换格式”使用的是结构化的.json文件。这个JSON文件不仅仅是一个标注列表它更是一个自包含的数据库里面详细描述了整个数据集的元信息、所有图像的属性以及每一个目标实例的精确位置和类别。绝大多数先进的深度学习框架和模型库如MMDetection、Detectron2、PyTorch Lightning等都原生支持读取COCO格式的标注文件这使得COCO格式的权重和预训练模型能够无缝迁移到新任务上。因此“VisDrone转COCO格式JSON文件”这个操作本质上是一个**数据格式的“翻译”与“重构”**过程。它的核心目的是将VisDrone数据集中分散的、相对原始的TXT标注信息整合、转换并封装成一个符合COCO JSON规范的结构化文件。这个过程不仅仅是简单的字符串拼接它涉及到坐标系的转换、ID系统的重建、以及数据结构的设计。一个高质量的转换脚本能让你直接利用COCO生态中丰富的工具链进行可视化、评估和训练极大地提升研究或工程开发的效率。接下来我们就深入这个“翻译”过程的每一个细节。2. COCO JSON格式深度拆解不只是标注列表在动手转换之前我们必须彻底理解目标格式——COCO JSON的“语法”。很多转换脚本出问题根源在于对COCO格式的理解停留在表面。COCO的JSON文件是一个多层嵌套的字典结构主要包含三个顶级键info,images,annotations对于有分割任务的数据集还会有categories和licensesVisDrone转换中通常可简化或忽略licenses。2.1images数组为每一张图建立“身份证”images字段是一个列表列表中的每个元素是一个字典代表数据集中的一张图像。这个字典必须包含以下核心信息id: 整型图像的唯一标识符。这是整个JSON文件中最重要的索引之一。在VisDrone中图像文件名如0000001_00001_d_0000001.jpg包含序列信息我们需要为其分配一个唯一且连续的整数ID通常从1或0开始。file_name: 字符串图像文件的名称。需要与磁盘上的文件名严格一致。height和width: 整型图像的高和宽。这个信息至关重要因为VisDrone的TXT标注是归一化坐标我们必须根据原始图像的实际尺寸将其还原为绝对坐标像素值才能填入COCO的bbox。获取图像尺寸通常需要借助PILPython Imaging Library或OpenCV库在转换过程中实时读取。一个典型的images条目如下{ images: [ { id: 1, file_name: 0000001_00001_d_0000001.jpg, height: 1080, width: 1920 }, // ... 更多图像 ] }2.2annotations数组标注信息的核心载体annotations是另一个列表每个元素代表一个目标实例如一个人、一辆车的标注。它的结构更复杂id: 整型标注实例的全局唯一ID。通常在整个数据集中连续递增与图像ID无关。image_id: 整型此实例所属图像的ID。必须与images数组中某一条目的id对应上。这是连接实例与图像的桥梁。category_id: 整型实例的类别ID。需要与后续categories数组中定义的ID对应。bbox: 一个包含4个浮点数的列表[x, y, width, height]。这里是最容易出错的地方x,y: 代表边界框左上角的像素坐标。width,height: 代表边界框的宽和高像素值。关键转换VisDrone的TXT格式是[class_id, center_x, center_y, bbox_width, bbox_height]且均为归一化值0~1。转换公式为img_w, img_h image_width, image_height # 从VisDrone TXT中读取的归一化中心坐标和宽高 norm_center_x, norm_center_y, norm_w, norm_h ... # 转换为COCO的左上角坐标和绝对宽高 abs_x (norm_center_x - norm_w / 2.0) * img_w abs_y (norm_center_y - norm_h / 2.0) * img_h abs_w norm_w * img_w abs_h norm_h * img_h # COCO要求bbox是浮点数列表 bbox [abs_x, abs_y, abs_w, abs_h]area: 浮点数边界框的面积 (width * height)。在COCO评估指标中用于区分小、中、大目标。iscrowd: 整型0或1表示是否是拥挤、难以区分的群体。VisDrone数据集中通常为0除非有特殊标注。segmentation和keypoints: 对于实例分割和关键点检测任务有用。在纯目标检测任务中segmentation可以用bbox的四个角点组成的列表[[x1,y1, x2,y2, x3,y3, x4,y4]]来近似表示或者直接留空列表[]。VisDrone本身不提供分割标注所以通常设为[]。一个典型的annotations条目如下{ annotations: [ { id: 1, image_id: 1, category_id: 1, bbox: [512.3, 256.8, 64.2, 128.5], area: 8243.1, iscrowd: 0, segmentation: [] }, // ... 更多标注 ] }2.3categories数组定义类别字典categories列表定义了数据集中所有对象类别。每个类别是一个字典id: 整型类别的唯一ID。这里需要与VisDrone原始的类别ID进行映射。VisDrone有10个类别如pedestrian, people, bicycle, car等但它的ID是从0开始的而COCO格式通常也从0或1开始。我们需要建立一个明确的映射关系并确保annotations中的category_id使用映射后的新ID。name: 字符串类别的名称。supercategory: 字符串父类别可选。例如“car”和“bus”的supercategory可以是“vehicle”。一个典型的categories定义如下{ categories: [ {id: 1, name: pedestrian, supercategory: person}, {id: 2, name: people, supercategory: person}, {id: 3, name: bicycle, supercategory: vehicle}, {id: 4, name: car, supercategory: vehicle}, // ... 其他类别 ] }注意VisDrone的“ignored regions”忽略区域在TXT中以特定类别ID如0或11标注。在转换时你需要决定是否将它们纳入COCO JSON。通常对于目标检测训练我们会过滤掉这些忽略区域因为它们不是有效的检测目标。但如果你的任务需要特别处理被遮挡或模糊的区域也可以将其转换为一个特殊的category如“ignored”。3. 手把手实现转换脚本从TXT到JSON的完整链路理解了COCO格式的“语法”我们就可以开始编写“翻译器”了。下面我将以一个Python脚本为例详细拆解每一步并说明其中的坑点和优化技巧。3.1 环境准备与目录结构假设你的VisDrone数据集目录结构如下VisDrone2019-DET-train/ ├── images/ │ ├── 0000001_00001_d_0000001.jpg │ ├── 0000002_00001_d_0000002.jpg │ └── ... └── annotations/ ├── 0000001_00001_d_0000001.txt ├── 0000002_00001_d_0000002.txt └── ...你需要安装必要的Python库PIL(或Pillow)、json、tqdm用于进度条。pip install Pillow tqdm3.2 核心转换代码实现import os import json from PIL import Image from tqdm import tqdm import argparse def convert_visdrone_to_coco(visdrone_img_dir, visdrone_ann_dir, output_json_path): 将VisDrone格式的标注转换为COCO格式的JSON文件。 Args: visdrone_img_dir (str): VisDrone图像文件夹路径。 visdrone_ann_dir (str): VisDrone标注TXT文件夹路径。 output_json_path (str): 输出的COCO JSON文件路径。 # 1. 定义类别映射。VisDrone原始类别ID到COCO类别ID和名称的映射。 # VisDrone类别: 0:ignored, 1:pedestrian, 2:people, 3:bicycle, 4:car, 5:van, 6:truck, 7:tricycle, 8:awning-tricycle, 9:bus, 10:motor # 我们过滤掉ignored regions (0)并为其他类别建立映射。 categories [] visdrone_to_coco_id {} # 这里我们创建一个新的ID序列从1开始 coco_categories [ {id: 1, name: pedestrian, supercategory: person}, {id: 2, name: people, supercategory: person}, {id: 3, name: bicycle, supercategory: vehicle}, {id: 4, name: car, supercategory: vehicle}, {id: 5, name: van, supercategory: vehicle}, {id: 6, name: truck, supercategory: vehicle}, {id: 7, name: tricycle, supercategory: vehicle}, {id: 8, name: awning-tricycle, supercategory: vehicle}, {id: 9, name: bus, supercategory: vehicle}, {id: 10, name: motor, supercategory: vehicle}, ] for cat in coco_categories: categories.append(cat) # 建立映射VisDrone原始ID (1-10) - COCO ID (1-10) # 注意这里假设我们使用的VisDrone标注TXT中类别ID就是1-10忽略了0。 visdrone_to_coco_id[cat[id]] cat[id] # 这里ID一致但映射关系是明确的 # 2. 初始化COCO JSON结构 coco_output { info: { description: VisDrone2019-DET Dataset converted to COCO format, version: 1.0, year: 2019, contributor: VisDrone Team, date_created: 2023/10/27 }, licenses: [{url: http://creativecommons.org/licenses/by-nc-sa/4.0/, id: 1, name: CC BY-NC-SA 4.0}], images: [], annotations: [], categories: categories } # 3. 遍历图像和标注文件 image_id 1 annotation_id 1 # 获取所有图像文件确保和标注文件能对应上 img_files [f for f in os.listdir(visdrone_img_dir) if f.lower().endswith((.jpg, .jpeg, .png))] img_files.sort() # 排序以保证ID顺序固定 print(f开始处理 {len(img_files)} 张图像...) for img_file in tqdm(img_files): # 构建完整的图像路径和对应的标注TXT路径 img_path os.path.join(visdrone_img_dir, img_file) ann_file os.path.splitext(img_file)[0] .txt ann_path os.path.join(visdrone_ann_dir, ann_file) # 检查标注文件是否存在 if not os.path.exists(ann_path): print(f警告标注文件 {ann_path} 不存在跳过图像 {img_file}。) continue # 读取图像尺寸 try: with Image.open(img_path) as img: width, height img.size except Exception as e: print(f无法读取图像 {img_path}: {e}跳过。) continue # 添加图像信息到COCO结构 image_info { id: image_id, file_name: img_file, height: height, width: width } coco_output[images].append(image_info) # 读取并处理标注TXT文件 with open(ann_path, r) as f: lines f.readlines() for line in lines: line line.strip() if not line: continue parts line.split(,) # VisDrone DET格式: bbox_left,bbox_top,bbox_width,bbox_height,score,object_category,truncation,occlusion # 但更常见的TXT格式是class_id center_x_norm center_y_norm width_norm height_norm # 这里我们假设是第二种格式。如果是第一种解析方式需要调整。 # 我们按空格分割并尝试转换为浮点数 data list(map(float, line.split())) if len(data) 5: continue # 跳过格式错误的行 class_id, center_x_norm, center_y_norm, w_norm, h_norm data[:5] # 过滤掉忽略区域如果class_id是0 if int(class_id) 0: continue # 将归一化坐标转换为绝对像素坐标COCO格式 # 注意这里假设TXT中的坐标是归一化的中心点坐标和宽高。 # 如果VisDrone提供的TXT是左上角坐标和宽高且为绝对像素值则转换逻辑完全不同 abs_x (center_x_norm - w_norm / 2.0) * width abs_y (center_y_norm - h_norm / 2.0) * height abs_w w_norm * width abs_h h_norm * height # 确保边界框在图像范围内处理可能的浮点数精度问题 abs_x max(0, abs_x) abs_y max(0, abs_y) abs_w min(abs_w, width - abs_x) abs_h min(abs_h, height - abs_y) # 如果转换后的边界框无效宽或高0则跳过 if abs_w 0 or abs_h 0: continue # 计算面积 area abs_w * abs_h # 获取映射后的COCO类别ID coco_category_id visdrone_to_coco_id.get(int(class_id)) if coco_category_id is None: # 如果遇到未定义的类别ID跳过或记录警告 print(f警告图像 {img_file} 中发现未知类别ID {class_id}跳过此标注。) continue # 构建标注信息 ann_info { id: annotation_id, image_id: image_id, category_id: coco_category_id, bbox: [abs_x, abs_y, abs_w, abs_h], # COCO格式[x, y, width, height] area: area, iscrowd: 0, segmentation: [] # 目标检测任务分割掩码为空 } coco_output[annotations].append(ann_info) annotation_id 1 image_id 1 # 4. 保存为JSON文件 with open(output_json_path, w) as f: json.dump(coco_output, f, indent2) print(f转换完成共处理 {len(coco_output[images])} 张图像{len(coco_output[annotations])} 个标注实例。) print(f结果已保存至: {output_json_path}) if __name__ __main__: parser argparse.ArgumentParser(descriptionConvert VisDrone annotations to COCO format.) parser.add_argument(--img_dir, typestr, requiredTrue, helpPath to VisDrone images directory.) parser.add_argument(--ann_dir, typestr, requiredTrue, helpPath to VisDrone annotations directory.) parser.add_argument(--output, typestr, defaultvisdrone_train_coco.json, helpOutput COCO JSON file path.) args parser.parse_args() convert_visdrone_to_coco(args.img_dir, args.ann_dir, args.output)3.3 关键步骤解析与避坑指南图像尺寸读取的优化上述脚本对每张图都用PIL.Image.open读取尺寸对于数万张图像的数据集这会成为性能瓶颈。一个优化方案是提前遍历一次将(文件名宽高)缓存到一个字典或JSON文件中转换时直接查询速度能提升一个数量级。标注格式的确认VisDrone数据集可能提供多种标注格式。务必确认你下载的TXT文件是“归一化中心坐标”格式还是“绝对像素左上角坐标”格式。上述脚本针对的是前者。如果是后者转换逻辑简化为abs_x, abs_y, abs_w, abs_h bbox_left, bbox_top, bbox_width, bbox_height # 注意仍需检查边界是否超出图像范围。你可以通过查看前几行TXT文件的内容来判断。归一化坐标值通常在0~1之间而绝对像素坐标值可能是几十到上千的整数。类别映射的灵活性脚本中的类别映射是硬编码的。在实际项目中你可能希望合并某些类别如将pedestrian和people都映射为person或者忽略某些不感兴趣的类别如tricycle。修改categories列表和visdrone_to_coco_id映射字典即可实现。忽略区域的处理脚本直接过滤掉了类别ID为0的忽略区域。如果你的任务需要这些信息可以将其映射为一个特殊的COCO类别如id: 11, name: ignored并在后续训练中通过设置数据加载器的skip_empty选项或在损失函数中赋予极低权重来处理。ID连续性的重要性COCO格式要求image_id和annotation_id在各自数组内是唯一的但通常不强制要求连续。然而保持ID连续从1开始递增是一个好习惯能避免一些下游工具如某些可视化库的潜在问题。验证生成的JSON转换完成后强烈建议使用COCO官方API或第三方工具验证JSON文件的正确性。一个简单的方法是使用pycocotoolsfrom pycocotools.coco import COCO coco COCO(你的输出文件.json) # 如果没有报错说明格式基本正确 # 可以进一步打印统计信息 print(coco.dataset[info]) print(f图像数量: {len(coco.imgs)}) print(f标注数量: {len(coco.anns)}) print(f类别数量: {len(coco.cats)})4. 转换后JSON文件的验证与应用生成COCO格式的JSON文件不是终点而是高效利用现有深度学习生态的起点。验证文件的正确性至关重要。4.1 使用COCO API进行可视化验证最直观的验证方式是将标注可视化到图像上。pycocotools不仅用于评估也提供了简单的可视化功能。import matplotlib.pyplot as plt from pycocotools.coco import COCO import cv2 import os # 加载转换后的COCO标注 coco COCO(visdrone_train_coco.json) # 获取所有类别 cats coco.loadCats(coco.getCatIds()) cat_names [cat[name] for cat in cats] print(COCO categories: \n, .join(cat_names)) # 获取所有图像ID img_ids coco.getImgIds() print(f总图像数: {len(img_ids)}) # 随机选择一张图像进行可视化 import random img_id random.choice(img_ids) img_info coco.loadImgs(img_id)[0] img_path os.path.join(VisDrone2019-DET-train/images, img_info[file_name]) # 读取图像 I cv2.imread(img_path) # 转换颜色通道matplotlib使用RGB I cv2.cvtColor(I, cv2.COLOR_BGR2RGB) # 加载该图像对应的所有标注ID ann_ids coco.getAnnIds(imgIdsimg_info[id]) anns coco.loadAnns(ann_ids) # 使用COCO API绘制标注 plt.figure(figsize(12, 8)) plt.imshow(I) coco.showAnns(anns, draw_bboxTrue) # 绘制边界框 plt.title(fImage ID: {img_id} - {img_info[file_name]}) plt.axis(off) plt.show()这段代码会随机显示一张图像及其上所有的检测框。检查边界框是否与目标对齐类别标签是否正确这是验证转换是否成功最直接的方法。4.2 在主流框架中加载与训练一旦验证通过你就可以像使用标准COCO数据集一样使用它了。以PyTorch和MMDetection为例修改配置文件在MMDetection的配置文件中如configs/_base_/datasets/coco_detection.py你只需要将数据集的ann_file和img_prefix路径指向你的VisDrone-COCO JSON文件和图像文件夹。# 在自定义配置文件中 data dict( traindict( typeCocoDataset, ann_filepath/to/your/visdrone_train_coco.json, img_prefixpath/to/your/VisDrone2019-DET-train/images/, # ... 其他参数 ), valdict(...), testdict(...) )直接使用预训练权重现在你可以直接加载在COCO数据集上预训练的模型权重如mask_rcnn_r50_fpn_1x_coco来对你的VisDrone数据进行微调Fine-tuning。模型会识别你定义的categories如pedestrian,car等而不再局限于COCO的80类。这是格式统一带来的最大便利。使用COCO评估指标你可以直接使用pycocotools中的COCOeval来评估你的模型在VisDrone验证集上的性能计算mAP平均精度均值。这确保了评估标准的统一和可比性。4.3 处理大规模数据集的性能考量当处理VisDrone这样的数据集训练集约6.5k张图像验证集约1.6k张时JSON文件可能变得很大几十MB甚至上百MB。在训练时每次迭代都完整加载这个JSON文件到内存是低效的。缓存策略像MMDetection这样的框架在首次读取数据集时会解析JSON并将标注信息缓存为.pkl文件后续加载速度大大加快。懒加载Lazy Loading更高级的做法是实现标注的懒加载即只在需要某张图像的标注时才从磁盘读取。这可以通过自定义Dataset类来实现但会稍微增加数据读取的复杂度。JSON文件优化在保存JSON时使用json.dump(..., indentNone, separators(,, :))可以生成最小化的JSON文件无空格和换行能减少约50%-70%的文件大小对磁盘IO友好。不过可读性会变差调试时可能不方便。5. 进阶话题处理特殊标注与格式变体VisDrone数据集的标注并非一成不变你可能遇到一些特殊情况或变体需要调整转换脚本。5.1 处理“忽略区域”与“困难样本”VisDrone的TXT标注中除了常规目标还有ignored regions通常类别ID为0和others可能被标记为特定ID。在目标检测中常见的处理策略有完全过滤如我们脚本所做在训练和评估中都不考虑。这是最简单直接的方法。作为负样本在训练时将这些区域的提议框Proposals视为负样本背景但需要小心因为有些忽略区域可能包含部分目标这可能会引入噪声。单独作为一个类别将其定义为一个特殊的“ignored”类别。在评估时可以忽略对这个类别的预测。这能让你在可视化时看到哪些区域被标记为需要忽略。5.2 处理VisDrone-MOT多目标跟踪格式如果你处理的是VisDrone的多目标跟踪数据集VisDrone-MOT其标注格式是每行包含[frame_index, target_id, bbox_left, bbox_top, bbox_width, bbox_height, score, object_category, truncation, occlusion]。转换为COCO格式用于检测任务时你需要忽略frame_index和target_id或者用frame_index来区分不同视频序列的图像。将每一帧视为一张独立的图像为其分配唯一的image_id。剩余的bbox_*等字段的处理方式与检测数据集类似。这本质上是从视频序列中构建一个大型的静态图像检测数据集。需要注意的是同一目标在不同帧中会出现多次这可能会影响训练数据的平衡性。5.3 与其他格式如YOLO、PASCAL VOC的互转有时你的工作流可能涉及多种格式。掌握了COCO格式的核心你可以很容易地编写与其他格式互转的脚本。COCO转YOLO需要将COCO的绝对坐标[x, y, w, h]转换为YOLO格式的归一化中心坐标[cx_norm, cy_norm, w_norm, h_norm]公式是上述转换公式的逆过程并保存为每张图一个TXT文件。COCO转PASCAL VOCVOC格式是每张图一个XML文件。你需要将COCO JSON中的信息提取出来按照VOC的XML结构包含filename,size,object等节点重新组织并写入。一个健壮的转换工具链应该能适应不同的输入格式。在实践中我通常会维护一个中心化的、最丰富的中间格式通常是COCO所有其他格式都先转到COCO再从COCO转到目标格式这样可以减少N*(N-1)对转换器的开发工作量。6. 调试与排错当转换结果不如预期时即使按照脚本一步步操作也可能遇到各种问题。这里列出几个常见问题及其排查思路问题1可视化时边界框错位或大小完全不对。可能原因1坐标转换公式错误。这是最常见的问题。再次确认你的VisDrone TXT格式是“中心点归一化宽高”还是“左上角绝对宽高”。用一张简单的图比如只有一个明显目标的图打印出转换前后的坐标值手动计算验证。可能原因2图像尺寸读取错误。用PIL或OpenCV读取图像后打印出(width, height)并与图像属性或直接用看图软件查看的信息进行比对。注意OpenCV的shape返回的是(height, width, channels)。排查命令# 在转换脚本中针对第一张图打印调试信息 print(fImage: {img_file}, Size: ({width}, {height})) print(fRaw bbox line: {line}) print(fParsed norm values: class{class_id}, cx{center_x_norm}, cy{center_y_norm}, w{w_norm}, h{h_norm}) print(fConverted abs bbox: [{abs_x}, {abs_y}, {abs_w}, {abs_h}])问题2类别ID混乱或者某些类别在可视化中不显示。可能原因类别映射字典visdrone_to_coco_id定义错误或覆盖不全。检查VisDrone原始TXT文件中出现的所有类别ID是否都在映射字典中有对应的键。可以在读取所有标注后统计一下出现的所有class_id。排查命令# 在读取所有标注后 all_class_ids set() for line in all_lines: class_id int(line.split()[0]) all_class_ids.add(class_id) print(f所有出现的原始类别ID: {sorted(all_class_ids)}) # 对比你的映射字典的键 print(f映射字典包含的键: {list(visdrone_to_coco_id.keys())})问题3生成的JSON文件无法被pycocotools加载报JSONDecodeError或键错误。可能原因1JSON文件格式错误。可能是写入过程中出现了编码问题或字符串格式错误。用文本编辑器打开JSON文件检查最后几行是否有不完整的结构或者尝试用json.load()重新加载它来定位错误行。可能原因2缺少必需的键。确保images数组中的每个字典都有id,file_name,height,widthannotations数组中的每个字典都有id,image_id,category_id,bbox,area,iscrowd。bbox必须是4个数的列表。排查命令# 验证JSON可读性 with open(your_output.json, r) as f: data json.load(f) # 如果这里报错说明JSON文件损坏 # 验证结构 required_image_keys {id, file_name, height, width} for img in data[images][:5]: # 检查前5张图 if not required_image_keys.issubset(img.keys()): print(f图像 {img.get(id)} 缺少键: {required_image_keys - img.keys()})问题4转换速度非常慢。瓶颈分析最大的瓶颈通常是Image.open()读取图像尺寸。如前所述使用缓存可以极大提升速度。其次是文件IO读写大量TXT和最终的大JSON。可以考虑使用多进程并行处理图像但要注意JSON的写入需要序列化。简易缓存实现import pickle def get_image_size_cache(img_dir, cache_fileimage_sizes.pkl): if os.path.exists(cache_file): with open(cache_file, rb) as f: return pickle.load(f) else: size_cache {} for img_file in tqdm(os.listdir(img_dir)): img_path os.path.join(img_dir, img_file) try: with Image.open(img_path) as img: size_cache[img_file] img.size # (width, height) except: size_cache[img_file] (0, 0) with open(cache_file, wb) as f: pickle.dump(size_cache, f) return size_cache # 在转换函数开始调用 size_cache get_image_size_cache(visdrone_img_dir) # 在循环中直接使用 width, height size_cache.get(img_file, (0, 0))转换VisDrone数据到COCO格式是一个典型的“数据工程”任务它虽然不涉及复杂的算法但却是整个机器学习项目 pipeline 中至关重要且容易出错的一环。一个准确、高效的转换脚本能为后续的模型训练、评估和迭代扫清障碍。希望这份详细的指南能帮助你顺利完成转换并深刻理解这背后的每一个字节和像素的意义。本文还有配套的精品资源点击获取
返回列表