最近做项目需要用到yolo,参考了网上一些代码和文章,记录一下对yolo的理解。
yolo核心思想:
将整张图作为网络的输入,单个神经网络将图像分割成区域。并且,这个神经网络可以预测每个区域的边界框,以及用该边界框分割区域的概率。这些边界框由预测的概率加权。
优势:
- 它在测试时查看整个图像,因此它的预测由图像中的全局信息提供。
- 它可以通过单一网络进行预测,而不像R-CNN这样的系统需要数千张图像,这使得它运行速度非常快。
yolo代码理解:
在对yolo有了初步的了解之后,我在github上找到了一份yolov3的代码,通过代码理解yolo的执行过程。(代码来自GitHub:https://github.com/xiaochus/YOLOv3)
- 首先,argparse这个模块包的意义需要了解一下,详情见注释。
import argparse #Argparse的作用就是为py文件封装好可以选择的参数,使他们更加灵活,丰富。即导入一个模块
parser = argparse.ArgumentParser( description='Yet Another Darknet To Keras Converter.') #parser = argparse.ArgumentParser()的目的是创建一个解析对象
parser.add_argument('config_path', help='Path to Darknet cfg file.') #然向该对象中添加你要关注的命令行参数和选项,每一个add_argument方法对应一个你要关注的参数或选项
_main(parser.parse_args()) #最后调用parse_args()方法进行解析,解析成功之后即可使用
- yad2k.py部分的代码感觉不需要过分解读,这部分代码的主要目的就是使用yolo的网络结构配置文件使其转换成keras的.h5文件。如下所示,一些关键的地方写了注释。
#! /usr/bin/env python
"""
Reads Darknet53 config and weights and creates Keras model with TF backend.
Currently only supports layers in Darknet53 config.
"""
import argparse #Argparse的作用就是为py文件封装好可以选择的参数,使他们更加灵活,丰富。即导入一个模块
import configparser #ConfigParser模块在python中用来读取配置文件,配置文件的格式可以包含一个或多个节(section), 每个节可以有多个参数(键=值)
import io
import os
from collections import defaultdict
import numpy as np
from keras import backend as K
from keras.layers import (Conv2D, GlobalAveragePooling2D, Input, Reshape,
ZeroPadding2D, UpSampling2D, Activation, Lambda, MaxPooling2D)
from keras.layers.advanced_activations import LeakyReLU
from keras.layers.merge import concatenate, add
from keras.layers.normalization import BatchNormalization
from keras.models import Model
from keras.regularizers import l2
from keras.utils.vis_utils import plot_model as plot
parser = argparse.ArgumentParser( description='Yet Another Darknet To Keras Converter.') #parser = argparse.ArgumentParser()的目的是创建一个解析对象
parser.add_argument('config_path', help='Path to Darknet cfg file.') #然向该对象中添加你要关注的命令行参数和选项,每一个add_argument方法对应一个你要关注的参数或选项
parser.add_argument('weights_path', help='Path to Darknet weights file.')
parser.add_argument('output_path', help='Path to output Keras model file.')
parser.add_argument(
'-p',
'--plot_model',
help='Plot generated Keras model and save as image.',
action='store_true')
parser.add_argument(
'-flcl',
'--fully_convolutional',
help='Model is fully convolutional so set input shape to (None, None, 3). '
'WARNING: This experimental option does not work properly for YOLO_v2.',
action='store_true')
def unique_config_sections(config_file): #转换所有config部分,使其具有唯一名称,并为config解析器的兼容性向配置部分添加惟一后缀。
"""Convert all config sections to have unique names.
Adds unique suffixes to config sections for compability with configparser.
"""
section_counters = defaultdict(int) #defaultdict的作用是当字典里的key不存在但被查找时,返回的不是keyError而是一个默认值,这个默认值是多少根据defaultdict()中的值决定,如defaultdict(int)就表示这个默认值是0
output_stream = io.StringIO() #io.StringIO表示在内存中以io流的方式读写str
with open(config_file) as fin:
for line in fin:
if line.startswith('['):
section = line.strip().strip('[]')
_section = section + '_' + str(section_counters[section])
section_counters[section] += 1
line = line.replace(section, _section)
output_stream.write(line)
output_stream.seek(0) #把文件指针移动到文件开始处
return output_stream
def _main(args):
config_path = os.path.expanduser(args.config_path) #返回参数,参数中开头的~被替换成user的主目录;如果扩展失败或者参数path不是以~打头,则直接返回参数(path)。
weights_path = os.path.expanduser(args.weights_path)
output_path = os.path.expanduser(args.output_path)
assert config_path.endswith('.cfg'), '{} is not a .cfg file'.format(
config_path) #a