COCO数据集格式、mask两种存储格式、官方包API详解

2023-05-16

文章目录

  • 前言
  • COCO数据集格式
    • 总体组织结构
    • `image对象`的主要属性:
    • `annotation对象`的属性主要:
  • pycocotools包中的COCO对象及API
    • COCO对象的属性
    • COCO对象的方法
  • API源码分析
    • mask保存的格式
    • mask不同的保存格式如何进行可视化
    • `showAnns`函数源码剖析

前言

在前面的文章中我们介绍了如何使用COCO提供的官方API来进行coco格式数据集的可视化,下面我们主要来讲COCO数据集格式官方API实现

COCO数据集格式

coco数据集格式充分利用了面向对象的思路:整个标注文件是一个json对象,这个大的json对象包含几个主要的filed:"info""licenses""categories""images""annotations"。每个filed都是一个数组,里面包含所有的image对象annotation对象。在coco格式中,每一张图片是一个json对象,每一个标注也是一个json对象,所有的对象都用一个唯一的id进行标识。注意,image对象和annotation对象的id是分开来标识的。

总体组织结构

如图所示:
在这里插入图片描述

image对象的主要属性:

  • id:image对象的id
  • file_name: 图片的文件名
  • width: 图片的宽
  • height: 图片的高

annotation对象的属性主要:

  • id: 标注的id
  • image_id: 标注所属图片的id
  • category_id:此标注所属的类别
  • iscrown:是否紧凑,默认为0
  • area:标注的面积
  • bbox:标注的框,左上角x坐标,左上角y坐标,框的宽,框的高
  • segmentation:掩码的标记,有两种格式:多边形格式和RLE格式
  • width: 标注所属图片的宽
  • height: 标注所属图片的高
    在这里插入图片描述

pycocotools包中的COCO对象及API

为了方便可视化COCO格式的对象,官方为我们能提供了pycocotools这个工具包,下面我们来介绍一下这个包下的COCO类.

使用前通过from pycocotools.coco import COCO语句进行导入。

COCO对象的属性

  • self.dataset: 所加载的json文件
  • self.anns:字典类型,保存所有的annotation对象,key是annotation的id,value是标注对象
  • self.cats:字典类型,保存所有的catgory对象,key是catgory的id,value是类别对象
  • self.imgs:字典类型,保存所有的image对象,key是image的id,value是图片对象
  • self.imgToAnns:字典类型,保存所有的image到anno的对应关系,key是图片的id,value是数组对象,保存标注对象,图片与标注是一对多的关系
  • self.catToImgs:字典类型,保存所有的cat到image的对应关系,key是类别的id,value是数组对象,保存图片对象,类别与图片是一对多的关系

COCO对象的方法

所有的方法如下图所示:
在这里插入图片描述

  • getAnnoIds:根据图片id或者类id来得到相应的标注id
  • getCatIds: 得到类别id
  • getImgIds: 根据类别id得到图片id
  • loadAnns: 根据标注Id得到标注对象
  • loadImgs: 根据图片ID得到图片对象
  • showAnnos: 可视化掩码
  • loadRes: 根据预测结果生成对应的COCO对象

总之,有了上面的这些方法,我们在img,anno, catgory 之间形成了一个闭环,三者可以互相转换,如下图:

在这里插入图片描述

API源码分析

下面我们主要分析一下showAnns函数,看一下官方API是如何显示掩码的.

mask保存的格式

再分析源代码之前,我们首先想一下应该如何表示一个mask。mask就是一个不规则的分割结果,那么这个不规则的形状在计算机中应该如何保存呢?

主要有两种格式:多边形表示法RLE压缩表示法

多边形表示法就是将mask边缘的坐标保存下来,类似于图一,COCO数据集中的mask就是以这种形式表示的;RLE是将mask所在的区域进行二值化后,压缩保存,类似于图二,预测结果中的mask就是以这种格式保存的。
在这里插入图片描述
图一
图二
图二

mask不同的保存格式如何进行可视化

首先来说多边形表示法如何转化为二值掩膜。

