从零搭建pytorch模型教程(八)实践部分(二)目标检测数据集格式转换

前言

图像目标检测领域有一个非常著名的数据集叫做COCO,基本上现在在目标检测领域发论文,COCO是不可能绕过的Benchmark。因此许多的开源目标检测算法框架都会支持解析COCO数据集格式。通过将其他数据集格式转换成COCO格式可以无痛的使用这些开源框架来训练新的数据集,比如Pascal VOC数据集。

本文首先将介绍COCO和VOC目标检测数据集格式以及VOC转换到COCO格式的核心步骤,最后将自定义一种数据格式利用上述核心步骤将其转换到COCO格式下。只要理解了不同数据集的标注方法,转换数据集其实就是一个非常简单自然的过程,可以拓展到任意方式标注的数据集上。

数据集格式介绍

COCO
其实COCO数据集的标签内容不仅仅涵盖目标检测,还包含了目标关键点、实例Mask以及图片描述等信息。在这里我们着重介绍COCO的目标检测相关内容。我们以COCO2017为例先看看其标签文件结构:

图片

其中红框框出来的就是以Json格式组织的目标检测相关的标注文件,其主要由三个部分构成:

"info"字段:数据集的基本信息描述、版本号、年份等信息。

“images字段” :包含了图片路径、宽高信息、唯一标志ID等信息。

“annotations字段”:包含了图片中的Box位置、类别等信息。

其简单示例如下所示:

