分享源码

https://github.com/wjwzy/lip_reading

部分内容参考https://blog.csdn.net/weixin_42907473/article/details/103470208

目录

    • 分享源码
  • 1.摘要
  • 2.项目流程
  • 3.部分代码展示
    • 3.1.代码结构
    • 3.2.demo主程序
    • 3.3.视频切帧
    • 3.4.目标检测模块处理
    • 3.5.图片裁剪
    • 3.6.唇读推理模块预处理
    • 3.7.模型预测
  • 4.核心技术分析
    • 4.1.数据分析
    • 4.2.目标检测算法
    • 4.3.分类网络
  • 5.预处理trick
    • 5.1.数据增广
    • 5.2.帧数填充
  • 6.效果展示
    • 6.1.训练效果
    • 6.2.页面展示效果
  • 7.弱点分析
  • 8.总结

1.摘要

项目主要针对基于视频的计算机唇读系统中唇部检测、唇读特征提取和唇语识别等关键技术进行了研究。具体来说,首先对数据进行预处理,包括对视频进行切帧和增广处理;然后采用Yolov5算法对唇部检测并截取有效区域进行后续处理;接着设计了一个新型网络用于唇部特征的提取和识别。该网络融合了3DResNet和GRU网络,能够同时利用视频数据的空间和时间信息,进而提取高效的特征获得较好的识别结果。最后,为了体现可视化和实用性,本文使用Flask框架实现了唇读系统的各个功能,可以在web端体验唇读系统的识别效果。

2.项目流程

研究的主要内容是对中文唇语词语的识别功能,研究的问题涉及到唇部定位、数据特征提取、网络对特征的预测结果以及web端实现前后端数据交互四个方面。而最为关键的,就在于特征提取以及预测结果两个方面,重点设计可行的深度学习方案,对比各种方法来研究出本文的最佳实现手段。对于模型的鲁棒性和泛化能力,项目需要大量而又无误的数据集支持,以及采用合适该数据集的网络模型,才能保证网络拥有强有力的表现能力。
在系统功能上,用户需要登录成功才能使用唇语识别功能,项目流程如图所示。

在技术路线上,第一个模块是目标检测,该模块需要准确的找到人脸的唇部位置,并且通过预测的坐标对图像进行切割,保证唇部位于图像的最中间位置,项目实现算法为Yolov5算法,采用最小的预训练模型进行训练。在目标检测数据集的制作中,需要保证数据的完整性,并且标注的嘴唇应该位于图像的最中间位置,达到唇部定位的效果,这样可以大程度加快后续分类网络的拟合速度。
第二模块采用的是3DResNet与GRU复合式网络,通过Yolov5算法处理过的数据传入该网络中,残差结构提取特征,GRU保证时序信息的传递与保存,再通过softmax得到预测的结果。在该模块中,训练数据的数量尤为关键,所以在预处理中,使用数据增广让网络有充足的数据训练。其次,网络的结构也非常重要,残差网络ResNet是由多层网络堆叠而成,解决网络深度造成的梯度消失问题,让网络更深,提取到的图像信息特征越多越有效。而循环神经网络RNN的变种体GRU则是通过了门的控制机制,使时序信息得到很好的保留,让神经网络更加关注的是时间序列的唇部动态变化信息。
预测结果最终传入web模块,依靠html和js完成前后端的交互,实现的系统的识别功能。在web模块中,所使用的框架是Flask框架,该框架优点就是轻巧灵活,在登录功能中html直接往后端提交表单,后端只要通过数据库对表单进行校验,就可以完成登录功能。在识别功能中,通过js配合html读取本地视频,再提交到后台进行处理,处理过程首先是经过视频切帧,然后Yolov5模型对帧数图像进行唇部坐标预测,再切割图像并保存,最后通过分类网络得到预测的结果,识别的词语展示到前端页面即可完成整个功能的流程,处理的流程如图所示。

项目采用的技术为当今最主流的one-stage目标检测算法Yolo,用来辅助残差网络ResNet对视频进行唇语翻译,该目标检测算法首次应用于唇语识别中,使系统达到端到端的识别效果。其次数据集是由多帧数图像组成单一样本,存在缺帧等问题,给项目带来了一定的难度。项目还采用了python轻量级web框架Flask,通过前端html和js的配合使用来操作深度学习算法,达到视觉上的展示效果,让用户可以使用网页端操作唇语识别系统。