对于多边形表示法,我们的思路是

  • 1、先初始化一张和原图大小相等的mask,令所有的初值为零
  • 2、取出annos中多边形边缘点的坐标
  • 3、调用cv2.fillPoly()函数进行多边形填充

代码如下:

if 'segmentation' in ann:
   # 如果掩码为多边形格式
   if type(ann['segmentation']) == list:
       polys = []
       # 依次遍历掩码中多个多边形,一个掩膜中也可能包含多个多边形
       for seg in ann['segmentation']:
           poly = np.array(seg, dtype=np.int32).reshape((int(len(seg) / 2), 2))
           polys.append(poly)
       # 多边形填充, mask代表将要填充的初始图,polys存储所有的多边形边界坐标,1代表所填充的值
       cv2.fillPoly(mask, polys, 1)

再来说RLE格式如何转换为二值掩膜。

对于RLE格式的转化,我们可以直接借助官方的APImaskUtils.decode(rle)函数实现,得到的对象直接就是我们想要的二值掩膜。

代码如下:

# 如果掩码为RLE格式
else:
    if type(ann['segmentation']['counts']) == list:
        for seg in ann['segmentation']:
            poly = np.array(seg).reshape((int(len(seg) / 2), 2))
            # polygons.append(Polygon(poly))
            # color.append(c)
        # rle = maskUtils.frPyObjects([ann['segmentation']], t['height'], t['width'])
    else:
        rle = [ann['segmentation']]  # 针对预测结果而言,通常直接走这个分支
    m = maskUtils.decode(rle)
    # 解码后是相同的三通道,我们只取一个通道
    m = m[:, :, 0].reshape((m.shape[0], m.shape[1]))

完整的代码如下,这个函数可以根据image_id和category_id生成对应的二值掩膜:

def get_mask(coco: COCO, image_id, category_id):
	"""
	根据coco对象,image_id和cat_id生成掩膜
	:param coco:
	:param image_id:
	:param category_id:
	:return:
	"""
	image = coco.loadImgs(image_id)
	image = image[0]  # 因为我们只会得到一张特定的图片
	w, h = image["width"], image["height"]
	# 每一类的掩膜
	mask = np.zeros((h, w), dtype="uint8")
	# 找到每一类的掩膜
	anno_ids = coco.getAnnIds(imgIds=image_id, catIds=category_id, iscrowd=None)
	if len(anno_ids) == 0:
	    return mask
	# 得到所有的标注,并依次处理每个标注
	annos = coco.loadAnns(anno_ids)
	for ann in annos:
	    if 'segmentation' in ann:
	        # 如果掩码为多边形格式
	        if type(ann['segmentation']) == list:
	            polys = []
	            # 依次遍历掩码中多个多边形,一个掩膜中也可能包含多个多边形
	            for seg in ann['segmentation']:
	                poly = np.array(seg, dtype=np.int32).reshape((int(len(seg) / 2), 2))
	                polys.append(poly)
	            # 多边形填充
	            cv2.fillPoly(mask, polys, 1)
	
	        # 如果掩码为RLE格式
	        else:
	            if type(ann['segmentation']['counts']) == list:
	                for seg in ann['segmentation']:
	                    poly = np.array(seg).reshape((int(len(seg) / 2), 2))
	                    # polygons.append(Polygon(poly))
	                    # color.append(c)
	                # rle = maskUtils.frPyObjects([ann['segmentation']], t['height'], t['width'])
	            else:
	                rle = [ann['segmentation']]
	            m = maskUtils.decode(rle)
	            # 解码后是相同的三通道,我们只取一个通道
	            m = m[:, :, 0].reshape((m.shape[0], m.shape[1]))
	            idx = np.nonzero(m)
	            mask[idx[0], idx[1]] = 1
	return mask

showAnns函数源码剖析

好了,有了前面知识的铺垫,我们可以来看官方源码了。这里我把注释直接写进了代码中,同学们一定要耐心看完,这样才能有所收获~

