今年7月份到9月份在平安科技(上海)实习了一段时间,岗位是人脸识别算法组算法工程师,主要负责采用深度学习进行视频流的唇语识别。平安科技不愧是保险公司,就是有钱,当时组里有四个实习生,我做唇语识别,另外三个人做GAN、声形同步、以及3D目标检测,平均每个人有一台8卡Tesla v100可以用,有充足计算资源自己折腾实验

当时我负责的研究内容是读验证码唇语识别,给定的数据是公司的内部数据,每个样本是一个短视频,里面显示的是不同的人读取数字,实习期间针对这个任务做了一系列的改进 。整体大致流程是:输入视频数据->提取音频->根据音频截取视频中间说话人的部分->从截取视频中抽取固定帧图像->训练

1.数据分析

前期拿到数据首先做了初步的分析,数据比较脏,存在诸多问题:

(1) 噪音较多。背景音比较嘈杂

(2) 方言。导致同一验证码唇形变化不一致

(3) 重复读。一个验证码有的人会读多次

(4) 截断。并没有完整截取视频片段

(5) 唇动不明显。这种情形更多是个人习惯导致

噪音问题会导致我们在截取视频前后片段时的不准确,从而导致采样图片帧出现较大误差,如何从视频中抽取富含信息的图像帧,直接决定了最终模型能够达到的识别精度

2.数据过滤

这一步主要是过滤了一些较短或者较长的视频,根据时间长短筛选视频,通过对筛选出的数据做分析,发现较短的视频基本都是没有读完,而较长的视频,部分是不相关数据,部分是采样时间过长的数据

3.视频截取

由于视频中大多在开始以及结束阶段存在一个空白区域,在这一段时间内视频中人并没有说话,唇形没有发生变化,所以我们需要将视频的开始以及结束阶段都去掉,只截取中间说话的部分,这里我们采用的思路是根据音频来判断说话起止时间,设计了两种算法:

(1) 首先计算音频wav的均值,在时间轴上面找出大于均值的起止时间,然后利用新的起止时间重新计算均值,找到新的起止时间,迭代次数人为设定

(2) 因为我们的验证码都是4个数字,对音频wav做k(k=4)均值聚类,这样可以找到第一个和第四个数字的读取时间

实验中发现,第一种方法速度快,但是精度不高,更加容易受到噪音的影响,截取效果不是很理想,第二种方法虽然截取精度高,但是却非常慢,综合考虑下采用了3次迭代下的第一种算法,也尝试了根据相邻帧之间唇形是否发生变化来判断起止时间,但是时间消耗非常大,无法达到线上使用的要求

为了消除噪音的影响,采用了spleeter,spleeter能够将背景音乐与人声分离,我们将这个库应用在我们的项目中,消除了部分视频中的噪声,进一步提升了视频截取的精度

4.视频抽帧

在探索如何抽取帧以及抽取多少帧这一阶段也做了较多工作,首先是抽帧数量,我们尝试了5-25张(每隔5张),比5更少的话有效信息不足,如果更多的话我们在训练模型的时候成本会增加,但是由于视频截取的不完美,总会出现视频的前几帧或者后几帧冗余的现象,为了增强抽帧的鲁棒性,最终采取的策略是:

每个视频抽取10-25帧图像,然后在开头以及结尾进行padding(copy-paste),最终得到固定的24帧,这样的话就缓解了前后冗余帧的问题

在抽帧策略上面,尝试了均匀采样以及随机采样,均匀采样效果要好一些,因此最终选择均匀采样

5.唇部提取

因为不同视频场景不尽相同,因此视频帧图像无法直接用于唇语识别,需要做进一步提取

初始的思路是手动标注了大约1000张人脸图像,利用yolov3进行人脸(唇部)检测,标注的时候标注的是人脸下颌到鼻子之间的区域,并不包含全部人脸,且保证嘴巴在图片的正中心,训练后的模型切割效果良好

最后的方案是利用dlib68人脸关键点检测算法,检测鼻尖、下颌、左右嘴夹关键点,分别按照比例左右上下进行扩充,检测的效果很好,并且速度也较快