3.部分代码展示

3.1.代码结构

项目由三部分构成,唇读模块、目标检测模块和web端demo模块,由于目标检测的模型路径问题,将demo和yolov5整合到了一个目录下。

3.2.demo主程序

post请求将前端读取的视频先保存至本地相应目录,再做后续相关操作。

@app.route('/predict', methods=['GET', 'POST'])
def predict():if request.method == 'POST':try:# 读取video文件f = request.files['file']# 保存前端读取的视频到uploadsbasepath = args.save_videofile_path = os.path.join(basepath, secure_filename(f.filename))f.save(file_path)img_list = video_to_frames(file_path)cut_img_list = cut_img(img_list)del img_listvocab_path = 'lip_models/vocab100.txt'# 载入网络进行预测result = model_predict(model, cut_img_list, vocab_path, args.device)result = str(result[0])print("识别结果:" + result)return resultexcept Exception as e:return "错误,无法正确识别"return None

3.3.视频切帧

切帧直接存入list返回

def video_to_frames(path):"""输入:path(视频文件的路径)"""# VideoCapture视频读取类# 抽取帧数videoCapture = cv2.VideoCapture()videoCapture.open(path)# 总帧数frames = videoCapture.get(cv2.CAP_PROP_FRAME_COUNT)img_list = []for i in range(int(frames)):ret, frame = videoCapture.read()if i % 4 == 0:img_list.append(frame)print("视频切帧完成!")return img_list

3.4.目标检测模块处理

重新构建一个类,将加载模型初始化,由于只有一个类别,因此classes为0,定义detect方法,传入参数为图像的list,返回结果为对应坐标的list。

class yolov5(object):def __init__(self,img_size = 416,weights = 'runs/train/exp/weights/best.pt',iou_thres = 0.45,conf_thres = 0.25,device = '0',classes = 0,agnostic_nms = False,augment = False):self.imgsz = img_sizeself.iou_thres = iou_thresself.conf_thres = conf_thresself.device = select_device(device)self.classes = classesself.agnostic_nms = agnostic_nmsself.augment = augment# Initializeset_logging()self.half = self.device.type != 'cpu'  # half precision only supported on CUDA# Load modelself.model = attempt_load(weights, map_location=self.device)  # load FP32 modeldef detect(self, source):stride = int(self.model.stride.max())  # model strideimgsz = check_img_size(self.imgsz, s=stride)  # 检查图片的大小if self.half:self.model.half()  # to FP16cudnn.benchmark = True  # 设置True可以加速恒定图像大小的处理速度# Run inferenceif self.device.type != 'cpu':self.model(torch.zeros(1, 3, imgsz, imgsz).to(self.device).type_as(next(self.model.parameters())))  # run onceresult = []for img0 in source:imgsz = check_img_size(imgsz)  # check img_sizeimg = letterbox(img0, imgsz, stride=32)[0]# Convertimg = img[:, :, ::-1].transpose(2, 0, 1)  # BGR to RGB, to 3x416x416img = np.ascontiguousarray(img)img = torch.from_numpy(img).to(self.device)img = img.half() if self.half else img.float()  # uint8 to fp16/32img /= 255.0  # 0 - 255 to 0.0 - 1.0if img.ndimension() == 3:img = img.unsqueeze(0)# 获取模型预测pred = self.model(img, augment=self.augment)[0]# 使用NMS进行预测pred = non_max_suppression(pred, self.conf_thres, self.iou_thres, classes=self.classes,agnostic=self.agnostic_nms)# 过程检测for i, det in enumerate(pred):  # 遍历预测框# 还原图像坐标值大小det[:, :4] = scale_coords(img.shape[2:], det[:, :4], img0.shape).round()result.append(det[0][:4].tolist())return result

3.5.图片裁剪

目标检测模块得到唇部坐标,然后裁剪保存至新的list中返回。

# 根据预测得到的坐标进行裁剪
def cut_img(img_list):# 进行目标检测得到坐标点result = yolov5_det.detect(img_list)cut_img_list = []for idx, image in enumerate(img_list):labels = result[idx]cropped = image[int(labels[1]): int(labels[3]), int(labels[0]):int(labels[2])]cut_img_list.append(cropped)print("嘴型检测并裁剪完成!")return cut_img_list

