速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

目标检测中的数据标注

  • 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:004620

    评论

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

    技术分享 | 被测项目需求你理解到位了么?

    霍格沃兹测试开发学社

    【Django | allauth】useprofile 用户模型扩展

    计算机魔术师

    8月月更

    【Django | 开发】面试招聘信息网站(快速搭建核心需求)

    计算机魔术师

    8月月更

    【Django | 开发】面试招聘网站(增加csv,excel导出&企业域账号集成&日志管理功能)

    计算机魔术师

    8月月更

    华为云GaussDB践行云原生 带来极致弹性、全域可用和极简体验

    IT资讯搬运工

    软件测试 | 测试开发 | 接口测试之HTTP、HTTPS 抓包分析

    测吧(北京)科技有限公司

    HTTP

    软件测试 | 测试开发 | 使用 cURL 发送请求

    测吧(北京)科技有限公司

    curl

    软件测试 | 测试开发 | 接口测试价值与体系

    测吧(北京)科技有限公司

    接口测试

    【Django | allauth】重写allauth重置密码方法

    计算机魔术师

    8月月更

    【小程序项目开发-- 京东商城】uni-app之自定义搜索组件(下) -- 搜索历史

    计算机魔术师

    8月月更

    软件测试 | 测试开发 | 接口测试中如何使用Json 来进行数据交互 ?

    测吧(北京)科技有限公司

    json

    华为云GaussDB深耕数据库根技术,助力能源行业数字化转型

    IT资讯搬运工

    华为云联合信通院发布业界首个《云原生数据库白皮书》

    IT资讯搬运工

    技术分享 | 软件项目管理与跨部门沟通协作

    霍格沃兹测试开发学社

    软件测试 | 测试开发 | app自动化测试(Android)-- 属性获取与断言

    测吧(北京)科技有限公司

    自动化测试

    helm实战之开发Chart

    程序员欣宸

    Kubernetes Helm 8月月更

    内容小程序化,是在线教育服务推广的最佳格式

    Speedoooo

    小程序 在线教育 移动开发 小程序容器

    主机监控是什么意思?用什么软件好?咨询电话多少?

    行云管家

    运维 主机 主机监控

    NFT系统:数字藏品交易平台app开发功能

    开源直播系统源码

    NFT 数字藏品 数字藏品软件开发 数字藏品开发 数字藏品系统

    云聚华为伙伴暨开发者大会GaussDB专场,与客户伙伴共话金融科技新发

    IT资讯搬运工

    技术分享 | 被测系统架构与数据流分析

    霍格沃兹测试开发学社

    【Django | 开发】面试招聘信息网站(处理产品细节和权限&美化页面样式)

    计算机魔术师

    8月月更

    leetcode 28. Implement strStr() 实现 strStr()(简单)

    okokabcd

    LeetCode 数据结构与算法

    【Django | 开发】面试招聘信息网站(划分面试官权限&集成钉钉消息)

    计算机魔术师

    8月月更

    汽车制造企业如何最大化数据资产价值?

    Kyligence

    数据分析 智能多维数据库

    多线程原理和常用方法以及Thread和Runnable的区别

    共饮一杯无

    多线程 8月月更

    全新EMQX Dashborad:易操作、可观测,集群数据尽在掌握

    EMQ映云科技

    物联网 IoT mqtt emqx 8月月更

    【Django | 开发】面试招聘信息网站(用户登录注册&投在线递简历)

    计算机魔术师

    8月月更

    内网穿透是什么意思?有什么用?用什么软件好?

    行云管家

    运维 内网穿透 内网

    技术分享 | 测试平台开发-前端开发之Vue.js 框架(一)

    霍格沃兹测试开发学社

    技术分享 | 测试平台开发-前端开发之Vue.js 框架的使用(二)

    霍格沃兹测试开发学社

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