6.模型选择

3D卷积模型

初期采用的是《ECO: Efficient convolutional Network For online video understanding》,这篇文章是3D卷积模型的代表作之一,也是我们首先尝试的模型,模型结构如下:

1.S1到SN是从视频中采样的N帧图像,对于每帧图像,采用权值共享的2D卷积子网络得到96个28*28的feature map,堆叠之后得到一个N*28*28*96的特征volume,到这一步采用的是BN-inception网络中的第一部分(inception-3c层前)

2.对于得到的特征volume,采用一个3D子网络进行处理,直接输出对应类别数量的一维向量,这一部分采用了3D-resnet18的部分层。以上的两个部分,就构成了ECO的网络

2D卷积模型

2D 卷积模型由于其轻量的结构和多元的 backbone 选择,使得其在云端计算和边缘部署上相对 3D 卷积模型具有巨大的优势,但 2D 卷积模型因为时序上的关系很难利用好,各种加如 lstm 等结构的网络还是被 3D 卷积实力碾压,通常情况下如果只考虑精度则不考虑 2D 卷积模型 。但是如果一个模型只使用 2D 卷积,且在分类精度上仍然能达到 SOTA,那么其带来的实用价值是巨大的,是碾压一切 3D 模型的存在。而2019年 ICCV 上的这篇文章《TSM: Temporal Shift Module for Efficient Video Understanding》提出的 Temporal Shift Module 这个模块很好的利用了帧间的时序关系,实现了 3D 卷积的性能且保持了 2D 卷积的相对较小的计算量。最终采用的模型也正是2D卷积网络+TSM模块的结构

如上图所示TSM模块通过沿时间维度移动特征图来执行有效的时间建模,图a是原始的tensor,图b是离线模式所适用的双向TSM将过去和未来的帧和当前帧混合,而图c是在线模式,实时识别,由于不能获取到未来的帧信息,所以仅用过去的帧和当前的帧混合在一起。我们最终采用的是图b的方式。可以看到,仅仅是对部分通道进行了移位,几乎没有额外的其他操作,也意味着没有额外的计算消耗,且没有多余的参数

7.数据增广

对帧图像采样进一步调整,均匀将视频划分为几个片段,然后从每个片段中随机选择一幅图像,以此来增强模型的泛化能力,同时减少计算量。除此之外,我们还增加了随机丢帧的操作,具体做法是对样本图像数量大于一定值(如12)的样本进行随机丢帧,当然帧数小于2且不能为连续帧。另外还加入了图片随机移动,让一组嘴巴并不在一个位置,来增强模型的泛化能力

对于数据增广,我们还采用了一些常规的增广方式:随机加入高斯噪声,随机对图像做双边滤波,随机调图像的明暗度、对比度、饱和度、色度,随机对图像加入小旋转(5°以内),随机对图像做上下左右小平移,随机水平反转操作。这些数据增广操作都是在不损失模型的关键信息的原则上,去告诉模型它应该关注的信息是什么,以此来增强模型的泛化能力

8.模型训练

因为原始的数据是4个数字,如果按照传统方法,这是一个万类分类问题,但是我们数据只有几万条,显然是不够的,因此将视频帧按照前后75%进行切割,做3个数字的分类,也就是1000类,这样模型更加容易收敛

因为我们利用了额外的数据,训练初期出现模型迟迟无法收敛的问题,但是利用在外部数据上面训练的模型进行初始化之后,模型正常收敛,所以很多情况下如果出现模型无法收敛的问题,初始化也是一种良好的解决方案

9.外部数据

采用了一万条中文词语数据,中文成语或者词语相比于数字,唇形变化明显,更加易于区分,通过对不同词语的准确率召回率进行分析,模型训练得到的效果更好,但是经过沟通后在业务上面行不通,因为考虑到很多用户并不认识字,但是数字大部分都是认识的,同理,英文字母验证码的方案也被pass掉了。最终我们采用的评估方案是正样本接受率以及负样本拒绝率,要求在副样本拒绝率90%以上的情况下尽可能提高正样本接受率,最终方案达到93%



实习

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!