MediaPipe 是谷歌在 CVPR2019会议上开源的一个感知和增强现实的框架。该框架基于图,可在移动设备、工作站和服务器上跨平台运行,并支持移动 GPU 加速。

BlazeFace 为其中一个重要的组件,因为检测是绝大多数计算机视觉应用的入口。过往检测算法总是从提升性能出发,即便关注轻量级检测器的文章仍不免要在通用数据集上刷一下榜。而谷歌这篇紧贴实际需求,考虑场景限制条件,打造出一款小而专的人脸检测器。BlazeFace 输入设置为 128×128128 \times 128128×128,仅检测图中较大的人脸。换个角度看,它也可以在局部区域内检测小脸,即不考虑目标交叉情况下的跟踪。

BlazeFace 是一个轻量且性能出色的人脸检测器,为移动 GPU 推理量身定制。它在旗舰设备上的运行速度为200-1000+ FPS。这种超实时性能使其能够应用于任何增强现实管道,该管道需要准确的面部感兴趣区域作为任务特定模型的输入,例如2D/3D 面部关键点或几何估计,人脸特征或表情分类,以及人脸区域分割。BlazeFace 的贡献包括:

  • 一个轻量级的特征提取网络,其灵感来自于 MobileNetV1/V2;
  • 一种对 GPU 友好的 SSD 锚点改良方案;
  • 一种改进的限制分辨率策略替代非极大值抑制。

由于前置和后置相机的焦距以及拍摄物体的典型尺寸不同,BlazeFace 为二者分别建立了模型。除了预测轴对齐的人脸矩形外,BlazeFace 模型还可以生成6个人脸关键点(眼睛中心、耳屏点、嘴部中心和鼻尖)坐标,以便估计面部旋转(滚动角度)。这样可以将旋转的面部矩形传递到视频处理管道的后续特定任务阶段,从而减轻后续处理步骤中显著平移和旋转不变性要求。

BlazeFace 模型构建时考虑下面讨论的四个重要设计因素:

增大感受野
作者注意到深度可分离卷积计算由它们的逐点部分支配。对于 s×s×cs\times s \times cs×s×c 输入张量,k×kk \times kk×k 深度卷积涉及 s2ck2s^2 c k^2s2ck2 次乘加运算,而后续 1×11 \times 11×1 卷积到 ddd 输出通道包含 s2cds^2 c ds2cd 次操作,是深度部分的 d/k2d / k^2d/k2 倍。

在实践中,例如, Apple iPhone X 上的 Metal Performance Shaders 实现,对于56×56×12856\times 56\times 12856×56×128 张量,16位浮点运算中的 3×33\times 33×3 深度卷积需要0.07 ms,而随后从128到128通道的 1×11\times 11×1 卷积为0.3 ms,是前者的4.3倍(由于固定成本和内存访问因素,这不如纯算术运算计数差异那么显著)。

这一观察表明,增加深度部分的核尺寸相对成本小。为达到特定的感受野大小,BlazeFace 在 bottleneck 中使用 5×55\times 55×5 卷积,以增加卷积核大小来减少所需的 bottleneck 数量。如下图所示:

  • 考虑到网络前期 bottleneck 的中间张量通道较少,BlazeFace 设计出与 ResNet 中 BasicBlock 类似的 Single BlazeBlock,以便残差连接在“扩展”(增加)的通道分辨率上执行。

  • 网络深层使用 double BlazeBlock ,降低中间通道的同时进一步加速了感受野大小的增长(参见上面的右图)。

特征提取器
BlazeFace 必须考虑较小范围的目标尺度,才能具备较低的计算需求。前置摄像头模型的特征提取器如表 Table 4所示,采用 128×128128\times 128128×128 像素的 RGB 输入,由一个2D 卷积以及后跟的5个 Single BlazeBlock 和6个 Double BlazeBlock 组成。最大张量深度(通道分辨率)为96,而最低空间分辨率为 8×88\times 88×8(而 SSD 将分辨率一直降低到 1×11\times 11×1)。


