\u200E
如何基于飞桨打造智能眼镜视觉辅助系统
发布日期:2020-07-08T08:52:19.000+0000 浏览量:11341次
目前中国视障人士数量多达700万,占全世界视障人士总数的18%。此外,全国还有约1200万弱视人群,两者总和约占全国总人口的1.5%。严重的视觉障碍给他们日常生活带来了巨大困难。视障人群需要专人陪同,或借助辅助工具例如导盲杖、导盲犬等才能正常生活。这些传统解决方案,始终存在普及率低、成本高以及使用困难等问题。如何有效助力视障人士日常生活与出行,改善他们的生活质量,是当下全社会亟待解决的问题。
 

图 1 视障人士的困境(图片来自网络)
 
幸运的是,当前广泛使用的手机芯片,不仅具备高效能、超低功耗、开发设计弹性,也满足特殊行业应用的定制系统整合设计需求,因此非常适合用来开发智能出行类产品应用。例如,手机搭配百度端侧推理引擎Paddle Lite,不仅能够加速设备开发,同时能提供设备持续维护、优化的设计弹性,加上目前手机完善的生态链和自身高可靠度表现,可大大降低智能眼镜设备开发过程的风险。此外,通过设计出合理的并行运算机制,可以对人工智能算法进一步优化,特别是那些利用深度学习技术进行训练或推理的场合。百度飞桨支持并行计算,可以很容易设计出符合要求的系统结构;其丰富的程序资源和硬件支持,可以满足更广泛的市场需求。
 
因此,我们基于人工智能技术,开发出一套视觉辅助智能眼镜系统。该系统首先通过百度深度学习平台飞桨进行大规模日常生活环境图像的训练,形成服务于视障人士生活与出行的深度神经网络。接着配合智能眼镜,采用安卓智能手机作为运算核心,使用Paddle  Lite作为智能手机上的人工智能图像推理平台,并导入前述网络配置参数,从而在智能眼镜系统中实现对视障人士的生活和出行提供辅助。
 
用户佩戴上眼镜后,语音告诉眼镜相应的指令,例如,进行物体寻找,通过交互模块,手机端首先将会处理用户的语音信号,并执行相应的指令,与此同时,智能眼镜通过眼镜镜架处的摄像头捕捉周围的环境,通过通信模块传入手机端,手机采用飞桨生成的深度卷积神经网络SSD作为核心算法单元完成画面中的物体检测与识别。获得结果以后,将结果通过交互模块再反馈给用户。
 
01
这个系统是如何实现的?
智能眼镜系统的基本流程如下:

图2 系统基本流程

本系统基于深度学习技术中的深度卷积神经网络(Deep Convolution Neural Network),以目前通用的日常生活环境图像为训练数据集,开发出一套应用于视障人士的智能服务导航系统。本系统的软件核心算法通过飞桨进行卷积神经网络搭建,硬件部分采用安卓智能手机以及配有摄像头的眼镜,利用 Paddle  Lite 进行安卓手机端的开发,完成了如下两方面的设计工作:
 
1. 飞桨深度学习算法设计,即通过飞桨生成用于辅助视障人士日常生活和出行的深度神经网络。
 
2. 安卓程序开发,即读取摄像头图像,使用 Paddle Lite在智能手机上进行神经网络推理等功能开发,最后进行系统测试。
 

图3 利用飞桨和智能眼镜帮助视障人士进行智能导航
 
02
数据图像训练样本
如图4所示,系统中用于训练的样本选用平时常用的生活用品,如水杯,瓶子,自行车,汽车等 20 类图片,其中包含 9963 张标注过的图片,由训练集、测试集、验证集三部分组成,共标注出 24,640 个物体。对于非视觉障碍的人而言,从图中可以直观地分类出这些内容。图像经过初步的预处理,根据数据集中提供的标记信息,传入深度卷积神经网络进行训练。
 

图4 训练样本图片示例
 
03
系统实现
整个系统由三个交互的主题构成:眼镜、手机以及用户,而在具体实现过程中,我们将系统分为如下几个部分:
 
1、通信模块
2、分析模块
3、交互模块
 
其中,通信模块负责连接眼镜上的摄像头进行传输,将视频数据传给手机端,而交互模块则完成实时播报和语音交互。而最核心的则为分析模块,包含SSD深度神经网络,用于完成物体检测与识别,其基本网络结构如图所示:
 

图5 SSD深度神经网络结构
 
SSD算法的特点在于Single Shot,也就是说只要观察一次图片,就能够进行目标检测和识别,因此算法的效率非常高。SSD网络属于典型的回归目标检测算法,具体分为四个步骤:
 
1. 通过深度神经网络提取整个图片的特征。
2. 对于不同尺度的深度特征图设计不同大小的特征抓取盒。
3. 通过提取这些特征抓取盒对应的深度特征图的特征进行目标识别。
4. 在这些识别的结果中通过非极大值抑制选择最佳的目标识别结果。
 
