Yolo系列 & Darknet

0. 前言

  • 本文主要包括两部分内容:
    • 第一部分:介绍Yolo v1/v2/v3 三篇论文的主要内容。
    • 第二部分:介绍DarkNet的使用。

1. 论文笔记

1.1. Yolo v1

  • 参考资料:
  • 素质四连
    • 要解决什么问题?
      • 对于物体检测任务,快速算法的性能低;性能高的算法(如R-CNN系)不能达到实时性的要求。
      • 之前物体检测任务主要分为两个步骤,第一步获取候选区域,第二步队每个分区进行分类。这种方法的性能不能达到实时性要求。
    • 用了什么方法解决?
      • 提出了一种使用回归方式获取候选去的方法,将所有物体检测任务都结合到一个神经网络中。
    • 效果如何?
      • 运行速度大大提高,可以达到45fps。
      • 相比于其他快速物体检测模型,检测结果的准确率有了很大提高。
      • 相比于R-CNN,对于背景的分类结果好了很多。
    • 还存在什么问题?
      • 模型准确率距离其他模型(如Fast R-CNN)还有一定的距离。
      • 在候选边框预测方面(与R-CNN系方法相比),误差较大且对于新数据集的泛化能力较弱。
      • 对于空间聚集较密的数据的预测结果不好。
  • Yolo 系统结构如下:
    • 第一步,resize图片。
    • 第二步,进行图像检测,获取若干候选框以及对应的类别。
    • 第三步,通过NMS筛选第二步得到的候选框。
    • image_1dr2tobdl112msd41k6v7s315e15f.png-562.9kB
  • Yolo 模型思路如下图:
    • 第一步:将图片分为SS个区域,其实就是经过backbone获取SS的特征图。
    • 第二步:通过全连接、卷积等操作,获取 S*S 特征图中每个点的图像检测信息。每个点一共分类依稀和预测 B 个bbox,分类信息是个长度为 C 的向量,每个bbox预测长度为5的向量,所以预测每个点要预测的向量长度为 S*S*(B*5+C)
    • 第三步:进行 post-processing 筛选获取的bbox。
    • image_1dr2s6sp1rb21pkh76jl0o5c1o.png-547.8kB
  • Yolo 网络结构如下图:
    • 网络结构没什么好说的,就提一下中间有全连接层……
    • image_1dr2seome120gl4h8dth3q1kdj45.png-200.7kB
  • Yolo 损失函数如下图:
    • TODO:参考 源码 进一步理解Yolo loss。
    • 首先,对于Yolo中所有损失函数都是以平方差的形式存在。
    • 几个解释:
      • $1_i^{obj}$ 代表网格中存在对象,但不确定是哪个bbox。
      • $1_{ij}^{obj}$ 代表网格i中第j个bbox存在对象。
      • $1_{ij}^{noobj}$ 代表网格i中的j个bbox不存在对象。
      • 几个 $\lambda$ 都是为了平衡大小。
    • 猜测上述内容的计算流程:
      • 第一步:根据gt获取所有有物体的bbox对应的中心点,即选择S*S中的某一个点。
      • 第二步:分别计算GT bbox与选中点中B个候选bbox之间的IOU。
      • 第三步:选择IOU较大的候选bbox作为 $1_{ij}^{obj}$。
      • 第四步:遍历所有GT bbox,除了选中的候选bbox外,其他的均作为 $1_{ij}^{noobj}$。
    • 损失函数分为三个部分:
      • 通过confidence计算损失函数(判断是否有物体)
        • 对应下图中第三行与第四行。
        • 对所有候选bbox都进行计算。
      • 分类误差(确定有物体,判断物体类别)
        • 对应下图中第五行。
        • 只对确定有物体的bbox进行计算。
      • 物体bbox误差(确定有物体,计算x, y, w, h的误差)
        • 对应下图中第一行与第二行。
        • 只对确定有物体的bbox进行计算。
      • image_1dr2sfvhc56q1e6jq6jdfhc3552.png-94.8kB

