超轻量化目标检测网络NanoDet在Android移动端部署(Winodws)
Woodrat
编辑于 2022年08月02日 21:24

原作者开源代码链接:https://github.com/RangiLyu/nanodet

1 NanoDet目标检测模型介绍

    NanoDet是一个速度极快的轻量化Anchor-free目标检测模型,其可以用于在移动端的部署,主要具有以下优势:

⚡ 超轻量级。模型文件只有980KB(INT8)或1.8MB(FP16)。

⚡超级快: 在移动ARM CPU上为FPS达到97(10.23ms)。

高精度。COCO mAPval@0.5:0.95高达34.3,并且能够在CPU上实现实时检测。

训练友好。比其他模型低得多的GPU内存成本。在GTX1060 6G上可以使用batch size的大小为80。

😎易于部署。支持各种后端,包括ncnn、MNN和OpenVINO。同时提供了基于ncnn推理框架的Android演示(在Android的移动端部署)。

2 网络架构

    1) NanoDet的网络结构如下:

NanoDet网络结构

    Nanodet的作者在backbone(骨干网络)部分提供了EfficientNet、MobileNet和ResNet等。本文以作者提供的ShuffleNetV2 1.0x作为backbone(骨干网络),ShuffleNet本身就是一种基于分组卷积的轻量化卷积神经网络。Nanodet作者去掉了ShuffleNet V2的最后一层,将8, 16, 32倍下采样率的特征层(具体参数参见ShuffleNetV2原文https://arxiv.org/abs/1807.11164)分别输入到 PAN结构进行多尺度特征融合。

代码块
JavaScript
自动换行
复制代码
backbone:
      name: ShuffleNetV2
      model_size: 1.0x
      out_stages: [2,3,4]
      activation: LeakyReLU
    fpn:
      name: PAN
      in_channels: [116, 232, 464]
      out_channels: 96
      start_level: 0
      num_outs: 3
复制成功

    这里需要注意的是PAN本质上是FPN的一种改进方法,FPN将高层的语义信息进行上采样并进行横向add操作。而PAN是在FPN后添加了将底层向高层下采样的操作。所以严格地来说,NanoDet的Neck部分是FPN结构+PAN结构。PAN的主要作用是对FPN进行补充,增强网络的定位信息。NanoDet的作者在原始PAN的基础上做了改进,其中上下采样直接使用bilinear双线性插值而不是pooling,这样做可以有效减少计算量。

    2) 损失函数部分Nanodet采用了Generalized Focal Loss (GFL,论文原文https://arxiv.org/abs/2006.04388)。对于如YOLO,NanoDet等单阶段目标检测模型来说,在box的生成阶段,大部分box其实都属于负样本(背景),而正样本(前景,即需要被检测的目标)占比较少。则大量的负样本会主导Loss,使得训练没有足够的实际意义(想象一下网络学到的都是负样本的背景信息,而前景的学习信息很少)。为解决这种正负样本不均衡的问题,retinanet提出了Focal Loss如下:

FL(p)%3D-(1-p_%7Bt%7D%20)%5E%5Cgamma%20log(p_%7Bt%7D)%0A

相比于二分类Cross Entropy Loss (CE,交叉熵损失函数),FL增加了调节因子和参数γ。γ越大,则好分样本(p较大)的Loss越小,使得难分样本的Loss权重更大。同时当γ为0时,FL就是CE。

FL和CE的在不同置信度分类样本的Loss曲线

而FL作为二分类问题中的label非0即1,回归的是狄拉克分布(在除了零以外的点函数值都等于0,而其在整个定义域上的积分等于1)。而对于复杂场景,尤其是一些前景与背景的边界,这种回归方式不够灵活。想象一下一个模糊的前景和背景重叠的边界,使用这种分布显然太单一。

复杂场景下的目标检测的框回归

而GFL则提出了Quality Focal Loss (QFL)和Distribution Focal Loss (DFL)。首先是QFL中,作者提出了定位质量(预测框和groundtruth框的IoU)和分类得分的联合表示。label是动态的0-1,负样本为0,而正样本标签y的取值即为对应的预测框的IoU score。在训练过程中IoU动态值为0-1则QFL表示如下:

其中FL中的调节因子被扩展为预测结果σ和连续的标签y的绝对距离,实验中β=2效果最好

GFL和传统方法的对比

而对于传统的定位的框回归问题(狄拉克分布),作者提出使用积分的方式对框回归进行建模。考虑到提出的General分布一个积分值可能对应着无穷多种形式,影响网络学习的效率。并且真实的分布通常不会距离标注位置太远,所以GFL中又引入了DFL来快速聚焦到标注位置附近的数值。DFL表示如下:

其形式上与QFL的右半部分很类似,含义是以类似交叉熵的形式去优化与标签y最接近的一左一右两个位置的概率,从而让网络快速地聚焦到目标位置的邻近区域的分布中去。

QFL和DFL可以统一地表示为GFL:

假设要预测两个变量yl,yr的概率,满足yl<y<yr

3 Android模型部署

    目前开源的NanoDet部署方法主要有两种。

    首先当然是原作者的官方部署方法:

    1、首先下载github上的NanoDet开源项目。从ncnn库中下载ncnn-android-vulkan.zip(https://github.com/RangiLyu/nanodet/releases/download/v0.3.0/nanodet_m_ncnn_model.zip)。

2、将ncnn-android-vulkan.zip解压缩到demo_android_ncnn/app/src/main/cpp中,或者在 demo_android_ncnn/app/src/main/cpp/CMakeLists .txt 中将ncnn_DIR路径更改为你自己的路径。

以上是我的项目路径,根据自己的情况修改

3、将 NanoDet ncnn 初始模型文件(nanodet_m.param 和 nanodet_m.bin)从 models 文件夹复制到 demo_android_ncnn/app/src/main/assets(需要注意的是nanodet的开源代码的该位置没有assets文件夹,需自己创建)。此外还可以指定yolov5s或yolov4-tiny模型。

模型下载链接https://github.com/RangiLyu/nanodet/releases/download/v0.3.0/nanodet_m_ncnn_model.zip

4、安装Android Studio,用Android Studio打开demo_android_ncnn 文件项目并进行创建。 Android Studio在初次使用时需要配置相关环境。首先设置Android SDK,勾选安卓版本并在SDK tools进行相关配置。NDK需要勾选上,否则无法编译。

将安卓手机连接电脑,将手机设置为开发者模式,并打开USB调试(需要在电脑上安装相关USB驱动)。启动AS中的项目,可在手机上看到NanoDet。

    第二种方法是利用整合好的开源项目进行安装。项目路径:https://github.com/nihui/ncnn-android-nanodet。

1、下载好项目后。依然是先下载ncnn-android-vulkan.zip,这里在作者的readme中给出了相应的下载地址https://github.com/Tencent/ncnn/releases。

2、下载ncnn-YYYYMMDD-android-vulkan.zip或自己为Android构建ncnn‎。将 ncnn-YYYYMMDD-android-vulkan.zip解压到 ‎‎app/src/main/jni‎‎ 中,并在‎‎app/src/main/jni/CMakeLists‎‎‎.txt‎中更改ncnn_DIR‎‎路径为自己的ncnn文件夹路径。这里更简单的操作是下载好相应的ncnn文件(一般下载出来的文件夹会有相应版本名,我的是ncnn-20220216-android-vulkan)。此时在下载的项目的目录的\app\src\main\jni中创建一个空的同名文件夹ncnn-20220216-android-vulkan(根据版本命名),并将原ncnn文件里的文件复制进新建的文件夹,这样可以不对CMakelists进行更改。

3、同理下载https://github.com/nihui/opencv-mobile。依然在\app\src\main\jni中创建相应的opencv文件夹将下载的文件复制进新建的文件夹。最终的结构如下图所示:

4、最后使用Android Studio打开工程,相同方法连接安卓手机(开发者模式)。

Build it and enjoy!

4 模型部署效果

    具体性能根据模型的不同有变化。

官方的可视化界面,非极大值抑制(NMS)和IoU阈值可调

nihui的项目可视化界面,可以切换前后摄像头