这里的多个特征抓取盒就是多尺度的,换言之,SSD算法的核心思想就是从深度神经网络的不同层来提取特征,并分别利用这些特征进行回归预测。
 
本系统中,涉及到的SSD算法的代码部分如下所示:
 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
def ssd_net(self, scale=1.0):    # 300x300    tmp = self.conv_bn(self.img, 3, int(32 * scale), 2, 1)    # 150x150    tmp = self.depthwise_separable(tmp, 32, 64, 32, 1, scale)    tmp = self.depthwise_separable(tmp, 64, 128, 64, 2, scale)    # 75x75    tmp = self.depthwise_separable(tmp, 128, 128, 128, 1, scale)    tmp = self.depthwise_separable(tmp, 128, 256, 128, 2, scale)    # 38x38    tmp = self.depthwise_separable(tmp, 256, 256, 256, 1, scale)    tmp = self.depthwise_separable(tmp, 256, 512, 256, 2, scale)

# 19x19 for i in range(5): tmp = self.depthwise_separable(tmp, 512, 512, 512, 1, scale) module11 = tmp tmp = self.depthwise_separable(tmp, 512, 1024, 512, 2, scale)

# 10x10 module13 = self.depthwise_separable(tmp, 1024, 1024, 1024, 1, scale) module14 = self.extra_block(module13, 256, 512, 1, 2) # 5x5 module15 = self.extra_block(module14, 128, 256, 1, 2) # 3x3 module16 = self.extra_block(module15, 128, 256, 1, 2) # 2x2 module17 = self.extra_block(module16, 64, 128, 1, 2)

mbox_locs, mbox_confs, box, box_var = fluid.layers.multi_box_head( inputs=[ module11, module13, module14, module15, module16, module17 ], image=self.img, num_classes=self.num_classes, min_ratio=20, max_ratio=90, min_sizes=[60.0, 105.0, 150.0, 195.0, 240.0, 285.0], max_sizes=[[], 150.0, 195.0, 240.0, 285.0, 300.0], aspect_ratios=[[2.], [2., 3.], [2., 3.], [2., 3.], [2., 3.], [2., 3.]], base_size=self.img_shape[2], offset=0.5, flip=True)
    return mbox_locs, mbox_confs, box, box_var
 
为了提升模型性能和加快训练速度,我们在主模型中插入了mobileNet预训练模型,mobileNet模型结构如下:

 

 

在输出层,将softmax作为分类输出函数,损失函数使用交叉熵(cross_entropy)函数,采用在均方根传递算法(RMSprop)上改进的适合比较大规模的适合训练大数据集的阶梯阶梯型的学习率算法,通过反向传播来不断更新模型中的参数,从而使得损失函数逐渐减小来不断优化模型。
 
04
进行SSD网络训练
 
1. 数据准备
 
对于SSD网络的训练,我们选择从ImageNet官网下载PASCAL-2012的图像数据,共计17125张图片。依7:1:2的比例将数据集分为训练集train_dates、验证集validate_date和测试集test_date, 分别放入到"train" 、 "val" 和”test”目录中,供之后使用。

 

2. 模型训练
 
首先从paddle_model中导入采用已经预训练好的mobileNet模型,用train中的60000张图片进行再训练,设置类别数量class_num = 80, batch_size = 256, 在0.1的learning rate下训练100个epoch.  然后以7e-5的decay_rate衰减learning_rate,微调模型参数,再训练100个epoch,最终得到参数收敛的模型,表示训练已完成。
 

图6. SSD网络训练损失与训练迭代次数之间的关系
 
可以看出,在训练过程中,尽管在短时间跨度内,训练误差有着剧烈的波动,但在多次的迭代下,总体呈现下降的趋势,并最终趋于稳定。
 
MobileNet模型链接:
https://github.com/PaddlePaddle/models/tree/release/1.7/PaddleCV/image_classification
飞桨模型库链接:
https://github.com/PaddlePaddle/models
3. 系统模型评估
我们将设计好的眼镜系统进行性能评估,用于进行测试的物体识别的数据集由 VOC07 与我们自己拍摄的目标图像组成。目标检测的场景为视障人士日常生活中会遇到的相关场景进行识别,在本系统前期进行深度学习测试的过程中,采用飞桨所搭建的几种 SSD 卷积神经网络分别具有以下几种测试结果:
 
表1. 模型性能比较

不同网络的资源消耗不同,取得的识别结果也不尽相同。考虑到智能手机的资源情况,我们选择MobileNet SSD 作为核心,其在性能和资源消耗上可以取得很好的平衡。
 
05
Paddle Lite手机端部署
1)模型转化
 
首先,我们需要将训练后的神经网络模型的格式进行转化,使其适用于安卓端。对此,我们采用了百度新推出的为移动端贴身打造的Paddle Lite,不仅能满足以上需求,还能对模型进行压缩,使其更小更快。
 