def showAnns(self, anns, draw_bbox=False):
    """
    Display the specified annotations.
    :param anns (array of object): annotations to display
    :return: None
    """
    # 判断标注是否为空
    if len(anns) == 0:
        return 0
    # 判断当前任务是否为实例分割或目标检测
    if 'segmentation' in anns[0] or 'keypoints' in anns[0]:
        datasetType = 'instances'
    elif 'caption' in anns[0]:
        datasetType = 'captions'
    else:
        raise Exception('datasetType not supported')
    # 如果当前正在做实例分割或检测
    if datasetType == 'instances':
    	# 导入需要的包
        import matplotlib.pyplot as plt
        from matplotlib.collections import PatchCollection
        from matplotlib.patches import Polygon
		# 获取当前活动的子图对象实例
        ax = plt.gca()
        ax.set_autoscale_on(False)
        polygons = []  # 定义数组,保存多边形掩码
        color = [] 
        for ann in anns:
            c = (np.random.random((1, 3))*0.6+0.4).tolist()[0]
            # 判断是否为分割任务
            if 'segmentation' in ann:
            	# 如果mask的保存格式为多边形表示法
                if type(ann['segmentation']) == list:
                    # 遍历所有的segmentation
                    for seg in ann['segmentation']:
                    	# 获取多边形边界点的坐标
                        poly = np.array(seg).reshape((int(len(seg)/2), 2))
                        # 根据边界点坐标构造Polygon实例
                        polygons.append(Polygon(poly))
                        color.append(c)
                # 如果mask的保存格式为RLE
                else:
                    # 根据image_id得到image对象,主要是为了得到这张图片的宽和高
                    t = self.imgs[ann['image_id']]
                    # 如果是未经压缩处理的RLE格式
                    if type(ann['segmentation']['counts']) == list:
                        rle = maskUtils.frPyObjects([ann['segmentation']], t['height'], t['width'])
                    else:
                        rle = [ann['segmentation']]
                    # 解析rle得到二值掩膜
                    m = maskUtils.decode(rle)
                    img = np.ones( (m.shape[0], m.shape[1], 3) )
                    if ann['iscrowd'] == 1:
                        color_mask = np.array([2.0,166.0,101.0])/255
                    if ann['iscrowd'] == 0:
                        color_mask = np.random.random((1, 3)).tolist()[0]
                    for i in range(3):
                        img[:,:,i] = color_mask[i]
                    # 显示掩膜
                    ax.imshow(np.dstack( (img, m*0.5) ))
            if 'keypoints' in ann and type(ann['keypoints']) == list:
                # turn skeleton into zero-based index
                sks = np.array(self.loadCats(ann['category_id'])[0]['skeleton'])-1
                kp = np.array(ann['keypoints'])
                x = kp[0::3]
                y = kp[1::3]
                v = kp[2::3]
                for sk in sks:
                    if np.all(v[sk]>0):
                        plt.plot(x[sk],y[sk], linewidth=3, color=c)
                plt.plot(x[v>0], y[v>0],'o',markersize=8, markerfacecolor=c, markeredgecolor='k',markeredgewidth=2)
                plt.plot(x[v>1], y[v>1],'o',markersize=8, markerfacecolor=c, markeredgecolor=c, markeredgewidth=2)

            if draw_bbox:
                [bbox_x, bbox_y, bbox_w, bbox_h] = ann['bbox']
                poly = [[bbox_x, bbox_y], [bbox_x, bbox_y+bbox_h], [bbox_x+bbox_w, bbox_y+bbox_h], [bbox_x+bbox_w, bbox_y]]
                np_poly = np.array(poly).reshape((4,2))
                polygons.append(Polygon(np_poly))
                color.append(c)
		# 将多边形放入多边形集合中,如果是RLE格式,那么多边形集合为空
        p = PatchCollection(polygons, facecolor=color, linewidths=0, alpha=0.4)
        # 叠加显示多边形集合
        ax.add_collection(p)
        # 为多边形画边界框
        p = PatchCollection(polygons, facecolor='none', edgecolors=color, linewidths=2)
        ax.add_collection(p)
    # 另一种任务,暂时用不到
    elif datasetType == 'captions':
        for ann in anns:
            print(ann['caption'])
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

