写点什么

PyTorch 深度学习实战 | 基于 YOLO V3 的安全帽佩戴检测

作者:TiAmo
  • 2023-03-18
    江苏
  • 本文字数:3822 字

    阅读完需:约 13 分钟

PyTorch 深度学习实战 | 基于YOLO V3的安全帽佩戴检测

本期将提供一个利用深度学习检测是否佩戴安全帽的案例,从而展示计算机视觉中的目标识别问题的一般流程。目标检测是基于图片分类的计算机视觉任务,既包含了分类,又包含了定位。给出一张图片,目标检测系统要能够识别出图片的目标并给出其位置。由于图片中目标数是不确定的,且要给出目标的精确位置,目标检测相比分类任务更复杂,所以也有更多的使用场景,如无人驾驶、智慧安防、工业安全、医学图像等方面。而本案例就是工业安全领域的一个应用,也可移植到其他的目标检测任务。

在一个项目开始时,首先需要明确最终的目标,然后对目标分解,并根据不同目标执行不同的实现方案。本案例较为容易分解出实现目标和实现方式,即通过深度学习中常用的目标检测方法对收集到的图片进行学习,从而得到可以用于结果推断的模型参数。基于这样的目标和方法,首先就需要进行数据收集、处理,然后选择合适的模型以及实现模型的框架。

1、数据采集与标注


数据采集和标注是很重要但繁杂的基础工作,是整个工程的很重要的一个环节。本案例中的数据主要是图片,而图片的选择和标注的质量往往决定着模型的精度,有时候质量太差的数据会导致模型无法收敛。

一般来说,采集图片可以借助于搜索引擎、在实际的业务场景的拍摄和借助已有的数据集三种方式。这些方式各有特点,很多时候需要结合这些方式来完成图片的采集。借助搜索引擎采集的图片在尺寸、内容上会更加丰富,这也意味着会对模型的泛化能力要求更高,但是采集相对简单,可以通过写爬虫的方式进行。而来自实际业务场景的图片或者视频则需要消耗人力和物力去拍摄,而且为了适应不同的时间和地点,拍摄前的规划也是很重要的。这种采集后的图片往往质量较高,规格较为统一,对后续的标注和训练也有很大的帮助。而最常用的一种就是借助已有的数据集,尤其是进行一些小的测试或者试验时。已有的数据集也有不同的类型,包括一些大的计算机视觉比赛发布的数据集,如 PASCAL VOC、COCO 数据集;还有一些人工智能公司发布的数据集,如旷世联合北京智源发布的 Objects 365 数据集;还有个人采集标记的数据集等。不同类型的数据集的质量和数量是不同的,所以要优先选择质量较高的数据集。而且在实际应用时,很有可能只是抽取其中一部分,或者进行二次加工。

通过爬虫获取到的图片,由于图片质量、尺寸、是否包含检测目标等原因,一般是不能直接拿来用的,所以需要对获取到的图片进行过滤处理。当然,通过人工筛选的方式是可以的,但是如果图片数量过于大,就会耗时耗力,所以也可以用一些自动化脚本来进行处理。例如:利用已经训练好的成熟的分类模型对图片进行相似度判断,从而去除相似的图片;利用已经训练好的成熟的人体检测模型去除不包含人的图片等。

技巧/


在使用爬虫获取图片时,一方面可以通过多线程的方式加快爬取速度,另一方面可在设置搜索关键词时只用“安全帽”这样的关键词是不够的,可以多设置一些类似“建筑工地”“建筑工人”等,以扩大搜索范围。而在对图片进行标注时,可以先标注一部分,然后根据这一小部分图片训练出一个粗糙模型,然后使用这个粗糙模型对剩下未标注的图片进行自动标注,然后再进行人工调整,这样会节省较多时间。

本案例使用的个人在 GitHub 上开源的安全帽检测数据集。

该数据集共 7581 张图片,包含 9044 个佩戴安全帽的标注(正类),以及 111514 个未佩戴安全帽的标注(负类)。正类图片主要通过搜索引擎获取,负类图片一部分来自 SCUT-HEAD 数据集。所有的图片用 LabelImg 工具标注出目标区域及类别,包含两个类别标签:hat 表示佩戴安全帽,person 表示普通未佩戴的行人头部。

该数据集采用的是类似 PASCAL VOC 数据集的结构。PASCAL VOC 数据集来自 PASCAL VOC 挑战赛。该挑战赛是由欧盟资助的网络组织的世界级的计算机视觉挑战赛。PASCAL 的英文全称为 Pattern Analysis, Statistical Modelling and Computational Learning。PASCAL VOC 从 2005 年开始举办挑战赛,每年的内容都有所不同,从最开始的分类,到后面逐渐增加检测、分割、人体布局、动作识别等内容,数据集的容量以及种类也在不断地增加。目前,普遍被使用的是 VOC2007 和 VOC2012 数据集两种,虽然是同一类数据集,但是数据并不相容,一般会将两组数据集结合使用。PASCAL VOC 数据集的基本结构代码如下:

由以上结构可以看出,该数据集以文件名作为索引,使用不同的.txt 文件对图片进行分组,而每张图片的尺寸、目标标注等属性都会保存在.xml 文件中。POSCAL VOC 数据集.xml 文件数据格式示例如图 1 所示。对于目标检测任务来说,需要关注的属性就是 filename(图片名称)、size (图片尺寸)、object 标签下的 name(目标类别)和 bnbox (目标的边界框)。

