NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

目标检测中的数据标注

  • 2020-12-18
  • 本文字数:3688 字

    阅读完需:约 12 分钟

目标检测中的数据标注

随着人工智能行业的发展,深度学习中的神经网络结构越来越复杂。众所周知深度学习是数据驱动的,日益复杂的神经网络模型需要更多的训练数据作为底层的支撑。理论上,在算力满足要求的前提下,模型效果会随着数据数量的增多而变好。实践证明,在基于深度学习的应用开发过程中,数据规模和标注数据的质量是算法研发的关键因素。本文重点介绍目标检测中的数据标注流程以及如何制定标注规则。

一、标注通用规则


数据标注是通过人工把需要识别和分辨的数据贴上标签。深度神经网络学习这些标注数据的特征,最终实现自主识别的功能。下面介绍几个目标检测中的标注通用规则:


  • 1、贴边规则:标注框需紧贴目标物体的边缘进行画框标注,不可框小或框大。



  • 2、重叠规则:当两个目标物体有重叠的时候,只要不是遮挡超过一半的就可以框的(遮挡范围需要根据算法识别情况制定),允许两个框有重叠的部分。如果其中一个物体挡住另一个物体一部分,框的时候就需要对另一个物体的形状进行脑补完整然后框起来即可。



  • 3、独立规则:每一个目标物体均需要单独拉框,比如下图中三瓶水不能只拉一个框,而是要将三个目标分别拉框。



    • 4、不框规则:图像模糊不清的不框,太暗和曝光过度的不框,不符合项目特殊规则的不框。



    • 5、边界检查:确保框坐标不在图像边界上,防止载入数据或者数据扩展过程出现越界报错。



    • 6、小目标规则:不同的算法对小目标的检测效果不同,对于小目标只要人眼能分清,都应该标出来。根据算法的需求,去决定是否启用这些样本参与训练。

    二、项目数据标注流程


    目标检测数据标注流程分为以下几步:


    • 确定标注规则;

    • 标注人员试标注;

    • 对标注数据检查;

    • 训练模型;

    • 利用模型进行预标注;

    • 根据预标注结果补充标注。


    下面我们通过项目详细介绍数据标注的完整流程。该项目是利用目标检测算法将图像中的光盘和非光盘分别识别出来,助力光盘活动。


    • 1、确定标注规范

    • 在制定标注规范时,我们要对待识别图像进行观察,提取图像中某些共有的特征作为检测类别,对于不明确的类别,需要结合实际场景进行细分。这样,当需要合并某些类别时候,可以直接通过程序把细分类别合成一个类别进行训练。在项目中主要的需要识别场景如下图:



    我们根据识别场景来确定光盘的标准,通过分析得出以下几种情况可认为是光盘。第一种,干净的碗盘;第二种,碗盘中留有食物的汤水(比如说面汤,菜汁),残渣,尖椒段、生姜等你觉得不需要吃掉的内容;第三种,碗盘中留有食物,剩下东西是一小口能吃完。特别需要注意,此次标注只关注盛放食物的碗盘不关注托盘。



    标注时候需要将图片所有碗盘利用标注工具画上矩形框,注意矩形框必须贴合所标注的碗盘,标签根据图像内容是否符合光盘标准选择光盘非光盘。特别的对于遮挡情况标注时需要脑补完整后画上矩形框,如下图示例中淡绿色矩形框代表光盘,灰色矩形框代表非光盘。



    • 2、试标注,并进行标注检查

    有了清晰的标注规则和标注用例,需要向标注人员详细的讲解标注规则,过程中需要详尽列举出标注正确和错误用例。有了对标注规则的清晰理解,标注人员就可以进行试标注了。在大概标注到 100 张图片时候需要进行标注检查。


    对标注检查需要从以下几个方面进行:


    • 标注正确率:检查被标注的目标的标签类别是否正确,由于我们标注工具对于不同标签分配不同的颜色,可以很迅速的检查标注类别的正确率。

    • 标注精确度:检查标注框是否完整贴合目标,是否存在标注框过大或者过小情况。

    • 标注完备性:检查重叠或者部分被遮挡的目标是否存在漏标,或者重复标注情况。


    • 3、训练模型,预标注,标注效果反馈


    一般来说,各个标签的目标框大致有 2000 个时候基本上就可以训练出有一定效果的模型了。在图像中因为一张照片中包含多个目标,在标注到 1000 张左右时候我们就开始训练模型,随后通过训练好的模型对 500 张未标注的图片进行识别(具体数目可以根据任务总量来定),将识别结果转化为标注生成的 voc 数据集通用的 xml 文件。具体代码如下:


    from lxml.etree import Element, SubElement, tostring#转化识别框为标注框def getObject(node_root,xmin, xmax, ymin, ymax, lable):    node_object = SubElement(node_root, 'object')    node_fixed = SubElement(node_object, 'name')    node_fixed.text = lable    node_pose = SubElement(node_object, 'pose')    node_pose.text = 'Unspecified'    node_truncated = SubElement(node_object, 'truncated')    node_truncated.text = '0'    node_difficult = SubElement(node_object, 'difficult')    node_difficult.text = '0'    node_bndbox = SubElement(node_object, 'bndbox')    node_xmin = SubElement(node_bndbox, 'xmin')    node_xmin.text = str(xmin)    node_ymin = SubElement(node_bndbox, 'ymin')    node_ymin.text = str(ymin)    node_xmax = SubElement(node_bndbox, 'xmax')    node_xmax.text = str(xmax)    node_ymax = SubElement(node_bndbox, 'ymax')    node_ymax.text = str(ymax)
    def iniXml(filename,filePath,width , height): x,y,z,w, = filePath.rsplit("/",3) node_root = Element('annotation') node_folder = SubElement(node_root, 'folder') node_folder.text = z node_filename = SubElement(node_root, 'filename') node_filename.text = filename node_source = SubElement(node_root, 'source') node_database = SubElement(node_source, 'database') node_database.text ='Unknown' node_database.text ='The VOC2007 DatabaseUnknown' node_database = SubElement(node_source, 'annotation') node_database.text =' PASCAL VOC2007' node_database = SubElement(node_source, 'image') node_database.text ='flickr' node_size = SubElement(node_root, 'size') node_width = SubElement(node_size, 'width') node_width.text = str(width) node_height = SubElement(node_size, 'height') node_height.text = str(height) node_depth = SubElement(node_size, 'depth') node_depth.text = '3' node_segmented = SubElement(node_size, 'segmented') node_segmented.text = '1' return node_root
    num = input(r'num:')image_root = 'xxx/images/rmb_'+numfileList = os.listdir(image_root)for file in fileList: filePath = image_root + os.sep +file data = { "img":filePath, "algorithmLabel":"xx", "imgDataType":2 } headers = {"Content-Type": "application/json"} res = requests.post("http://ip:port/", data=json.dumps(data), headers=headers) lableList = res.json().get("data") img = Image.open(filePath) width , height = img.size[0],img.size[1] if len(lableList)!=0: node_root = iniXml(file,filePath,width , height) for lableinfo in lableList: xmin, xmax, ymin, ymax, lable = getInfo(lableinfo) getObject(node_root, xmin, xmax, ymin, ymax, lable) xmlroot = '/home/ap/vrc/label-img-tools/_xml/rmb_'+numif not os.path.exists(xmlroot): os.makedirs(xmlroot)xmlPath = xmlroot+os.sep+file.split(".",1)[0]+".xml"## Write document to filewith open(xmlPath,'wb') as f: f.write(etree.tostring(node_root, pretty_print = True, xml_declaration = True, encoding='UTF-8', standalone="yes"))else: continue
    复制代码


    预标注后,我们可以将图片和标注生成 xml 文件放到标注工具上,便可直接在标注界面查看模型识别的效果。对预标注内容进行标注检查,可以发现试标注的不足之处。


    • 4、预标注检查,补充标注

    在通过模型预标注之后,我们需要检查预标注结果以此来挖掘试标注的不足之处,随后根据不足之处进行补充标注。在此项目中检查发现预标注中非光盘存在很多漏标注情况,于是安排标注人员在预标注基础上进行补充标注。


    • 5、循环迭代

    补充标注完成后按照上述的三个检查方面对 500 多张图像的标注数据检查。随后利用该数据进行增量训练得到新模型;通过新模型对其他未标注部分图片进行预标注,标注人员对预标注数据进行修改完善。然后循环迭代模型增量训练——预标注——补充标注过程,直到得到好的模型效果。



    三、总结


    当遇到目标检测需求,标注的流程是这样的:确定一个标注规则——试标注——对标注数据进行检查——训练——预标注效果反馈——补充标注——…


    整个流程中标注规则制定尤为重要,需要总结业务提供的图像数据,确定标注类别和标签。对于不明确的类别需要实际场景进行细分,当需要合并某些类别时候,可以直接通过程序把类别合成一个类别进行训练。同时,标注的规则要尽可能地详尽;需要给出文档和样例。此外,在试标注和正式标注过程中遇到不确定情况时,需要及时进行沟通,否则可能会影响到整体标注质量。


    本文转载自:金科优源汇(ID:jkyyh2020)

    原文链接:目标检测中的数据标注

    2020-12-18 07:004103

    评论

    发布
    暂无评论
    发现更多内容

    目前青岛只有一家正规等保测评机构吗?在哪里?

    行云管家

    青岛 等级保护 等保测评

    “AI Earth”人工智能创新挑战赛:助力精准气象和海洋预测Baseline[1]、NetCDF4使用教学、Xarray 使用教学,针对气象领域.nc文件读取处理

    汀丶人工智能

    人工智能 数据挖掘 机器学习 深度学习 6 月 优质更文活动

    【618备战巡礼】“三高”之第一高--如何打造高可用系统 | 京东云技术团队

    京东科技开发者

    高可用 集群 高可用架构 618 企业号 6 月 PK 榜

    原来kafka也有事务啊,再也不担心消息不一致了

    做梦都在改BUG

    Java kafka 事务

    直播app源码开发的稳定控制知识

    山东布谷科技

    软件 App 开发 搭建平台 直播app系统

    干货 | Mysql binlog插件三种数据采集模式介绍

    大河

    MySQL 数据采集 Binlog bboss

    Springboot3 + SpringSecurity + JWT + OpenApi3 实现认证授权

    京茶吉鹿

    spring security springboot OpenAPI JWT

    “AI Earth”人工智能创新挑战赛:助力精准气象和海洋预测Baseline[3]:TCNN+RNN模型、SA-ConvLSTM模型

    汀丶人工智能

    人工智能 数据挖掘 机器学习 LSTM 6 月 优质更文活动

    只见新人笑,不见旧人哭 ChatGPT淘汰了多少产品?快来了解!

    加入高科技仿生人

    人工智能 AI 低代码 ChatGPT

    时序数据库 openGemini 线下meetup · 北航站来啦,欢迎大家报名!

    华为云开源

    数据库 前端

    电动车厂家会生产制造共享电动车吗?

    共享电单车厂家

    共享电动车厂家 共享电单车生产 本铯电动车厂家 电动车生产厂家

    容器化部署四大优势简单说明-行云管家

    行云管家

    容器化 部署 IT运维 容器化部署

    ChatGPT与软件架构(5) - 网络安全

    俞凡

    人工智能 架构 网络安全 ChatGPT

    “AI Earth”人工智能创新挑战赛:助力精准气象和海洋预测Baseline[2]:数据探索性分析(温度风场可视化)、CNN+LSTM模型建模

    汀丶人工智能

    人工智能 数据挖掘 机器学习 LSTM RNN回归 6 月 优质更文活动

    20个Golang片段让我不再健忘 | 京东云技术团队

    京东科技开发者

    Java Go 语言 企业号 6 月 PK 榜

    软件测试/测试开发丨接口测试学习笔记分享

    测试人

    程序员 软件测试 协议 接口测试 http和https

    制作Jdk镜像

    tiandizhiguai

    Docker k8s 镜像

    flutter系列之:做一个会飞的菜单

    程序那些事

    flutter 架构 程序那些事

    #架构实战营# 模块1 作业

    Zz

    架构实战营 学生管理系统架构

    NineData x 华为云正式上线

    NineData

    数据库 华为云 企业动态 语言 & 开发 NineData

    学习MyBatis的异常处理机制

    做梦都在改BUG

    Java mybatis

    响应式编程的复杂度和简化

    阿里技术

    响应式编程

    质量内建实践的八大特质

    老张

    质量保障 质量内建

    INFINI Easysearch 完成龙芯架构兼容性认证

    极限实验室

    搜索引擎 国产化 龙芯 easysearch 极限科技

    2023秋招,Java岗最全面试攻略,吃透25个技术栈Offer拿到手软

    架构师之道

    java面试

    BH1750 传感器实战教学 —— 硬件设计篇

    矜辰所致

    传感器 硬件设计实战 光照传感器 6 月 优质更文活动

    基于 prefetch 的 H5 离线包方案 | 京东云技术团队

    京东科技开发者

    ios H5 andiod prefetch_related 企业号 6 月 PK 榜

    浅谈ByteHouse Projection优化实践

    字节跳动数据平台

    OLAP Clickhouse bytehouse

    凝聚全球顶尖力量,助力开源行业发展 | 2023开放原子全球开源峰会开幕式暨高峰论坛亮点抢先看!

    开放原子开源基金会

    开源

    阿里Java调优笔记爆火,7大模块优化实战,请查收

    做梦都在改BUG

    Java 性能优化 性能调优

    原来kafka也有事务啊,再也不担心消息不一致了

    JAVA旭阳

    kafka

    目标检测中的数据标注_大数据_金科优源汇_InfoQ精选文章