COCO数据集格式、mask两种存储格式、官方包API详解 的相关文章

  • Codeforces Round #356 (Div. 1) 题解(待补)

    Bear and Prime 100Bear and Tower of CubesBear and Square GridBear and Chase Bear and Prime 100 This is an interactive pr
  • Centos 7 /local_lim.h:38:26: fatal error: linux/limits.h: No such file or directory

    今天在给一台全新的CENTOS 7 编译 部署GITHUB 项目时遇到如下问题 xff1a In file included from usr include bits posix1 lim h 160 0 from usr include
  • INTEL 傲腾16G 的再利用

    虽然当年INTEL 傲腾上市时自称是 MEMORY xff0c 不过时至2021年 xff0c 把傲腾看成一个 NVME 的SSD就可以了 技术参数 性能测试这些网上已经有很多了 xff0c 不再赘述了 缺点很明显 xff1a 容量太小 x
  • Dell 服务器 用板载网口访问iDrac 并设置风扇静音

    最近需要在办公区域放一台DELL R230 进行测试 xff0c 由于加装了 C2000 pro NVME SSD作为数据盘 xff0c 导致风扇开机后就直奔15000 43 转 xff1b 官方的解释是 xff1a 由于PCIE通道上使用
  • sina 股票接口 2022.1.21 更新

    常年以来 xff0c 作为数据挖掘的一部分 xff0c 作为模拟交易的接口 xff0c 一直使用 sina 的股票接口 http hq sinajs cn 白嫖 xff1b 2022年1月21日 xff0c 这次新浪接口更新后增加了 htt
  • 使用nginx 反向代理 wordpress

    最近需要使用WORDPRESS 建立一个知识库 WIKI xff0c nginx 和wordpress的安装教程网上已经有很多了 xff0c 不再赘述 具体配置参照如下 xff0c 达到效果 xff1a 访问 https www abc c
  • linux 查看CPU 核心温度

    以下命令直接查看CPU 核心温度 echo cat sys class thermal thermal zone0 temp 1000
  • 加速github下载

    前言 由于github 的服务器在海外 xff0c 在国内下载github资源很慢 xff0c 或者无法下载 尤其是最近AI 大火 提供一种加速方式 git config global url 34 https g blfrp cn 34
  • 后ARM时代,嵌入式工程师的自我修养

    1 嵌入式学习的一些概念理解误区 很多嵌入式初学者认为 xff0c 学嵌入式 xff0c 就是学习ARM xff0c 就是学习开发板 买一块开发板 xff0c 然后在上面 移植 u boot Linux内核 xff0c 再使用busybox
  • Linux在shell下输出进度条

    无论下载 xff0c 解压缩 xff0c 复制等情况时 xff0c 我们总能看到进度条这种东西 进度条以图片形式的可视化窗口直观的显示出计算机处理当前任务的速度 xff0c 完成度 xff0c 剩余完成的任务量 xff0c 以及需要的时间等
  • linux ls 按文件大小排序

    ls Sl 其是按照由大到小排序 xff0c 如果想要反过来 xff0c 从小到大 xff0c 那么用 ls Slr 再者 xff0c 如果想要输入是按照 便于人类阅读的方式 xff0c 那么就再加一个 h xff0c 表示 34 huma
  • 常用损失函数

    损失函数汇总 1 目标检测类1 1 分类1 1 1 centerloss1 1 2 arcsoftmax 1 1 3 focalloss 1 2 人脸1 2 1GIOU loss1 2 2 DIOU LOSS1 2 3 CIOU LOSS1
  • xrandr命令用法

    目录 1 常用命令 2 获取其他用法 3 参数选择 1 常用命令 xrandr 作用 xff1a 显示当前显示器可以支持的分辨率 xrandr q 也可以使用 q 参数来查看屏幕目前支持的分辨率 root 64 ubuntu home sa
  • VirtualBox中Ubuntu18.04挂载添加虚拟硬盘

    在ubuntu中挂载一个虚拟硬盘存储在主机硬盘 xff0c 目的是为了防止虚拟机系统崩溃导致数据资料丢失 xff0c 在我们创建完成虚拟硬盘后 xff0c 可以将虚拟硬盘作为所有文件的存放区 想要灵活使用这个虚拟硬盘 xff0c 只需将其挂
  • virtualbox中的Ubuntu18.04版本文件映射win10(虚拟机中Ubuntu安装samba)

    samba是什么 xff1f samba是文件共享服务器 xff0c 一般应用在局域网中 xff0c 能控制共享的权限 xff0c 也能够方便的让用户在客户端和服务端都可以修改文件内容并同步提交 配置samba流程 1 进入root权限 s
  • navicat连接mysql报错1251的解决方法

    在环境变量中添加mysql路径 xff1a 找到下载mysql的文件目录 xff0c 复制并添加至环境变量Path eg C Program Files MySQL MySQL Server 8 0 bin 或者 win 43 r gt s
  • mkdir命令、chmod修改权限、利用scp 远程上传下载文件/文件夹

    一 mkdir命令 在工作目录下 xff0c 建立一个名为 AAA 的子目录 mkdir AAA 在工作目录下的 BBB 目录中 xff0c 建立一个名为 Test 的子目录 若 BBB 目录原本不存在 xff0c 则建立一个 xff08
  • 树莓派 vnc Cannot currently show the desktop

    情况一 xff1a 分辨率没有设置好 解决方案 xff1a 设置分辨率 sudo raspi config 情况二 xff1a 树莓派内存空间不够用 解决方案 xff1a 参考链接二 三 sudo apt get clean sudo ap
  • 基于51单片机的红外避障小车

    提示 xff1a 记录2022年4月做的毕设 文章目录 前言一 任务书1 1设计 研究 目标 1 2设计 研究 内容 二 代码思路三 硬件四 部分代码五 联系我们喜欢请点赞哦 xff01 企鹅号 前言 基于51单片机的红外避障小车 xff0
  • Snipaste的安装及快捷键的设置

    Snipaste的安装及快捷键的设置 关于Snipaste xff1a Snipaste 是一个简单但强大的截图工具 xff0c 也可以让你将截图贴回到屏幕上 xff01 可以将剪贴板里的文字或者颜色信息转化为图片窗口 xff0c 并且将它