■ 图 1 POSCAL VOC 数据集.xml 文件数据格式示例

2、模型选择

在实际的应用中,目标检测模型可以分为以下两种:

一种是 two-stage 类型,即把物体识别和物体定位分为两个步骤,然后分别完成。其典型代表是 R-CNN 系列,包括 R-CNN、Fast R-CNN、Faster-RCNN 等。这一类型的模型相对来说识别错误率较低,漏识别率也较低,但相对速度较慢,无法满足实时检测场景。

为了适应实时检测场景,出现了另一类目标检测模型,即 one-stage 模型。该类型模型的典型代表有 SSD 系列、YOLO 系列、EfficientNet 系列等。这类模型识别速度很快,可以满足实时性要求,而且准确率也基本能达到 Faster R-CNN 的水平。尤其是 YOLO 系列模型,可以一次性预测多个 Box 位置和类别的卷积神经网络,既能够实现端到端的目标检测和识别,同时又能够具有基于该模型的各种变型,适用于各种场景,所以本案例选用 YOLO V3 模型作为实现模型。但是需要注意的是,在实际项目中要根据业务场景进行选择,例如是否要求实时性、是否要在终端设备上等。而且为了得到更好的效果,往往会对多个模型进行尝试,然后进行对比。


3、数据格式转换


有时候,数据集的格式与模型读取所需要的格式并不相同,所以可以通过写脚本来进行格式转换。类似 PASCAL VOC 类型的数据集,会以目录区分训练数据集、测试数据集等,这种形式不但读取复杂、慢,而且占用磁盘空间较大。而 TFRecord 是 Google 公司官方推荐的一种二进制数据格式,是 Google 公司专门为 TensorFlow 设计的一种数据格式,内部是一系列实现了 Protocol buffers 数据标准的 Example。这样,就可以把数据集存储为一个二进制文件,从而可以不用目录进行区分。同时,这些数据只会占据一块内存,而不需要单独依次加载文件,从而获得更高的效率。所以,需要将 PASCAL VOC 格式的数据转换为 TFRecord 类型的数据。相对应的转换代码和注释如代码清单 1 所示。

代码清单 1


import osimport osimport hashlib from absl import app,flags,loggingfrom absl.flags import EIAGSimport tensorflow as tfimport lxml.etreeimport todmfrom PIL import Image # 设置命令行读取的参数flags.DEFINE string('data dir','../data/helmet VOC2028/13'path to raw PASCAL VOC dataset')flags.DEFINE enum('split','train',[16'train','val'],'specify train or val spit')flags.DEFINE string( output file',../data/helmet VOC2028 train-h.tfrecord'outpot dataset')flags.DEFINE string('classes''../data/helmet VOC2028.names',classes file')# 创建 TERecords 所需要的结构def build example(annotation,class map) :# 根据 xml 文件名找到对应的 jpg 格式的图片名filename = annotation[ 'xml filename'].replace( '.xml',.jpg',1)img path = os.path.join(FLAGS.data dir,JPEGImages',filename)# 读取图片,可以通过设置大小过滤掉一些比较小的图片image = Image.open( img path)if image.size[ 0] < 416 and image.size[1] < 416:print("Image ",filename," size is less than standard:"image.sizereturn Noneimg raw = open( img path,'rb') .read()key = hashlib.sha256( img raw).hexdigest()width = int(annotationl'size']l'width'])height = int(annotation[ 'size'][ 'height'])xmin = []ymin = []xmax =[]ymax = []classes = []classes text = []truncated =views = []difficult obj = []# 解析图片中的目标信息if 'object'in annotation:for obj in annotation['object']:difficult = bool(int(obj['difficult']))difficult_obj.append(int(difficult))xmin. append( float(obj[ 'bndbox'][ 'xmin']) / width)ymin. append(float(obj[ 'bndbox'][ 'ymin']) / height)xmax.append(float(obj[ 'bndbox'][ 'xmax']) / width)ymax. append( float( obj[ 'bndbox'][ 'ymax']) / heightclasses_text.append( obj[ 'name'].encode( 'utf8'))classes.append(class map[ obj[ 'name']])truncated.append(int(objl[ 'truncated']))views.append(objl 'pose'].encode( utf8'))# 组装 TERecords 格式example = tf.train.Example(features = tf,train,Features(feature = ('image/height': tf.train, Feature( int64 list = tf.train, Int64List(valueheight ]))image/width': tf.train, Feature( int64 list = tf.train.Int64List(value[ width]) )image/filename': annotation['filename']. encode( utf8') ]))image/source id': tf.train.Feature(bytes list = tf.train,BytesList(value =annotation'filename'].encode( "utf8 )......)))return example# 解析 xml 文件def parse xml(xml) :if not len(xml) :return (xml.tag: xml. text)
复制代码


发布于: 刚刚阅读数: 2
用户头像

TiAmo

关注

有能力爱自己,有余力爱别人! 2022-06-16 加入

CSDN全栈领域优质创作者,万粉博主;阿里云专家博主、星级博主、技术博主、阿里云问答官,阿里云MVP;华为云享专家;华为Iot专家;亚马逊人工智能自动驾驶(大众组)吉尼斯世界纪录获得者

评论

发布
暂无评论
PyTorch 深度学习实战 | 基于YOLO V3的安全帽佩戴检测_数据采集_TiAmo_InfoQ写作社区