3.6.唇读推理模块预处理

def _sample(cut_img_list, bilater = True):data = []for img in cut_img_list:img = img_clip(img)  # 缩放并填充至112大小if bilater and random.random() < 0.6:# 引入双边滤波去噪img = cv2.bilateralFilter(src=img, d=0, sigmaColor=random.randint(15, 30), sigmaSpace=15)# 归一化,转换数据类型 并限定上下界限的大小必须为fixed_sideimg = img.astype(np.float32)# 标准化处理img -= np.mean(img)  # 减去均值img /= np.std(img)  # 除以标准差data.append(img)return np.array(data)

3.7.模型预测

网络输出后获取最大值的下标,结合词表得到预测的唇读词语类别

def model_predict(model, cut_img_list, vocab_path, device):model.to(device)id2label = []with open(vocab_path, 'r', encoding='utf-8') as f:for word in f:id2label.append(word.split(',')[0])# 预处理test_data = process(cut_img_list)test_data = torch.tensor(padding_batch(test_data))print("数据预处理完成!")###############################            预测##############################pre_result = []with torch.no_grad():batch_inputs = test_data.to(device)logist = model(batch_inputs)pred = torch.argmax(logist, dim=-1).tolist()pre_result.append(id2label[pred[0]])return pre_result

4.核心技术分析

4.1.数据分析

在数据方面,项目使用的数据集是2019年“创青春·交子杯”新网银行高校金融科技挑战赛-AI算法赛道的唇语数据集,该数据集是只有图片帧的数据集,整份数据集是由9996份带标签训练样本和2504份无标签预测样本构成,标签文件为txt格式文件,一个样本文件名对应一个中文词语,存储量8GB左右。数据包含的唇语是两个字或者四个字的中文词语,它们的比例为6816:3180,总共有313个类别,除了其中的“落地生根”和“卓有成效”两个类是只有22个样本,其他类别均有32个样本。每个数据样本的帧数由2到24不等,平均帧数在8帧左右,分布比较均匀,图片内容基本都是人脸部的下半部分,如图所示。

图像色度和饱和度都没有太大差异,这样一定程度削减的干扰因素,方便网络能够学习更多的有效特征。
数据可以分为有用信息和无用信息,在这份数据里,开口状态即为有用信息,闭口则是无用信息。因此在数据处理过程,神经网络应该着重注意开口状态的特征,但唇语数据中唇形差异并不大,使得低层数的网络提取不到更多有效的特征,所以在主干网络的选取上为多层数的深度3D神经网络,以便提取更多维度的特征提供网络学习记忆。此外,时间序列的特征信息也尤为重要,仅靠3D网络往往不会有太好的效果,因此项目在分类网络结构中需要引入循环神经网络RNN,它能将最大限度的保留时序特征,非常符合网络对特征的需求。

4.2.目标检测算法

项目对比不同的目标检测算法进行唇部检测,yolov5s、Faster-RCNN、SSD300以及Yolov3-spp这些主流目标检测算法。不同算法与不同模型对同一份数据集的效果肯定都是不一样的,通过试验不同算法在数据集中都进行了不同程度的训练以及测试,整理出了每一个算法在AP-50精度、GPU推理速度、置信度以及模型存储空间四个方面上的性能分析,如表所示。

在项目设计中,目标检测模块需要的仅仅是推理速度上的高相应需求。在参考多份资料以及通过实验结果分析,最终将算法的选择上采取Yolov5算法。

切割目标后:

4.3.分类网络

项目经过几轮测试对比,网络最终修改为ResNet内嵌一层的GRU,同样形成CNN与RNN的复合式网络,但网络并不会单纯使用3D的卷积与池化的结构,因为在特征提取的过程中,更趋向于CNN来提取像素特征,让GRU来提取时间动态变化的特征。因此在残差模块中,卷积和池化将替换成2D操作,这一定程度上能避免时间维度带来的干扰。流程如图所示。

残差模块如下图所示。