1.2. Yolo v2

  • 参考资料:
  • 素质四连
    • 要解决什么问题?
      • YOLO v1性能不好,与Faster RCNN的主要区别在于定位误差大,且召回率低。
      • 图像分类数据集较容易获取,数据量多,分类种类也多;物体检测数据集获取难度较大,分类种类太少,无法像数据分类数据集那么丰富。
      • 大多数检测模型只能用于某个特定数据集。 most detection methods are still constrained to a small set of objections.
    • 用了什么方法解决?
      • 从 Better, Faster, Stronger 三个角度对原有的YOLO模型进行优化。详细内容下文再说。
    • 效果如何?
      • 在VOC COCO上达到了state-of-the-art的检测结果。
      • 训练了YOLO9000模型可用于检测超过9000类物体。
      • 达到实时性要求。
    • 还存在什么问题?
      • 这一系列的方法(YOLO SSD YOLO v2)都对小物体、聚集在一起的多个物体的检测结果不佳。
  • Better(基于v1提高模型性能)
    • Batch Normolization: 在网络中添加BN。
    • High Resolution Classifier: 提高输入图片的尺寸:v1是224224,v2中用448448。
      • PS:训练的时候,先用448*448的模型在ImageNet上训练10个epochs,然后再用于目标检测训练。
    • Convolutional with Anchor Boxes & Dimension Clusters: 引入anchors,且利用聚类获取先验边框信息。
    • Direct location prediction: Faster RCNN中bbox的预测形式会导致预测不稳定,所以使用了类似yolov1的bbox表现形式。
      • image_1drggsd02ruu1srg17qj1c8g1pp29.png-87.9kB
    • Fine-Grained Features: 1313的特征图对于小物体来说太小了,所以需要增加特征图信息。这里通过passthrough来实现,即将最后一个pooling前2626512的特征图转换为1313*2048的特征图,然后再与pooling后的特征吃concat,作为后续检测的输入。转换方式如下图。
      • image_1drgi26861mkl1ue39iqmr3o8nm.png-40.8kB
    • 多尺寸训练
  • Faster
    • Darknet-19: vgg很好,但太复杂了,所以设计了Darknet-19。
      • image_1drgii8eqouu1tutk6ts96no113.png-146.3kB
    • 训练过程:
      • 先用224224在ImageNet上训练分类模型,在用448448fine-tune已经获取的模型。
      • 训练检测模型的时候,channels是 num_priors(5num_classes)
  • Stronger:主要就是介绍如何一次分类9000类,不太感兴趣。
  • 损失函数就放上参考文献中的截图:
    • image_1drgivjmr3ss13o6oqd1o3f1p821t.png-89.5kB
    • image_1drgiv8bqs39rvo2rtf446v11g.png-160.4kB

1.3. Yolo v3

  • 参考资料:
  • 素质四连
    • 要解决什么问题?
      • 将一些新的技术添加到yolo中。
    • 用了什么方法解决?
      • 在预测标签时,使用binary cross-entropy而不是softmax。这样在预测多标签任务时很有用。
      • 使用了 Multi-scale predict,类似于SSD,就是在多个尺寸的特征图上都分别检测bbox。
      • 使用了新的darknet结构。
        • image_1drih84r9gm811dn1lre43r1sgu9.png-148.8kB
        • image_1drihd5cm3vldjj1mud1lbtr4sm.png-586.2kB
    • 效果如何?
      • 又快又好。
    • 还存在什么问题?
      • 不太清楚,就感觉很好。

2. DarkNet实践

2.1. 安装

  • 安装方法:进入 darknet 文件夹后直接输入 make 命令即可。
  • 默认安装版本是:CPU版,且不使用OpenCV。
  • GPU版本:修改 Makefile 文件中的内容 GPU=1
  • OpenCV版本:
    • 方法:修改 Makefile 文件中 OPENCV=1
    • 作用:可以使用摄像头,以及所有OpenCV支持的图片、视频文件(本来只支持部分格式)。
  • 采坑:在安装OpenCV版本时老是出现问题。最后重新安装OpenCV解决,但安装时要注意以下几点:
    • 注意OpenCV的版本,建议不要使用3.4.1(存在已知错误),其他版本应该可以。我用当前最新的 3.4.7 成功了。
    • 需要修改OpenCV的安装文件CMakeLists.txt,设置 OCV_OPTION(OPENCV_GENERATE_PKGCONFIG "Generate .pc file for pkg-config build tool (deprecated)" ON )
    • 在安装成功后可能还需要进一步处理,参考这里,即。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      # 修改 /etc/ld.so.conf 文件
      # 即 sudo vim /etc/ld.so.conf
      # 添加内容
      include /etc/ld.so.conf.d/*.conf
      include /usr/local/lib

      # 保存并运行
      sudo ldconfig

      # 修改 /etc/bash.bashrc 文件
      # 即 sudo vim /etc/bash.bashrc
      # 文末添加
      PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
      export PKG_CONFIG_PATH

      # 最后更新配置文件
      source /etc/bash.bashrc

2.2. 直接默认命令

  • 方式就是使用 ./darknet 来进行目标检测。
  • 这里 有详细实例。
  • 举例:
    1
    2
    3
    4
    5
    6
    7
    8
    # 摄像头
    ./darknet detector demo cfg/coco.data cfg/yolov3.cfg yolov3.weights -c 0

    # 检测视频
    ./darknet detector demo cfg/coco.data cfg/yolov3-tiny.cfg yolov3-tiny.weights test.mp4

    # 检测结果保存到视频
    ./darknet detector demo cfg/coco.data cfg/yolov3.cfg yolov3.weights test.mp4 -out_filename out.avi

2.3. 调用Python接口

  • 主要源码位于 这里 中。
  • 有几个要点:
    • DarkNet接口中已经进行了NMS,不需要再自己手动处理。
    • 输入图像是RGB。
    • 脚本中还提供了在图上画bbox的代码。

2.4. V100 测试 YoloV3

环境 推理性能(视频读取+图像预处理+检测) 检测时间(ms)
DarkNet 71.62fps/14.0ms 9.3
TVM + cudnn 40.88fps/24.5ms 18.8
TVM + Auto-tuned 43.95fps/22.8ms 17.4
TensorFlow 28.03fps/36.8ms 28.0
TensorFlow + TensorRT 28.24fps/35.4ms 25.6