Overview
I read some paper about object detection, and I have some ideas. I prepare to study the source code of some models.
The YOLO is the first method I had used. As a start, I will try to understand YOLO's code. It's time consuming to read darknet because it was based on C to develop. So I find a project on Github which is a keras implementation of YOLOv3(Tensorflow backend).
This article will include:
- analyse the keras-yolov3
- convert
- yolo_video
- yolo
- model
- argparse基本使用
analyse the keras-yolov3
在项目的readme中有基本的使用和训练指南,下载yolov3.weight,使用convert.py,将权重转成keras的.h5文件。
然后使用yolo_video.py进行检测。
所以我从convert.py和yolo_video.py入手,进而对整个系统进行剖析。
convert.py
- 读取各种参数
- 用assert验证配置文件、权重、输出.h5路径的正确性
- 载入配置文件,使用了configparser模块,参考这里
- 解析cfg配置文件中的各个层,并解析成keras的层。并将weight文件的权重参数装进每一层中。
- 保存和绘图,将上面得到的模型保存为hdf5文件,绘制模型结构图。
yolo_video.py
- 进入main函数,读取各种参数。
- 判定,如果有--image参数,则是图片检测模式,调用detect_img方法;
否则是视频检测模式,调用detect_video方法。 - detect_img方法,进入一个死循环,不断键入文件名filename,检测该文件名对应图像,调用yolo.detect_image方法。
- detect_image和detect_video都是在yolo.py的方法。所以分析yolo.py
yolo.py
该文件包含两个部分,detect_video方法和YOLO类
- 先看detect_video方法。引入opencv模块。使用VideoCapture读取视频,验证视频是否可用,获取视频相关参数。验证输出视频路径是否可用。
如果都没有问题,则开始读取视频, 读里面的每一帧,调用yolo.detect_image方法检测。即上文提到的图片检测模式。(视频的检测实际上就是由多帧图片的检测组成的) - YOLO类,
- 构造方法中先设定默认参数:模型路径,anchor路径,类别路径,score阈值,iou阈值,输入图片大小,gpu数量。然后用get方法解析txt文件中的类别、anchors。最后用 generate方法整合信息,生成boxes,scores,classes。
- generae方法。先验证模型路径。判定是否为yolo_tiny。装载或构建模型、装载权重。生成后期作图需要用的颜色。由gpu的数量确定生成的输出张量。
- YOLO类的detect_image方法。
- 确定输入图像可以被32整除,因为yolo算法会缩小到原图的,
- 将图片进行预测
- 绘图
- 在过程中,用到了yolo3.utils.py和yolo3.model.py。utils就是一个工具箱,有随机生成数据,resize,compose功能。model在下面说。
yolo3.model.py
模型部分
用keras接口实现了yolov3模型。定义了一系列microarchitecture和macroarchitecture。
- DarknetConv2D:返回基本conv2d。
- DarknetConv2D_BN_Leaky:将conv2d、BN、leaky ReLU合并成一个块,返回。
- resblock_body:残差块。先构建DarknetConv2D_BN_Leaky,然后在循环中构建resblock。resblock由(1,1)和(3,3)组成,然后加上一个元素级相加的短路。
- darknet_body:由一个DarknetConv2D_BN_Leaky和5个resblock_body组成。
- make_last_layers:输出层,6个DarknetConv2D_BN_Leaky和1个DarknetConv2D作为输出。
- yolo_body:一开始是darknet_body和make_last_layers。构建DarknetConv2D_BN_Leaky和UpSampling2D,短路concatenate。做出3个输出。
- tiny_yolo_body:实现了tiny yolo,比较简单。
其他函数
主要包括:将模型的输出转换格式,模型评估,groundtruth预处理,iou的计算,loss函数的计算(coord,iou,class)
具体分析比较复杂,先略过,放到后面再具体分析。
argparse基本使用
argparse是一个 命令行参数解析器,比如linux中的shutdown -r now
,-r和now都是参数。使用argparse就可以解析命令行中的参数。
- help
import argparse
parser = argparse.ArgumentParser()
parser.parse_args()
python test.py -h
命令行中运行,获取帮助信息
python test.py -no
运行不存在的命令,会报错
- 添加参数
import argparse
parser = argparse.ArgumentParser()
# 这里添加参数名称 "some_command"
parser.add_argument("some_command")
args = parser.parse_args()
# 这里输出参数名称 args.some_command
print(args.some_command)
python test.py aaaa
aaaa作为参数传递,会被输出
- 添加可选参数
# 这里添加可选参数名称 "some_command"
parser.add_argument('-s','--sc','--some_command',help='opt args',nargs='?')
print(args.sc)