由于网络处理的数据是由多帧图像构成的动态变化多维数据,如果仅仅采用3D卷积和池化等操作,会因为下采样过程中使得时间维度数据丢失。从数据集来说,每一个样本的帧数并不恒定,而且是从2帧到24帧不等,数据帧数平均在8帧左右,由于帧数过低,时间维度上的信息本身就存在过少状态。因此当采用3D的卷积与池化后,会进一步缩减该维度上的特征数据,所以网络最终会过分依赖图像的像素两个维度来进行强行拟合,这显然是不合理的。

当残差网络从3D的残差模块更换成2D之后,此时数据中的时间维度并不会进行下采样,所以该维度特征会得到一个很好的保留。所以,为了提取时间维度的特征信息,在网络经过线性全连接之后引入一层门控循环单元GRU,让GRU通过更新门和重置门来控制时间维度特征信息的关联性。在全连接层中,通过输出的特征向量与隐藏层形成线性全连接,使网络融合了残差模块的特征信息来自适应感受向量的临界点,以此来提高网络的自适应表现能力。具体来说就是在线性全连接层中的引入自适应词语边界,不让GRU输出的隐藏层向量直接连接分类层,而是将GRU的每个时间维度的输出连接到全连接层中,在做sotfmax之后再将时间维度相加,最后使得每个时间维度的输出都能为最后的分类层做出贡献,最大化的实现了网络多维度的特征融合。

5.预处理trick

项目选择了100个词语进行研究,也就是100个类别,每个类别32份样本,一份样本平均帧数8帧左右,因此总体数据量有100×32×8=25600张图片左右。
根据标签与文件名生成词表,根据词表的下标对应各个类别。

5.1.数据增广

在图片的预处理中,首先是将图片进行缩放填充至112的像素,并对所有图像进行镜像翻转的数据增强,并对所有图像进行60%概率的双边滤波去噪。如下图所示,a为原图,b是经过缩放、填充、双边滤波后的图像,可以发现相邻的像素变得更加平滑,唇部棱角变得比较立体,图像的阴影更少了,这样很大程度减少了噪声的干扰。c图是镜像翻转的增强图像,可以使数据得到扩充,将3200份样本扩充到6400份。

5.2.帧数填充

由于网络一直过拟合,通过观察数据集,发现这是由于数据集帧数不恒定而产生的。所以在分批次的时候,会产生同一批次帧数不一的情况,这种情况有可能使网络会被帧数的干扰而影响特征提取的效果。因此在预处理阶段,程序划分批次的时候,就需要对每个批次进行0填充再训练,也就是将批次中每个样本的帧数固定到样本最大值,批次中样本统一帧数的形式输入到网络中训练。

6.效果展示

6.1.训练效果

纯3DResnet18+预处理trick训练效果:

3DDensenet+LSTM+GRU+预处理trick训练效果:

3D+2D残差模块+GRU+预处理trick训练效果:

不同预处理手段对比:

6.2.页面展示效果

项目最终成品是页面测试离线视频,从切帧、目标定位切割、网络分类、页面展示结果。

点击Choose按钮选择本地离线视频,选择后出现Predict按钮,点击后进行视频处理,待网络处理完响应请求,并将结果展示至页面,如下图。

7.弱点分析

唇语识别功能的测试中,会存在一个低泛化问题,这是由于数据集产生的。首先数据集中的样本是制作方采样而成,当训练出一个损失低正确率高,并且整体测试集效果比较好的模型时,对自己录制的视频进行切帧并送入网络进行分类,会出现准确率低的情况,这很明显模型对于非数据集的测试样例预测的效果并不是特别好。而模型的泛化能力想要提升,就需要对训练的数据集进行调整,例如增加一些自己的图像,增大每个类别的样本数据,以此提高模型的各项综合能力。
除了泛化问题,还存在相似词语识别混淆问题。例如样本中“技术”和“基础”两个词语,它们之间存在高度相似的动态唇形,测试结果和预想的一样,模型有时会对类似词语无法正确地分类。如下图为系统对录制的“技术”、“基础”两个词语视频识别结果。

在上图中,a图为“技术”词语,b图为“基础”词语,但是网络识别结果却张冠李戴,将两词识别相互混淆。如下图为二词唇部定位切割后的帧数图,首先从唇形上来说二者差异并不大,唯一不同的仅仅是“术”字和“础”字发音时的嚼舌情况不同。然而网络目前仅仅是针对图像的技术处理,并未涉及高层次的语义分析,因此在遇到唇形相似的词语这种情况下,根本无法正确地分辨类别。
混淆词语唇形切割:

