源码修改-TensorFlow目标检测API

源码阅读方法

  • 先看检测模型配置文件,即config文件
  • 再根据config文件中的具体配置选项的总名称,然后到builders文件夹中找到相关的命名的文件,如config文件中的参数loss配置对应builders文件夹下的losses_builder.py
  • 在对应的builder文件中,就可以看到具体参数配置的含义了,但具体的内部实现应该根据builder文件中的import部分中查看
    (model_builder里展现了各个检测模型的检测主要模块,如_build_ssd_model函数)

修改每一层anchor box的尺度和比例

multiple_grid_anchor_generator.py中的create_ssd_anchors函数,以及可以在config配置文件中指定

multiple_grid_anchor_generator.py

_generate函数

box_specs_list是二维列表,第一维表示该feature map层的预测方框数,第二维的数量对应于预测的feature map的数量(即参数feature_map_shape_list)

ssd_meta_architecture.py

有两个类,分别为特征提取类SSDFeatureExtractor和ssd网络架构类SSDMetaArch

修改feature map

models/feature_map_generators.py

models/feature_map_generators.py

ssd_meta_architecture.py中predict函数,展现了ssd的预测过程:

  • 先对预处理后的输入图片提取用于预测的feature_maps

      feature_maps = self._feature_extractor.extract_features(
          preprocessed_inputs)

    源码修改:models/ssd_mobilenet_v2_feature_extractor.py中的extract_features函数和models/feature_map_generators.py中的multi_resolution_feature_maps函数,目的是修改如何生成哪些feature map用于预测

若修改了用于预测的feature map的数量,则生成anchor box的create_ssd_anchors函数中的参数num_layers也应做相应修改,使两者的数量一致

  • 再计算feature_maps的shape尺寸大小,保存在feature_map_spatial_dims中

    feature_map_spatial_dims = self._get_feature_map_spatial_dims(
        feature_maps)

    源码修改:ssd_meta_arch.py中的feature_map_spatial_dims函数

  • 然后产生出anchor

    self._anchors = box_list_ops.concatenate(
        self._anchor_generator.generate(
            feature_map_spatial_dims,
            im_height=image_shape[1],
            im_width=image_shape[2]))

    源码修改:anchor_generator.py中的generate函数,但对anchor的生成规则的修改应修改multiple_grid_anchor_generator.py中的create_ssd_anchors函数,其中相关参数也可以在config文件中配置

  • 最后预测出box,并对box解码,预测结果保存在predictions_dict字典中,最后返回该字典

    prediction_dict = self._box_predictor.predict(
        feature_maps, self._anchor_generator.num_anchors_per_location())
    box_encodings = tf.concat(prediction_dict['box_encodings'], axis=1)
    if box_encodings.shape.ndims == 4 and box_encodings.shape[2] == 1:
      box_encodings = tf.squeeze(box_encodings, axis=2)
    class_predictions_with_background = tf.concat(
        prediction_dict['class_predictions_with_background'], axis=1)
    predictions_dict = {
        'preprocessed_inputs': preprocessed_inputs,
        'box_encodings': box_encodings,
        'class_predictions_with_background':
        class_predictions_with_background,
        'feature_maps': feature_maps,
        'anchors': self._anchors.get()
    }
    self._batched_prediction_tensor_names = [x for x in predictions_dict
                                             if x != 'anchors']
    return predictions_dict