锚点方案

通常的做法是根据目标尺度范围在多个分辨率级别定义锚点。积极的下采样也是优化计算资源的手段。典型的 SSD 模型使用来自 1×11\times 11×1、2×22\times 22×2、4×44\times 44×4、8×88\times 88×8 和 16×1616\times 1616×16 特征图大小的预测。然而,池化金字塔网络(Pooling Pyramid Network,PPN)架构的成功意味着在达到某个特征映射分辨率之后,额外的计算可能是多余的。

相对于 CPU 计算,GPU 的一个关键特性是调度特定层计算的显著固定成本,对于流行的 CPU 定制架构固有的深度低分辨率层来说,这一点变得相对重要。例如,在一个实验中,作者观察到,在 MobileNetv1 的4.9ms 推理时间中,只有3.9ms 用于实际的 GPU 着色器计算。

考虑到这一点,BlazeFace 采用了另一种锚点方案:

  • 仅将特征图下采样到 8×88\times 88×8;
  • 用 8×88\times 88×8 中的6个锚点替换原来 8×88\times 88×8、4×44\times 44×4 和 2×22\times 22×2 分辨率中的每个像素对应的2个锚点。
  • 由于人脸长宽比的变化有限,将锚框固定为1:1纵横比。


后处理
由于 BlazeFace 的特征提取器没有将分辨率降低到 8×88\times 88×8 以下,因此与给定目标重叠的锚点数量会随着目标大小的增加而显着增加。在典型的非极大值抑制场景中,只有一个锚点“胜出”并用作最终的算法结果。当将这种模型应用于后续视频帧时,预测倾向于在不同锚框之间波动并且表现出时间抖动(人类可感知的噪声)。

为了最大限度地减少这一现象,BlazeFace 将抑制算法替换为混合策略,该策略将边界框的回归参数估计为重叠预测之间的加权平均值。它几乎不会给原始的NMS算法带来额外的成本。对于这里的人脸检测任务,该调整使精度提高10%。

之前很多人不求甚解,仅根据文中表格创建网络即宣称做出算法的实现。试问检测器没有后处理,仅靠网络能运行吗?细节根本对不上。考虑到谷歌本身就已放出代码,以上不得不令人唏嘘。

WeightedNonMaxSuppression

WeightedNonMaxSuppression 即文中 blending 策略的实现。以加权方式替换原有 NMS 不是首创,但这里的实现和其他方法不完全一样,以分数作为权重进行调和。

IndexedScores 将得分及其索引成对存储。

Detection 可记录检测或跟踪的结果。
跳过分数低于阈值的检测。
Location 维护 LocationData。
OverlapSimilarity 首先从 Location 提取相对框,计算两个 Location 之间的重叠相似性。它假定 Location 中已经有一个相对的框表示,因此不需要帧宽和高度来进一步标准化。