在所使用的数据集中,类别的样本数不够很大程度上导致了这种情况产生,不仅如此,唇语识别原本是一个句子输入的过程,前一个字与后一个字的关联性也取决了识别的准确率高低。因此,在现有的基础上要想提高识别效果,首先需要从数据集出发,将过低帧数的样本进行重新采样,抽取高帧数的数据集样本,提高数据集的质量与科学性。同时还需要对网络深度进行修改,增加网络计算参数,让特征在网络中更加细化。其次,应该在网络中引入注意力机制,让网络充分提取开口的像素特征,以及时间维度上帧与帧之间的联系。最后需要设计语义分析模块,将图像转化成语义再对其特征向量做分析处理,细化字与字之间的关联特征,并将数据映射到更高的维度上做到数据再分。

8.总结

针对web端操作下的唇语识别系统,本文主要是使用了两大主流深度学习算法部署到Flask框架的集成思想,对如下内容进行了研究应用:
(1)Yolov5算法对人脸进行唇部定位,采用预测的坐标对数据集进行处理,整理得到图像内容仅包含有效信息的数据集;
(2)在本文所使用的数据集中,对比了不同的目标检测算法与分类网络结构,通过实验数据分析来最终确定选用的算法和网络结构;
(3)设计3DResNet和GRU复合网络,利用2D的残差模块组成深度网进行提取特征,最后利用GRU将每个帧数映射到特征维度中,形成由批次、时序和图像像素的高维度特征信息,再经过全连接层和softmax层处理;
(4)整合两个算法到Flask框架中,这是唇语识别首次应用到web框架中,通过设计路由和URL地址,再配合视图函数对预测算法进行方法调用,让系统达到可视化效果;
(5)对视频流进行预测,充分利用3D模型的优点对唇语视频进行识别,从视频的读取到切帧,最后传入网络中对图像包含的唇语信息进行相关的解码,达到端到端的识别效果。

项目一直存在一些不足的地方,针对这些问题,能从以下方面进行优化:第一是泛化能力,项目后续应该从数据集从发,需要进行一次所有类别的数据采集,以此来扩充样本数目。同时,在网络层数上,可以适当进行加深,以此来增强网络的表现能力,让数据更加细分,模型能学习到更高维度的特征信息。第二是类别数目上,可以扩充至原数据集的313类,让项目能够识别更多的中文词语,让系统不受限于翻译的类别,让更多中文词语甚至短语能够正确的被识别。第三是响应时间里,模型有可能受电脑的硬件设备影响,也有可能是双网络的原因,导致处理时间过长,这应该是项目未来工作的重点研究对象,优化项目的各个细节,提升算法的执行能力。
此外,当前识别的仅仅是词语,真正的唇语识别应该是以句子的形式被翻译的,这就需要对视频进行语句判断,例如开口到闭口的停顿时长,是否可以利用这一点来做句子识别的突破口。在识别功能上,目前仅仅是读取离线视频识别,未来的优化方向也可以向实时视频识别进军,让整个项目更加的智能,更加人性化,攻克唇语识别的这个难题,为将来的唇语工作做出积极的贡献。