{"info": {"description": "COCO 2017 Dataset","url": "http://cocodataset.org","version": "1.0","year": 2017,"contributor": "COCO Consortium","date_created": "2017/09/01"},
"images": [{"license": 4,"file_name": "000000397133.jpg","coco_url": "http://images.cocodataset.org/val2017/000000397133.jpg","height": 427,"width": 640,"date_captured": "2013-11-14 17:02:52","flickr_url": "","id": 397133},{"license": 1,"file_name": "000000037777.jpg","coco_url": "http://images.cocodataset.org/val2017/000000037777.jpg","height": 230,"width": 352,"date_captured": "2013-11-14 20:55:31","flickr_url": "","id": 37777}],"annotations": [{"area": 702.1057499999998,  //Box的尺寸"image_id": 289343,         //对应的图像ID"bbox": [473.07,                 //左上角点x坐标395.93,                 //左上角点y坐标38.65,                  //Box的宽28.67                   //Box的高],"category_id": 18,          //对应的类别"id": 1768,                 //该标签独有ID"iscrowd": 0                //0表示非密集场景,1表示密集场景}]
}

PASCAL VOC

PASCAL VOC数据集有两个相对重要年份的数据集:PASCAL VOC 2007与PASCAL VOC 2012,每年都会在上一年的基础上增加一些额外的数据或标签。PASCAL VOC数据集也涵盖了分类、检测、分割、动作识别等标签。

我们这里着重介绍其检测部分,以PASCAL VOC 2012数据集为例,包含了20个类别1W+数据集,2W+标注Box的目标。其标签格式是每一个图片都有一个对应的XML文件作为其标注信息载体,标注信息主要包含如下几方面内容:

图像基本信息:图像名、图像尺寸等

object字段:目标分类标签、box标签(xmin,ymin,xmax,ymax)等信息

XML主要格式如下:

<annotation><folder>VOC2012</folder><filename>2007_000063.jpg</filename>           //标签对应的图片文件<source><database>The VOC2007 Database</database><annotation>PASCAL VOC2007</annotation><image>flickr</image></source><size>                                         //图像尺寸<width>500</width><height>375</height><depth>3</depth></size><segmented>1</segmented><object><name>dog</name>                           //类别<pose>Unspecified</pose><truncated>0</truncated><difficult>0</difficult>                   //1表示这个目标是比较难识别的<bndbox>                                   //box信息<xmin>123</xmin>                       //左上角x坐标<ymin>115</ymin>                       //左上角y坐标<xmax>379</xmax>                       //右下角x坐标<ymax>275</ymax>                       //右下角y坐标</bndbox></object><object><name>chair</name><pose>Frontal</pose><truncated>1</truncated><difficult>0</difficult><bndbox><xmin>75</xmin><ymin>1</ymin><xmax>428</xmax><ymax>375</ymax></bndbox></object>
</annotation>

数据集格式转换

在知道了各个数据集格式的基础上做数据集格式的转换就已经是非常简单的任务了,也有很多优秀的开源框架已经帮我们做好了这些事情比如MMDetection中就已经提供好了现成的工具供我们白嫖(bushi),使用了。

我们抽取其一些核心部分来一起看看,详细代码请参考MMDetection

Github:https://github.com/openmmlab/mmdetection/tree/master/tools/dataset_converters

从不同的数据集转换到COCO下主要也就两个步骤:

解析待转换数据集格式。

用COCO格式重构Json文件。

上述第二步对任意待转换数据集都是一样的,可以抽象为一个函数,输入的是解析好的不同数据集的Box信息等数据。下面我们以几个不同的数据集为例介绍。

From VOC to COCO
从VOC数据集到COCO数据集格式转换主要包含如下两个步骤:

解析VOC数据集数据:遍历图片以及对应XML文件,返回一个数组A,数组中的每一个实例包含了图片路径、Box相关标注信息等。

遍历A将A中的实例信息用COCO的格式表达出来并生成Json文件

其主要由两块核心代码构成,一个是VOC的XML文件解析,一个是Json文件生成。

VOC XML标注文件解析

xml文件解析已经有下面这个非常方便的Python库供大家使用

import xml.etree.ElementTree as ETdef parse_xml(args):xml_path, img_path = argstree = ET.parse(xml_path)           # 构建XML文件解析树root = tree.getroot()               # 获取XML文件的根节点size = root.find('size')            # 获取图像的尺寸w = int(size.find('width').text)    # 图像宽高h = int(size.find('height').text)bboxes = []labels = []bboxes_ignore = []labels_ignore = []for obj in root.findall('object'):  # 遍历object字段下所有box信息name = obj.find('name').textlabel = label_ids[name]difficult = int(obj.find('difficult').text)  #这个difficult对应的是COCO中iscrowdedbnd_box = obj.find('bndbox')bbox = [                             # 对应的Box标注信息(x1,y1,x2,y2)int(bnd_box.find('xmin').text),int(bnd_box.find('ymin').text),int(bnd_box.find('xmax').text),int(bnd_box.find('ymax').text)]if difficult:                        # 将difficult属性的Box放入ignore列表bboxes_ignore.append(bbox)       # 最后计算AP时这个GT是被忽略的labels_ignore.append(label)else:bboxes.append(bbox)labels.append(label)if not bboxes:bboxes = np.zeros((0, 4))labels = np.zeros((0, ))else:bboxes = np.array(bboxes, ndmin=2) - 1labels = np.array(labels)if not bboxes_ignore:bboxes_ignore = np.zeros((0, 4))labels_ignore = np.zeros((0, ))else:bboxes_ignore = np.array(bboxes_ignore, ndmin=2) - 1labels_ignore = np.array(labels_ignore)annotation = {'filename': img_path,'width': w,'height': h,'ann': {'bboxes': bboxes.astype(np.float32),'labels': labels.astype(np.int64),'bboxes_ignore': bboxes_ignore.astype(np.float32),'labels_ignore': labels_ignore.astype(np.int64)}}return annotation

用解析好的annotation重构COCO格式的Json文件:

import numpy as npdef voc_classes():return ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat','chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike', 'person','pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor']def cvt_to_coco_json(annotations):image_id = 0annotation_id = 0coco = dict()coco['images'] = []coco['type'] = 'instance'coco['categories'] = []coco['annotations'] = []image_set = set()# coco annotations字段添加标注信息def addAnnItem(annotation_id, image_id, category_id, bbox, difficult_flag):annotation_item = dict()annotation_item['segmentation'] = []# 这里省略了seg部分代码seg = []annotation_item['segmentation'].append(seg)# 转换为COCO对应的x1,y1,w,h格式xywh = np.array([bbox[0], bbox[1], bbox[2] - bbox[0], bbox[3] - bbox[1]])annotation_item['area'] = int(xywh[2] * xywh[3])# 如果difficult标志为1,该目标对应coco中iscrowd字段为1表明为密集目标场景if difficult_flag == 1:annotation_item['ignore'] = 0annotation_item['iscrowd'] = 1else:annotation_item['ignore'] = 0annotation_item['iscrowd'] = 0annotation_item['image_id'] = int(image_id)annotation_item['bbox'] = xywh.astype(int).tolist()annotation_item['category_id'] = int(category_id)annotation_item['id'] = int(annotation_id)coco['annotations'].append(annotation_item)return annotation_id + 1#for category_id, name in enumerate(voc_classes()):category_item = dict()category_item['supercategory'] = str('none')category_item['id'] = int(category_id)category_item['name'] = str(name)coco['categories'].append(category_item)for ann_dict in annotations:file_name = ann_dict['filename']ann = ann_dict['ann']assert file_name not in image_setimage_item = dict()image_item['id'] = int(image_id)image_item['file_name'] = str(file_name)image_item['height'] = int(ann_dict['height'])image_item['width'] = int(ann_dict['width'])coco['images'].append(image_item)        # 设置COCO的"images"字段image_set.add(file_name)# 设置COCO的"annotations"字段bboxes = ann['bboxes'][:, :4]            # 获取box和label类别信息labels = ann['labels']for bbox_id in range(len(bboxes)):bbox = bboxes[bbox_id]label = labels[bbox_id]annotation_id = addAnnItem(annotation_id, image_id, label, bbox, difficult_flag=0)# ignore的目标表示该GT被忽视bboxes_ignore = ann['bboxes_ignore'][:, :4]labels_ignore = ann['labels_ignore']for bbox_id in range(len(bboxes_ignore)):bbox = bboxes_ignore[bbox_id]label = labels_ignore[bbox_id]annotation_id = addAnnItem(annotation_id, image_id, label, bbox, difficult_flag=1)image_id += 1return coco

拿到返回的coco对象后只需要调用下列方法就可以将对象序列化成Json文件了。

import mmcv
mmcv.dump(coco, out_file) # out_file为输出的json文件名

值得注意的一点是上面提到的iscorwd这个字段,这个字段标注为1时,最后统计AP时,该GT与预测框完成匹配后还可以考虑与其他预测框进行匹配,允许多个预测框与其匹配(因为场景是密集的)。

自定义格式数据集 to COCO

首先我们自定义一种数据标注格式,我们用txt文件作为标注信息的载体,将txt文件与图像文件通过相同的文件名一一对应。分别将标签文件以及对应图像文件放在Annotations以及JPEGImages文件夹下,同时我们生成JPEGImages图像文件的filelist.txt文件,这个文件每一行对应一个图像文件的全路径:

图片

txt文件格式如下:

图片

第一列表示类别,从0开始;第二到第五列表示Box信息依次为中心点x方向坐标,中心点y方向坐标,box的宽以及高(cx,cy,w,h)。

我们同样使用前面介绍过的cvt_to_coco_json将固定格式的annotations转换为COCO格式,那么我们只需要编写解析自定义格式数据集生成annotations的代码即可:

box尺寸小于min_size的作为ignore对象

file_path为图像路径的filelist.txt文件的全路径

def parse_info(file_path, min_size):annotations = []invalid_img = 0small_box = 0with open(file_path, 'r') as f:for l in tqdm(f):img_file = l.rstrip()img = cv2.imread(img_file)if img is None:invalid_img += 1continueh,w,_ = img.shape# 获取对应的标签文件ann_file = img_file.replace("JPEGImages", "Annotations").replace \(".png", ".txt").replace(".jpg", ".txt")annotation = {'filename' : img_file,'height' : h,'width' : w,'ann' : {}}if not osp.exists(ann_file):annotations.append(annotation)continueboxes, labels = [], []boxes_ignore, labels_ignore = [], []with open(ann_file, 'r') as fr:for anno in fr:anno_list = anno.rstrip().split(' ')cls = int(anno_list[0])cx, cy = float(anno_list[1]), float(anno_list[2])w, h = float(anno_list[3]), float(anno_list[4])# 转换为COCO box表示格式x1 = max(0, int(cx-w/2))y1 = max(0, int(cy-h/2))box = [x1, y1, w, h]if w >= min_size and h >= min_size:labels.append(cls)boxes.append(box)else:labels_ignore.append(cls)boxes_ignore.append(box)                    boxes = np.zeros((0, 4)) if len(boxes) == 0 else np.array(boxes)labels = np.zeros((0, )) if len(labels) == 0 else np.array(labels)      boxes_ignore = np.zeros((0, 4)) if len(boxes_ignore) == 0 else np.array(boxes_ignore)labels_ignore = np.zeros((0, )) if len(labels_ignore) == 0 else np.array(labels_ignore)  annotation['ann']['bboxes'] = np.array(boxes)annotation['ann']['labels'] = np.array(labels)annotation['ann']['bboxes_ignore'] = np.array(boxes_ignore)annotation['ann']['labels_ignore'] = np.array(labels_ignore)annotations.append(annotation)print('INFO:Invalid IMG:{}'.format(invalid_img))return annotations

写在后面

数据集的转换是非常有必要的,在软件设计中我们希望一套代码尽可能多的为不同情况服务。在这里我们希望训练代码中一套数据集(Dataset)class代码来完成所有目标检测任务训练,而不是针对不同的数据集设计不同的Dataset class代码。而对于目标检测来说,COCO可能就是这个最佳的模板~

最后

感谢你们的阅读和喜欢,我收藏了很多技术干货,可以共享给喜欢我文章的朋友们,如果你肯花时间沉下心去学习,它们一定能帮到你。

因为这个行业不同于其他行业,知识体系实在是过于庞大,知识更新也非常快。作为一个普通人,无法全部学完,所以我们在提升技术的时候,首先需要明确一个目标,然后制定好完整的计划,同时找到好的学习方法,这样才能更快的提升自己。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

img

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

img

四、AI大模型商业化落地方案

img

五、面试资料

我们学习AI大模型必然是想找到高薪的工作,下面这些面试题都是总结当前最新、最热、最高频的面试题,并且每道题都有详细的答案,面试前刷完这套面试题资料,小小offer,不在话下。
在这里插入图片描述

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/50810.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【计算机网络】静态路由实验

一&#xff1a;实验目的 1&#xff1a;掌握通过静态路由方法实现网络的连通性。 二&#xff1a;实验仪器设备及软件 硬件&#xff1a;RCMS-C服务器、网线、Windows 2019/2003操作系统的计算机等。 软件&#xff1a;记事本、WireShark、Chrome浏览器等。 三&#xff1a;实验方…

《分析模式:可重用对象模型》学习笔记之四:企业财务分析中的观察和测量02

这个模型基本解决问题&#xff0c;可以方便定义层次&#xff0c;以及反映了三个不同的维数元素&#xff0c;也反映了企业部门单元和维数元素的关系&#xff0c;但是很快可以看到&#xff0c;在这里&#xff0c;维数被局限在三个&#xff1a;也就是说&#xff0c;如果维数需要改…

静止轨道卫星大气校正(Atmospheric Correction)和BRDF校正

文章内容仅用于自己知识学习和分享&#xff0c;如有侵权&#xff0c;还请联系并删除 &#xff1a;&#xff09; 目的&#xff1a; TOA reflectance 转为 surface refletance。 主要包含两步&#xff1a; 1&#xff09;大气校正&#xff1b; 2&#xff09;BRDF校正 进度&#x…

抖音矩阵管理系统开发:全面解析与推荐

在数字时代&#xff0c;短视频平台如抖音已经成为人们生活中不可或缺的一部分。随着内容创作者数量的激增&#xff0c;如何高效地管理多个抖音账号&#xff0c;实现内容矩阵化运营&#xff0c;成为了众多创作者关注的焦点。今天&#xff0c;我们就来全面解析抖音矩阵管理系统的…

Java_如何在IDEA中使用Git

注意&#xff1a;进行操作前首先要确保已经下载git&#xff0c;在IDEA中可以下载git&#xff0c;但是速度很慢&#xff0c;可以挂梯子下载。 导入git仓库代码 第一次导入&#xff1a; 首先得到要加载的git仓库的url&#xff1a; 在git仓库中点击 “克隆/下载” 按钮&#xf…

SpringBoot教程(十七) | SpringBoot集成swagger

SpringBoot教程&#xff08;十七&#xff09; | SpringBoot集成swagger 一、Swagger的简述二、SpringBoot集成swagger21. 引入依赖2. 新建SwaggerConfig配置类当 SpringBoot为2.6.x及以上时 需要注意 3.配置Swagger开关4. 给Controller 添加注解&#xff08;正式使用&#xff0…

PCIe 以太网芯片 RTL8125B 的 spec 和 Linux driver 分析备忘

1,下载 RTL8125B driver 下载页&#xff1a; https://www.realtek.com/Download/List?cate_id584 2,RTL8125B datasheet下载 下载页&#xff1a; https://file.elecfans.com/web2/M00/44/D8/poYBAGKHVriAHnfWADAT6T6hjVk715.pdf3, 编译driver 解压&#xff1a; $ tar xj…

鸿蒙OpenHarmony Native API【drawing_color.h与drawing_font_collection.h】 头文件

drawing_color.h Overview Related Modules: [Drawing] Description: 文件中定义了与颜色相关的功能函数 Since: 8 Version: 1.0 Summary Functions FunctionDescription[OH_Drawing_ColorSetArgb] (uint32_t alpha, uint32_t red, uint32_t green, uint32_t blue)u…

机器学习第四十九周周报 GT

文章目录 week49 GY摘要Abstract1. 题目2. Abstract3. 网络结构3.1 graphon3.2 框架概览 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过程4.3.1 有效性4.3.2 可转移性4.3.3 消融研究4.3.4 运行时间 5. 结论6.代码复现小结参考文献 week49 GY 摘要 本周阅读了题为Fine-tun…

几个小创新模型,Transformer与SVM、LSTM、BiLSTM、Adaboost的结合,MATLAB分类全家桶再更新!...

截止到本期MATLAB机器学习分类全家桶&#xff0c;一共发了5篇&#xff0c;参考文章如下&#xff1a; 1.机器学习分类全家桶&#xff0c;模式识别&#xff0c;故障诊断的看这一篇绝对够了&#xff01;MATLAB代码 2. 再更新&#xff0c;机器学习分类全家桶&#xff0c;模式识别&a…

【四】jdk8基于m2芯片arm架构Ubuntu24虚拟机下载与安装

文章目录 1. 安装版本2. 开始安装3. 集群安装 1. 安装版本 如无特别说明&#xff0c;本文均在root权限下安装。进入oracle官网&#xff1a;https://www.oracle.com/java/technologies/downloads/找到最下面Java SE 看到java 8&#xff0c;下载使用 ARM64 Compressed Archive版…

vue3+vite纯前端实现自动触发浏览器刷新更新版本内容,并在打包时生成版本号文件

前言 在前端项目中&#xff0c;有时候为了实现自动触发浏览器刷新并更新版本内容&#xff0c;可以采取一系列巧妙的措施。我的项目中是需要在打包时候生成一个version.js文件&#xff0c;用当前打包时间作为版本的唯一标识&#xff0c;然后打包发版 &#xff0c;从实现对版本更…

五大设备制造商的 200 多种机型的安全启动功能完全失效

2012 年&#xff0c;一个由硬件和软件制造商组成的行业联盟采用了安全启动技术&#xff0c;以防范长期存在的安全威胁。这种威胁是恶意软件的幽灵&#xff0c;它可以感染 BIOS&#xff0c;即每次计算机启动时加载操作系统的固件。从那里&#xff0c;它可以保持不受检测和删除&a…

从零开始学Java(超详细韩顺平老师笔记梳理)08——面向对象编程中级(上)IDEA常用快捷键、包、封装、继承

文章目录 前言一、IDEA使用常用快捷键模板/自定义模板 二、包package1. 基本介绍2. 包的命名规范3. 常用的包和如何引入4. 注意事项和细节 三、访问修饰符&#xff08;四类&#xff09;四、封装Encapsulation&#xff08;重点&#xff09;1. 封装介绍2. 封装步骤3. 快速入门4. …

SpringCloud Nacos的配置与使用

Spring Cloud Nacos的配置与使用 文章目录 Spring Cloud Nacos的配置与使用1. 简单介绍2. 环境搭建3. 服务注册/服务发现4. Nacos 负载均衡4.1 服务下线4.2 权重配置4.3 同集群优先访问 5. Nacos 健康检查5.1 两种健康检查机制5.2 服务实例类型 6.Nacos 环境隔离6.1 创建namesp…

【MySQL进阶之路 | 高级篇】表级锁之S锁,X锁,意向锁

1. 从数据操作的粒度划分&#xff1a;表级锁&#xff0c;页级锁&#xff0c;行锁 为了尽可能提高数据库的并发度&#xff0c;每次锁定的数据范围越小越好&#xff0c;理论上每次只锁定当前操作的数据的方案会得到最大的并发度&#xff0c;但是管理锁是很耗资源的事情&#xff…

驾驭代码的无形疆界:动态内存管理揭秘

目录 1.:为什么要有动态内存分配 2.malloc和free 2.1:malloc 2.2:free 3.calloc和realloc 3.1:calloc 3.1.1:代码1(malloc) 3.1.2:代码2(calloc) 3.2:realloc 3.2.1:原地扩容 3.2.2:异地扩容 3.2.3:代码1(原地扩容) 3.2.3:代码2(异地扩容) 4:常见的动态内存的错误…

vite + xlsx + xlsx-style 导出 Excel

如下 npm i 依赖 npm i xlsxnpm i xlsx-style-vite1、简单的使用&#xff1a;.vue文件中使用 const dataSource ref([]) // 数据源const columns [{title: 用户名,key: userName,width: 120,},{title: 用户组,key: userGroup,width: 120,},{title: 状态,key: enable,width: …

鸿蒙(HarmonyOS)下拉选择控件

一、操作环境 操作系统: Windows 11 专业版、IDE:DevEco Studio 3.1.1 Release、SDK:HarmonyOS 3.1.0&#xff08;API 9&#xff09; 二、效果图 三、代码 SelectPVComponent.ets Component export default struct SelectPVComponent {Link selection: SelectOption[]priva…

浅谈我对RESTful架构的理解

总结说在前面&#xff1a; RESTful API是目前比较成熟的一套互联网应用程序的 API 设计理论&#xff0c;他是一种理论规范&#xff0c;方便不同的前端设备与后端进行通信&#xff0c;在 RESTful 风格的 API 设计架构中&#xff0c;每个网址代表一种资源&#xff08;resource&am…