当前位置:   article > 正文

在python程序中使用YOLO v3(基于keras)_python和yolo什么关系

python和yolo什么关系

在python程序中使用YOLO,可以为YOLO添加python接口,也可以把YOLO的网络框架和权重文件转换成keras或pytorch使用的格式,然后再在python程序中调用。这里介绍基于keras的YOLO调用。

 

完整项目代码下载地址 : https://github.com/dcrmg/yolo3-training-keras-master

 

1. 生成keras的.h5文件

需要:

  •  1. yolo网络结构配置文件 .cfg ,如 yolov3.cfg
  •  2. yolo训练好的权重文件 .weights ,如 yolov3.weights

 
使用yolo的网络结构配置文件和权重文件转换成keras的.h5文件,转换代码(convert.py):

  1. # coding: utf-8
  2. #! /usr/bin/env python
  3. """
  4. Reads Darknet config and weights and creates Keras model with TF backend.
  5. """
  6. import argparse
  7. import configparser
  8. import io
  9. import os
  10. from collections import defaultdict
  11. import numpy as np
  12. from keras import backend as K
  13. from keras.layers import (Conv2D, Input, ZeroPadding2D, Add,
  14. UpSampling2D, MaxPooling2D, Concatenate)
  15. from keras.layers.advanced_activations import LeakyReLU
  16. from keras.layers.normalization import BatchNormalization
  17. from keras.models import Model
  18. from keras.regularizers import l2
  19. from keras.utils.vis_utils import plot_model as plot
  20. parser = argparse.ArgumentParser(description='Darknet To Keras Converter.')
  21. parser.add_argument('config_path', help='Path to Darknet cfg file.')
  22. parser.add_argument('weights_path', help='Path to Darknet weights file.')
  23. parser.add_argument('output_path', help='Path to output Keras model file.')
  24. parser.add_argument(
  25. '-p',
  26. '--plot_model',
  27. help='Plot generated Keras model and save as image.',
  28. action='store_true')
  29. parser.add_argument(
  30. '-w',
  31. '--weights_only',
  32. help='Save as Keras weights file instead of model file.',
  33. action='store_true')
  34. def unique_config_sections(config_file):
  35. """Convert all config sections to have unique names.
  36. Adds unique suffixes to config sections for compability with configparser.
  37. """
  38. section_counters = defaultdict(int)
  39. # output_stream = io.StringIO()
  40. output_stream = io.BytesIO()
  41. with open(config_file) as fin:
  42. for line in fin:
  43. if line.startswith('['):
  44. section = line.strip().strip('[]')
  45. _section = section + '_' + str(section_counters[section])
  46. section_counters[section] += 1
  47. line = line.replace(section, _section)
  48. output_stream.write(line)
  49. output_stream.seek(0)
  50. return output_stream
  51. # %%
  52. def _main(args):
  53. config_path = os.path.expanduser(args.config_path)
  54. weights_path = os.path.expanduser(args.weights_path)
  55. assert config_path.endswith('.cfg'), '{} is not a .cfg file'.format(
  56. config_path)
  57. assert weights_path.endswith(
  58. '.weights'), '{} is not a .weights file'.format(weights_path)
  59. output_path = os.path.expanduser(args.output_path)
  60. assert output_path.endswith(
  61. '.h5'), 'output path {} is not a .h5 file'.format(output_path)
  62. output_root = os.path.splitext(output_path)[0]
  63. # Load weights and config.
  64. print('Loading weights.')
  65. weights_file = open(weights_path, 'rb')
  66. major, minor, revision = np.ndarray(
  67. shape=(3, ), dtype='int32', buffer=weights_file.read(12))
  68. if (major*10+minor)>=2 and major<1000 and minor<1000:
  69. seen = np.ndarray(shape=(1,), dtype='int64', buffer=weights_file.read(8))
  70. else:
  71. seen = np.ndarray(shape=(1,), dtype='int32', buffer=weights_file.read(4))
  72. print('Weights Header: ', major, minor, revision, seen)
  73. print('Parsing Darknet config.')
  74. unique_config_file = unique_config_sections(config_path)
  75. cfg_parser = configparser.ConfigParser()
  76. cfg_parser.read_file(unique_config_file)
  77. print('Creating Keras model.')
  78. input_layer = Input(shape=(None, None, 3))
  79. prev_layer = input_layer
  80. all_layers = []
  81. weight_decay = float(cfg_parser['net_0']['decay']
  82. ) if 'net_0' in cfg_parser.sections() else 5e-4
  83. count = 0
  84. out_index = []
  85. for section in cfg_parser.sections():
  86. print('Parsing section {}'.format(section))
  87. if section.startswith('convolutional'):
  88. filters = int(cfg_parser[section]['filters'])
  89. size = int(cfg_parser[section]['size'])
  90. stride = int(cfg_parser[section]['stride'])
  91. pad = int(cfg_parser[section]['pad'])
  92. activation = cfg_parser[section]['activation']
  93. batch_normalize = 'batch_normalize' in cfg_parser[section]
  94. padding = 'same' if pad == 1 and stride == 1 else 'valid'
  95. # Setting weights.
  96. # Darknet serializes convolutional weights as:
  97. # [bias/beta, [gamma, mean, variance], conv_weights]
  98. prev_layer_shape = K.int_shape(prev_layer)
  99. weights_shape = (size, size, prev_layer_shape[-1], filters)
  100. darknet_w_shape = (filters, weights_shape[2], size, size)
  101. weights_size = np.product(weights_shape)
  102. print('conv2d', 'bn'
  103. if batch_normalize else ' ', activation, weights_shape)
  104. conv_bias = np.ndarray(
  105. shape=(filters, ),
  106. dtype='float32',
  107. buffer=weights_file.read(filters * 4))
  108. count += filters
  109. if batch_normalize:
  110. bn_weights = np.ndarray(
  111. shape=(3, filters),
  112. dtype='float32',
  113. buffer=weights_file.read(filters * 12))
  114. count += 3 * filters
  115. bn_weight_list = [
  116. bn_weights[0], # scale gamma
  117. conv_bias, # shift beta
  118. bn_weights[1], # running mean
  119. bn_weights[2] # running var
  120. ]
  121. conv_weights = np.ndarray(
  122. shape=darknet_w_shape,
  123. dtype='float32',
  124. buffer=weights_file.read(weights_size * 4))
  125. count += weights_size
  126. # DarkNet conv_weights are serialized Caffe-style:
  127. # (out_dim, in_dim, height, width)
  128. # We would like to set these to Tensorflow order:
  129. # (height, width, in_dim, out_dim)
  130. conv_weights = np.transpose(conv_weights, [2, 3, 1, 0])
  131. conv_weights = [conv_weights] if batch_normalize else [
  132. conv_weights, conv_bias
  133. ]
  134. # Handle activation.
  135. act_fn = None
  136. if activation == 'leaky':
  137. pass # Add advanced activation later.
  138. elif activation != 'linear':
  139. raise ValueError(
  140. 'Unknown activation function `{}` in section {}'.format(
  141. activation, section))
  142. # Create Conv2D layer
  143. if stride>1:
  144. # Darknet uses left and top padding instead of 'same' mode
  145. prev_layer = ZeroPadding2D(((1,0),(1,0)))(prev_layer)
  146. conv_layer = (Conv2D(
  147. filters, (size, size),
  148. strides=(stride, stride),
  149. kernel_regularizer=l2(weight_decay),
  150. use_bias=not batch_normalize,
  151. weights=conv_weights,
  152. activation=act_fn,
  153. padding=padding))(prev_layer)
  154. if batch_normalize:
  155. conv_layer = (BatchNormalization(
  156. weights=bn_weight_list))(conv_layer)
  157. prev_layer = conv_layer
  158. if activation == 'linear':
  159. all_layers.append(prev_layer)
  160. elif activation == 'leaky':
  161. act_layer = LeakyReLU(alpha=0.1)(prev_layer)
  162. prev_layer = act_layer
  163. all_layers.append(act_layer)
  164. elif section.startswith('route'):
  165. ids = [int(i) for i in cfg_parser[section]['layers'].split(',')]
  166. layers = [all_layers[i] for i in ids]
  167. if len(layers) > 1:
  168. print('Concatenating route layers:', layers)
  169. concatenate_layer = Concatenate()(layers)
  170. all_layers.append(concatenate_layer)
  171. prev_layer = concatenate_layer
  172. else:
  173. skip_layer = layers[0] # only one layer to route
  174. all_layers.append(skip_layer)
  175. prev_layer = skip_layer
  176. elif section.startswith('maxpool'):
  177. size = int(cfg_parser[section]['size'])
  178. stride = int(cfg_parser[section]['stride'])
  179. all_layers.append(
  180. MaxPooling2D(
  181. pool_size=(size, size),
  182. strides=(stride, stride),
  183. padding='same')(prev_layer))
  184. prev_layer = all_layers[-1]
  185. elif section.startswith('shortcut'):
  186. index = int(cfg_parser[section]['from'])
  187. activation = cfg_parser[section]['activation']
  188. assert activation == 'linear', 'Only linear activation supported.'
  189. all_layers.append(Add()([all_layers[index], prev_layer]))
  190. prev_layer = all_layers[-1]
  191. elif section.startswith('upsample'):
  192. stride = int(cfg_parser[section]['stride'])
  193. assert stride == 2, 'Only stride=2 supported.'
  194. all_layers.append(UpSampling2D(stride)(prev_layer))
  195. prev_layer = all_layers[-1]
  196. elif section.startswith('yolo'):
  197. out_index.append(len(all_layers)-1)
  198. all_layers.append(None)
  199. prev_layer = all_layers[-1]
  200. elif section.startswith('net'):
  201. pass
  202. else:
  203. raise ValueError(
  204. 'Unsupported section header type: {}'.format(section))
  205. # Create and save model.
  206. if len(out_index)==0: out_index.append(len(all_layers)-1)
  207. model = Model(inputs=input_layer, outputs=[all_layers[i] for i in out_index])
  208. print(model.summary())
  209. if args.weights_only:
  210. model.save_weights('{}'.format(output_path))
  211. print('Saved Keras weights to {}'.format(output_path))
  212. else:
  213. model.save('{}'.format(output_path))
  214. print('Saved Keras model to {}'.format(output_path))
  215. # Check to see if all weights have been read.
  216. remaining_weights = len(weights_file.read()) / 4
  217. weights_file.close()
  218. print('Read {} of {} from Darknet weights.'.format(count, count +
  219. remaining_weights))
  220. if remaining_weights > 0:
  221. print('Warning: {} unused weights'.format(remaining_weights))
  222. if args.plot_model:
  223. plot(model, to_file='{}.png'.format(output_root), show_shapes=True)
  224. print('Saved model plot to {}.png'.format(output_root))
  225. if __name__ == '__main__':
  226. _main(parser.parse_args())