将重叠率大于阈值的检测收集到candidates

    IndexedScores remained_indexed_scores;remained_indexed_scores.assign(indexed_scores.begin(),indexed_scores.end());IndexedScores remained;IndexedScores candidates;output_detections->clear();while (!remained_indexed_scores.empty()) {const auto& detection = detections[remained_indexed_scores[0].first];if (options_.min_score_threshold() > 0 &&detection.score(0) < options_.min_score_threshold()) {break;}remained.clear();candidates.clear();const Location location(detection.location_data());// This includes the first box.for (const auto& indexed_score : remained_indexed_scores) {Location rest_location(detections[indexed_score.first].location_data());float similarity =OverlapSimilarity(options_.overlap_type(), rest_location, location);if (similarity > options_.min_suppression_threshold()) {candidates.push_back(indexed_score);} else {remained.push_back(indexed_score);}}

candidates中的边框和关键点按得分加权取均值。

      auto weighted_detection = detection;if (!candidates.empty()) {const int num_keypoints =detection.location_data().relative_keypoints_size();std::vector<float> keypoints(num_keypoints * 2);float w_xmin = 0.0f;float w_ymin = 0.0f;float w_xmax = 0.0f;float w_ymax = 0.0f;float total_score = 0.0f;for (const auto& candidate : candidates) {total_score += candidate.second;const auto& location_data =detections[candidate.first].location_data();const auto& bbox = location_data.relative_bounding_box();w_xmin += bbox.xmin() * candidate.second;w_ymin += bbox.ymin() * candidate.second;w_xmax += (bbox.xmin() + bbox.width()) * candidate.second;w_ymax += (bbox.ymin() + bbox.height()) * candidate.second;for (int i = 0; i < num_keypoints; ++i) {keypoints[i * 2] +=location_data.relative_keypoints(i).x() * candidate.second;keypoints[i * 2 + 1] +=location_data.relative_keypoints(i).y() * candidate.second;}}auto* weighted_location = weighted_detection.mutable_location_data()->mutable_relative_bounding_box();weighted_location->set_xmin(w_xmin / total_score);weighted_location->set_ymin(w_ymin / total_score);weighted_location->set_width((w_xmax / total_score) -weighted_location->xmin());weighted_location->set_height((w_ymax / total_score) -weighted_location->ymin());for (int i = 0; i < num_keypoints; ++i) {auto* keypoint = weighted_detection.mutable_location_data()->mutable_relative_keypoints(i);keypoint->set_x(keypoints[i * 2] / total_score);keypoint->set_y(keypoints[i * 2 + 1] / total_score);}}remained_indexed_scores = std::move(remained);output_detections->push_back(weighted_detection);}

参考资料:

  • BlazeFace: 亚毫秒级的人脸检测器(含代码)
  • BlazeFace Sub-millisecond Neural Face Detection on Mobile GPUs
  • tkat0/PyTorch_BlazeFace
  • MediaPipe Read-the-Docs
  • Combination Features and Models for Human Detection
  • Object detection via a multi-region & semantic segmentation-aware CNN model
  • 论文笔记 《Object detection via a multi-region & semantic segmentation-aware CNN model》
  • On The Stability of Video Detection and Tracking
  • 200~1000+fps!谷歌公布亚毫秒级人脸检测算法BlazeFace,面向移动GPU
  • 谷歌开源基于 ML 的手部跟踪算法:手机端实时检测,多个手势同时捕捉
  • MediaPipe: A Framework for Perceiving and Augmenting Reality