随机推荐

  • 并发编程之深入了解CAS

    文章目录 一 什么是 CAS 二 CAS应用三 CAS源码分析三 CAS缺陷四 ABA问题及其解决方案4 1 什么是ABA问题4 2 ABA问题的解决方案 一 什么是 CAS CAS xff08 Compare And Swap xff0c
  • HDU1085 —— 生成函数入门题

    1 43 X i 最经典的生成函数 include lt iostream gt include lt cstring gt include lt algorithm gt include lt vector gt using namesp
  • HDFS每日一练1 API读取文件

    HDFS每日一练1 API读取文件 更多整理都在我的github上 xff1a Auraros欢迎大家 题目 在右侧代码编辑区中编写代码实现如下功能 xff1a 使用FSDataInputStream获取HDFS的 user hadoop
  • 谈谈Java爬虫

    说起网络爬虫 xff0c 大家想起的估计都是 Python xff0c 我在没有接触Java爬虫之前也是只听过python是为爬虫而生 不过俗话说的好 xff1a Java是世界最好的语言 于是我就在网上查询有关于Java爬虫的资料 xff
  • 桌面虚拟化(VDI)的概述

    概述 到目前为止 xff0c 每个人都听说过桌面虚拟化和 VDI 这两个术语 自 2006 年以来 xff0c 我们似乎一直受到来自 VMware Citrix 和 Microsoft 等公司关于这些技术的营销宣传的冲击 但如果桌面虚拟化这
  • 虚拟桌面基础架构 (VDI)及其工作原理

    什么是虚拟桌面基础架构 VDI xff1f 虚拟桌面基础架构 VDI 是一种虚拟化解决方案 xff0c 其使用虚拟机提供和管理虚拟桌面 VDI 将桌面环境托管在一个集中式服务器上 xff0c 并根据请求将其部署到最终用户 可以使用端点设备
  • 数据库修改和忘记密码的解决方法(附详细步骤和操作图)

    数据库修改和忘记密码的解决方法 xff08 附详细步骤和操作图 xff09 修改密码 如果能登录的话就直接修改密码 登录方式 xff1a win 43 R输入cmd 接着输入mysql uroot p xff0c 会提示输入密码 xff0c
  • 初学者如何运用VS打代码?

    1 首先进入VS xff08 我这里以VS2017为例 xff09 如图 xff1a 2 然后选择文件 gt 新建 gt 项目 3 选择Visual C 43 gt 空项目 xff0c 为自己的项目命名 xff0c 例如 xff1a 我的第
  • 2019年中南大学研究生招生夏令营机试题

    2019年中南大学研究生招生夏令营机试题 最小花费 最小花费 题目描述 在n个人中 xff0c 某些人的银行账号之间可以互相转账 这些人之间转账的手续费各不相同 给定这些人之间转账时需要从转账金额里扣除百分之几的手续费 xff0c 请问A最
  • DEBUG模式和配置文件

  • ubuntu vscode 安装插件失败问题

    出现error while fetching extensions xhr failed错误 1 改手机热点 xff0c 2 挂vpn 3 修改网络代理 4 重启vs code 完美解决
  • NVM-Nodejs多版本管理工具

    推荐 当然是我们的大名鼎鼎的 NVM x1f50e 下载点我 下载简单安装版 xff08 推荐 xff09 下载含有 setup的 除了修改位置其他都是下一步安装完成还是不能用我们先下载一个 node 版本 xff0c 使用nvm inst
  • BI数据可视化|可自动刷新的可视化大屏报表

    BI数据可视化大屏和其他的BI报表一样 xff0c 都是可用于日常的决策中 xff0c 因此除了要求数据可视化外 xff0c 也会有自动刷新报表的要求 那么 xff0c 我们该怎么做 xff0c 才能获得一份会自动刷新的BI数据可视化大屏报
  • STM32Min开发板四路可调PWM互补输出

    STM32Min开发板四路触屏可调PWM互补输出 在正点原子的开发例程上 xff0c 结合PWM输出实验和触摸屏实验代码进行修改 定义了几个全局变量存储定时器ARR值和占空比 xff1a u32 F1 span class token op
  • 单点登录CAS(5.2)学习笔记(二)基础配置(HTTP协议,数据库连接,启用登出service参数,密码加密)

    一 打开application properties apache tomcat cas webapps cas WEB INF classes application properties 二 进行配置 默认用户名密码配置 cas aut
  • 使用vscode的git工具进行提交或拉取无效

    使用vscode的git工具进行提交或拉取的时候 xff0c 状态一直在进行中 xff0c 无法实现拉取或提交 具体怎么解决呢 xff0c 我们使用工具的时候比如source tree的时候可以输入账户密码 xff0c 如果他们在电脑的账户
  • DPPO算法(顺便对比PG、TRPO、PPO、PPO2以及A3C算法)

    强化学习 xff08 9 xff09 xff1a TRPO PPO以及DPPO算法 xff1a https blog csdn net zuzhiang article details 103650805 DPPO深度强化学习算法实现思路
  • 你真的弄懂equals()和 == 的区别了吗???

    首先 让我们看看Object类中equals方法源代码如下 Object中的equals方法是直接判断this和obj本身的值是否相等 xff0c 即用来判断调用equals的对象和形参obj所引用的对象是否是同一对象 xff0c 所谓同一
  • conda虚拟环境中安装cuda和cudnn,再也不用头疼版本号的问题了

    文章目录 背景 xff08 为什么 xff09 具体步骤查看conda支持的cuda版本下载cuda安装cuda查看cuda对应的cudnn版本下载cudnn版本安装cudnn 测试安装是否成功安装pytorch测试cuda版本 参考链接
  • COCO数据集格式、mask两种存储格式、官方包API详解

    文章目录 前言COCO数据集格式总体组织结构 96 image对象 96 的主要属性 xff1a 96 annotation对象 96 的属性主要 xff1a pycocotools包中的COCO对象及APICOCO对象的属性COCO对象的