我们采用百度提供的opt对PC端的飞桨模型转化为移动端的Paddle  Lite模型,在命令行中输入以下代码运行opt进行模型转换:
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
./opt \    --model_dir=<model_param_dir> \    --model_file=<model_path> \    --param_file=<param_path> \    --optimize_out_type=(protobuf|naive_buffer) \    --optimize_out=<output_optimize_model_dir> \    --valid_targets=(arm|opencl|x86|npu|xpu) \    --prefer_int8_kernel=(true|false) \    --record_tailoring_info =(true|false)

2)在安卓手机中使用Paddle Lite执行预测
 
主要流程有:
 
(1)导入baidu.paddle.lite Java库。
(2)利用config.setModelFromFile从路径中读取移动端的神经网络模型,然后将config设置为预测模型predictor的参数。
(3)把一维float数组格式的输入input送入预测模型predictor中。
(4)执行predictor.run运行神经网络进行预测。
(5)最后,将predictor的输出output以一维float数组格式取出。
具体代码如下:
 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
// 导入Java APIimport com.baidu.paddle.lite.MobileConfig;import com.baidu.paddle.lite.Tensor;import com.baidu.paddle.lite.PaddlePredictor;import com.baidu.paddle.lite.PowerMode;
// 1. 写入配置:设置MobileConfigMobileConfig config = new MobileConfig();config.setModelFromFile(<modelPath>); // 设置Paddle Lite模型路径config.setPowerMode(PowerMode.LITE_POWER_NO_BIND); // 设置CPU运行模式config.setThreads(4); // 设置工作线程数
// 2. 创建 PaddlePredictorPaddlePredictor predictor = PaddlePredictor.createPaddlePredictor(config);
// 3. 设置输入数据long[] dims = {100, 100};float[] inputBuffer = new float[10000];for (int i = 0; i < 10000; ++i) { inputBuffer[i] = i;}Tensor input = predictor.getInput(0);input.resize(dims);input.setData(inputBuffer);
// 4. 执行预测predictor.run();
// 5. 获取输出数据Tensor result = predictor.getOutput(0);float[] output = result.getFloatData();for (int i = 0; i < 1000; ++i) { System.out.println(output[i]);}
 
接下来,进行了实际场景测试。人的测试场景效果如图7和图8所示。
 

图7. 测试人物识别(近处场景)
 

图8. 测试人物识别(远处场景)

图9. 眼镜对于物体的检测识别结果
 
图中的方框标识出的物体是通过非极大值抑制进行输出的结果,也即取出SSD网络判断类型置信度最大的方框作为判断结果,实验结果表明,我们所设计的视觉辅助智能眼镜系统可以正确识别出所要检测的物体和目标。
 
06
应用前景
1、社会价值
 
针对全国数量庞大的视障人士同数量有限、成本昂贵的辅助出行方式之间的矛盾,本作品设计并开发了一套基于飞桨的视觉辅助智能眼镜系统。该系统不仅能够帮助那些视障人士识别日常生活中使用的物体,同时还能快速获得出行指示并有效提示行人。对于提高视障人士的生活质量,降低视障人士生活成本、缓解视障人士出行压力等方面着重要意义。
 
2、作品特点
 
另一方面,本系统基于目前人工智能领域比较流行的深度学习技术进行物体图像识别,作品采用飞桨 深度学习平台进行深度卷积神经网络的搭建,飞桨支持算法的高效设计以及深度神经网络的快速搭建,因此可以有效降低那些以往只能依赖人为判断的工作的复杂度,系统通过智能“学习”不同指示标识的特征,从而使得系统对新的出行指示标识能够进行正确的识别、判断。因此,本作品所设计的系统不仅可以用于日常生活物品识别,对于其他一些指示标志识别也具有一定借鉴意义。
 
3、商业价值
 
最后,本作品所设计的系统硬件部分基于安卓智能手机配合智能眼镜,这套硬件组合体积小、功耗低,对于视障人士十分便携。考虑到智能手机的普及程度,本作品所开发的智能眼镜系统便于推广,价格低廉,能够广泛深入到我国的各个地区,特别是偏远、经济不发达的地区,为提高未来视障人士生活质量,出行导航系统的小型化、便携化奠定了良好的基础,此外功耗低也可以满足设备续航能力以及环保节能的需求。
 
更多的实际演示效果可以参看本系统测试版本的视频,网址如下:
https://www.bilibili.com/video/av56580392/
 
注:本文示例代码和视频所使用的是Paddle Lite早期版本,目前最新版本为Paddle Lite v2.3,链接:
https://github.com/PaddlePaddle/Paddle-Lite
 
如果想与更多深度学习同学交流,欢迎加入飞桨官方QQ群:703252161
 
如果在端侧部署中遇到问题,欢迎加入Paddle Lite官方QQ群与开发人员进行技术交流及问题反馈:696965088