Yolov5+Resnet+Flask实现唇语识别系统相关推荐

  1. 唇语识别技术的开源教程,听不见声音我也能知道你说什么!

    作者 | Amirsina Torfi.Seyed Mehdi Iranmanesh.Nasser M. Nasrabadi 译者 | 清爹 整理 | Jane 出品 | AI科技大本营 [导读]唇语 ...

  2. AI如何练就读唇术?唇语识别数据功不可没

    所谓的"唇语识别",其实并不神秘. 早在古代,就有专门的唇语师存在.通过长期的训练,他们具备了"观察别人的嘴型,解读其表达语句"的能力.随着科技的发展,人工智能 ...

  3. 唇语识别真会是语言交互的终极战场?

    文 | 夏汀 来源 | 智能相对论(aixdlun) 在今年的乌镇世界互联网大会上,搜狗展出了一项黑科技--唇语识别,12月14号搜狗在北京又公开演示了这项技术.作为行业领先的唇语识别系统,搜狗在非特 ...

  4. 从人脸识别到唇语识别,图像识别技术发展现状

           "唇语识别研究的起源有一个故事.2006年世界杯上,马特拉齐好像说了一句话把齐达内惹怒了,然后齐达内就用头撞了马特拉齐.事后,大家都在猜他到底说了什么." 山世光 中 ...

  5. 史上最详细唇语识别数据集综述

    更新:VIPL官网网页格式更改,导致旧的LRW1000链接无法访问,现已更新LRW1000数据集链接,内部包含申请需要的文件 推荐一个大佬的综述,关于实现唇语识别的多种途径. 说明:本文包括经常用语唇 ...

  6. 今日新出 CV 论文汇总(含医学图像、目标检测、唇语识别、SLAM等)

    点击我爱计算机视觉标星,更快获取CVML新技术 最近,52CV分享了多篇CVPR 2019 的论文,有位群友问难道除了CVPR 就没有值得读的论文了吗?当然不是,其实很多优秀的工作并不一定出自CVPR ...

  7. 「唇语识别技术」看不透TA的心,但可以听懂TA的话

    导读 唇语识别有着极长的历史.古代的唇语师通过长期的训练,具备了"观察别人的嘴型,解读其表达语句"的能力.在现代社会里,一些听力障碍者们也会使用这种技巧与他人交谈,补充听力器官的不 ...

  8. 清华大学团队研发出新颖唇语解读系统

    文章目录 人说话时嘴唇动作跟语音同步,可以通过识别唇动来进行语言交流.对于声带.喉舌损伤的失声人群,唇语是一种不占用双手的.日常无障碍交流的有效方式.但唇语对讲话者友好,对解读唇语的听众来说却并不轻松 ...

  9. 唇语识别!AI 领域的下一个万亿市场?

    英国查尔斯王子迎娶卡米拉时,读唇者成功破解了伊丽莎白二世与儿子的低语,让女王糟糕的婆媳关系浮现在大众眼前 -- 这可能是"唇语识别"第一次大面积走进大众的视野. 什么是唇语识别 所 ...

  10. 史上最详细唇语识别最新研究进展记录

    本文是唇语识别近2年来最新的方法的记录,主要集中在中英文词级数据集如LRW,LRW-1000,英文句子级数据集如LRS2,英文短语级数据集如OuluVS2,以及其他一些数据集. 记录方法为1.简要翻译 ...

最新文章

  1. maven私服的配置使用
  2. TikTok英国市场你不能不知道的10大数据
  3. Elasticsearch技术解析与实战(四)shardreplica机制
  4. python自动化测试脚本可以测php吗_自动化测试,用Python还是Java?
  5. python查看关键字列表的命令是_Python 41 完整查询语句 和 一堆关键字
  6. 记录一些js面试题以及解法
  7. Robocode:下载安装及迁移至IntelliJ
  8. 细谈等级保护与ISO27000系列的区别与联系
  9. 【产品】 产品设计:ID工业设计、MD结构设计、HW硬件设计和SW软件设计详解
  10. sql删除元组_SQL笔记
  11. 查询加日期oracle,Oracle查询优化日期运算实例详解
  12. pandas批量处理体育成绩
  13. 狼行千里吃肉,马行千里吃草(我读了5遍,震撼了!)
  14. MySQL中show命令用法大全
  15. ATM自动取款机程序设计
  16. mysql 多表 left join_MySql left join 多表连接查询优化语句
  17. Eureka集群启动报错It seems to be a socket read timeout exception
  18. 如何快速有效的学习 Python ?阿里高级开发工程师给出建议
  19. Hibernate学习总结(5)——一对多的级联操作
  20. 推荐一位川大零基础转行 Python 的人生勇士

热门文章

  1. idea 打包不出现target的原因
  2. 计算机考研复试面试常问问题 数据结构篇(下)
  3. 解决 Oracle 密码过期 the password has expired
  4. java mockserver搭建_使用Moco搭建Mock Server教程
  5. golang微信小程序爬虫教程offer秀
  6. 操作系统概念之OSAL
  7. Django下载文件——三种方法和大文件下载
  8. java完成crm系统ppt,客户关系管理系统答辩稿.ppt
  9. cad批量打印快捷键_CAD布局批量打印必备工具之一
  10. 数字图像处理边缘检测算子matlab,使用roberts算子对图像进行边缘检测,并二值化的matlab代码实现...