转换生成yolo.h5
#! /usr/bin/env python
"""
Reads Darknet53 config and weights and creates Keras model with TF backend.
Currently only supports layers in Darknet53 config.
yad2k.py的作用主要是使用yolo的网络结构配置文件和权重文件转换成keras的.h5文件
"""
import argparse#argparse的作用就是为py文件封装好可以选择的参数,使他们更加灵活,
import configparser#该模块在python中用来读取配置文件,配置文件的格式可以包含一个或多个节,每个节可以有多个参数
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
'''
arser = argparse.ArgumentParser()的目的是创建一个解析对象
add_argument的作用是向该对象中添加你要关注的命令行参数和选项,
每一个add_argument方法对应一个你要关注的参数或选项
最后调用parse_args方法进行解析,解析成功之后即可使用
'''
parser = argparse.ArgumentParser(description='Yet Another Darknet To Keras Converter.')
parser.add_argument('config_path', help='Path to Darknet cfg file.')
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):
"""Convert all config sections to have unique names.
Adds unique suffixes to config sections for compability with configparser.
转换所有config部分,使其具有唯一名称,并为config解析器的兼容性向配置部分添加唯一后缀
"""
# defaultdict的作用是当字典里的key不存在但被查找时,返回的不是keyError而是一个默认值,
# 这个默认值是多少根据defaultdict()中的值决定,如defaultdict(int)就表示这个默认值是0
section_counters = defaultdict(int)
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):
# 返回参数,参数中开头的~被替换成user的主目录;如果扩展失败或者参数path不是以~打头,则直接返回参数(path)。
config_path = os.path.expanduser(args.config_path)
weights_path = os.path.expanduser(args.weights_path)
# assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假。
assert config_path.endswith('.cfg'), '{} is not a .cfg file'.format(
config_path)
assert weights_path.endswith(
'.weights'), '{} is not a .weights file'.format(weights_path)
output_path = os.path.expanduser(args.output_path)
assert output_path.endswith(
'.h5'), 'output path {} is not a .h5 file'.format(output_path)
output_root = os.path.splitext(output_path)[0]
# Load weights and config.
print(