使用方法:

python convert.py yolov3.cfg yolov3.weights yolov3.h5

转换过程输出:

  1. Loading weights.
  2. ('Weights Header: ', 0, 2, 0, array([1600]))
  3. Parsing Darknet config.
  4. Creating Keras model.
  5. Parsing section net_0
  6. Parsing section convolutional_0
  7. ('conv2d', 'bn', u'leaky', (3, 3, 3, 32))
  8. ……
  9. ……
  10. conv2d_59 (Conv2D) (None, None, None, 1 18450 leaky_re_lu_58[0][0]
  11. __________________________________________________________________________________________________
  12. conv2d_67 (Conv2D) (None, None, None, 1 9234 leaky_re_lu_65[0][0]
  13. __________________________________________________________________________________________________
  14. conv2d_75 (Conv2D) (None, None, None, 1 4626 leaky_re_lu_72[0][0]
  15. ==================================================================================================
  16. Total params: 61,576,342
  17. Trainable params: 61,523,734
  18. Non-trainable params: 52,608
  19. __________________________________________________________________________________________________
  20. None
  21. Saved Keras model to yolov3.h5
  22. Read 61576342 of 61576342 from Darknet weights.

执行完成之后在当前目录下生成yolov3.h5文件。

 

2. python + keras + yolo检测

需要:

  •  1. 类别标签文件yolo_classes.txt ,如有三个分类 dog、cat、tiger 则classes.txt内容为 dog cat tiger(每个类别一行)
  •  2. anchors文件 yolo_anchors.txt
  •  3. 步骤一中生成的 yolov3.h5

注意:yolo_anchors.txt记录了yolov3通过k-means聚类方法产生的9个anchors(锚点)信息,使用的训练图像大小是416×416,如果 你的训练图片大小不一样,这个yolo_anchors.txt文件需要重新生成,最好使用跟作者一样的416×416的图像训练。

检测代码略,请见项目代码。

通过调整YOLO类 self.score 的大小控制检出目标的阈值。

200个样本简单训练了400轮的检测效果:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/248574?site
推荐阅读
相关标签
  

闽ICP备14008679号