BlazeFace:一种非典型专用检测器相关推荐

  1. 28 岁退休程序员自述:不是富二代,行政专业出身,非典型程序员

    作者 | LinkedIn 来源 | LinkedIn(ID:LinkedIn-China) 最近,知乎上一个提问"如何看待年仅 28 岁的郭宇宣布从字节跳动退休?"火了,阅读讨论 ...

  2. 数万人的背影|非典型产品经理的生存现状

    品经理A.B.C同学,或许是几万人的背影 A同学是产品经历有3年左右的产品人,从销售.运营.最终转型到产品,经历了不同角色转变,到如今的产品工作日子. 很多朋友问我,从事产品是不是可以决定需求.决定U ...

  3. 一个非典型产品经理的创业心得

    我仍相信我还有机会,用一款产品去证明自己,去兑现童年时代的执念:终有一天,用一个了不起的发明,去影响人类的进程. 前两天,一款叫做zao的app忽然刷屏,主打ai换脸视频,一下子爆到服务器瘫痪. 尽管 ...

  4. 毕业季offer怎么拿?收下这份非典型求职面试指南

    摘要:求职面试莫慌,先自我评估一下 ,华为云专家手把手为你指导. 本文分享自华为云社区<毕业季offer怎么拿?收下这份非典型求职面试指南>,原文作者:技术火炬手 . 又是一年毕业季,对于 ...

  5. 设计模式的C语言应用-非典型模式-第十章

    上一章为止,C语言里显性和隐性的设计模式都已经介绍完了. 非典型模式章节开始介绍23种设计模式里在C语言退化的,不适用的.这些模式在使用中很难想到其实也是一种设计模式,代码的实现也没有什么特点.开发人 ...

  6. 是时候该学会 MMDetection 进阶之非典型操作技能(一)

    目录 前言 1 如何给不同 layer 设置不同的学习率以及冻结特定层 1.1 DefaultOptimizerConstructor 1.2 冻结特定层解决办法 2 如何在训练中优雅地使用多张图数据 ...

  7. Nature子刊:自闭症患者非典型的功能连接梯度

    自闭症谱系障碍(ASD)是一种具有高度复杂行为表型的持续性神经发育障碍.在过去的几十年里,它的概念经历了几次转变.早期的研究方法强调了非典型的感觉加工,而最近的研究集中在高级认知和社会功能的缺陷上,包 ...

  8. 重口味段子齐飞,安全圈大佬说要“出柜”,一场非典型发布会背后的八卦 | 宅客故事...

    一场难忘的发布会的前情回顾 在接到永信至诚和知道创宇的邀请函时,看起来好像确实是一场正经的安全圈发布会,虽然在再三询问下,公关还是支支吾吾,搞得特别神秘,说是要讲一个"走心"的故事 ...

  9. 数学学习缺陷起源于儿童早期额顶叶脑网络的非典型发育

    数学学习缺陷,在国际疾病分类中,将其定义为神经发育障碍(计算障碍).然而,目前还不清楚这些缺陷是如何在早期大脑发育过程中出现的.在这里,我们对没有正式数学学习经验的3-6岁儿童进行了功能和结构性磁共振 ...

最新文章

  1. Struts2文件上传方式与上传失败解决方式
  2. (七)日志采集工具sleuth--分布式链路跟踪(zipkin)
  3. winform 界面库SunnyUI初次使用
  4. 百度地图 key_Android百度地图导航的接入(包含驾车、公交、步行)
  5. 百度世界-“框天地”
  6. python程序员专用壁纸_代码没写完,哪里有脸睡觉!17 张程序员壁纸推荐
  7. 第5章 Python 数字图像处理(DIP) - 图像复原与重建7 - 周期噪声 余弦噪声生成方法
  8. 算法复杂度分析(下):最好、最坏、平均、均摊等时间复杂度概述
  9. arima 预测模型_预测未来:学习使用Arima模型进行预测
  10. java if,if...else...的应用
  11. [leetcode][JAVA]面试题第[1028]题[迭代]
  12. [大数据行业应用发展前景分析] 阿里潘永花报告:大数据产业将成为新的煤和石油介绍...
  13. MySQL数据库反向生成powerdesigner模型
  14. ImageView之android:tint= 属性方法作用详解
  15. xpath定位相邻元素方法
  16. Linux系统死亡之ping,linux下防止syn***,端口扫描和死亡之ping
  17. matlab仿真调速,直流调速系统的MATLAB仿真参考程序
  18. matlab 指数拟合原理,matlab指数增长和阻滞增长拟合代码.doc
  19. 顺丰科技运维开发工程师二面面经
  20. wix log_如何正确地从Wix切换到WordPress(逐步操作)

热门文章

  1. word长公式不换行显示的方法
  2. c 语言len函数,巧妙利用LEN、SUBSTITUTE函数,计算EXCEL单元格内某重复字符个数
  3. UVa10019:Funny Encryption Method
  4. html中怎样隐藏列,关于jquery:隐藏/显示HTML表中的列
  5. vc调用浏览器打开指定网址页面
  6. 微信小程序 09 前后端交互
  7. 13种权重的计算方法
  8. 数据结构与算法笔记:图搜索之DFS详解
  9. php的qq邮箱正则表达式语法_正则表达式综合应用:qq邮箱提取
  10. iOS、mac开源项目及库(转载)