/
githubmirror
/
models
Обзор
Документация
Войти
/
githubmirror
/
models
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
research/object_detection/builders/model_builder_tf2_test.py
583 строки
21 KB
Runze Wang
Automated Code Change
06 июн 2026, 19:36
06 июн 2026, 19:36
5b2b5aa
Код
Авторство
О чём код?
# Copyright 2020 The TensorFlow Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== """Tests for model_builder under TensorFlow 2.X.""" import os import unittest from absl.testing import parameterized from google.protobuf import text_format import tensorflow.compat.v1 as tf from object_detection.builders import model_builder from object_detection.builders import model_builder_test from object_detection.core import losses from object_detection.meta_architectures import deepmac_meta_arch from object_detection.models import center_net_hourglass_feature_extractor from object_detection.models.keras_models import hourglass_network from object_detection.protos import center_net_pb2 from object_detection.protos import model_pb2 from object_detection.utils import tf_version @unittest.skipIf(tf_version.is_tf1(), 'Skipping TF2.X only test.') class ModelBuilderTF2Test( model_builder_test.ModelBuilderTest, parameterized.TestCase): def default_ssd_feature_extractor(self): return 'ssd_resnet50_v1_fpn_keras' def default_faster_rcnn_feature_extractor(self): return 'faster_rcnn_resnet101_keras' def ssd_feature_extractors(self): return model_builder.SSD_KERAS_FEATURE_EXTRACTOR_CLASS_MAP def get_override_base_feature_extractor_hyperparams(self, extractor_type): return extractor_type in {} def faster_rcnn_feature_extractors(self): return model_builder.FASTER_RCNN_KERAS_FEATURE_EXTRACTOR_CLASS_MAP def get_fake_label_map_file_path(self): keypoint_spec_text = """ item { name: "/m/01g317" id: 1 display_name: "person" keypoints { id: 0 label: 'nose' } keypoints { id: 1 label: 'left_shoulder' } keypoints { id: 2 label: 'right_shoulder' } keypoints { id: 3 label: 'hip' } } """ keypoint_label_map_path = os.path.join( self.get_temp_dir(), 'keypoint_label_map') with tf.gfile.Open(keypoint_label_map_path, 'wb') as f: f.write(keypoint_spec_text) return keypoint_label_map_path def get_fake_keypoint_proto(self, customize_head_params=False): task_proto_txt = """ task_name: "human_pose" task_loss_weight: 0.9 keypoint_regression_loss_weight: 1.0 keypoint_heatmap_loss_weight: 0.1 keypoint_offset_loss_weight: 0.5 heatmap_bias_init: 2.14 keypoint_class_name: "/m/01g317" loss { classification_loss { penalty_reduced_logistic_focal_loss { alpha: 3.0 beta: 4.0 } } localization_loss { l1_localization_loss { } } } keypoint_label_to_std { key: "nose" value: 0.3 } keypoint_label_to_std { key: "hip" value: 0.0 } keypoint_candidate_score_threshold: 0.3 num_candidates_per_keypoint: 12 peak_max_pool_kernel_size: 5 unmatched_keypoint_score: 0.05 box_scale: 1.7 candidate_search_scale: 0.2 candidate_ranking_mode: "score_distance_ratio" offset_peak_radius: 3 per_keypoint_offset: true predict_depth: true per_keypoint_depth: true keypoint_depth_loss_weight: 0.3 score_distance_multiplier: 11.0 std_dev_multiplier: 2.8 rescoring_threshold: 0.5 gaussian_denom_ratio: 0.3 argmax_postprocessing: True """ if customize_head_params: task_proto_txt += """ heatmap_head_params { num_filters: 64 num_filters: 32 kernel_sizes: 5 kernel_sizes: 3 } offset_head_params { num_filters: 128 num_filters: 64 kernel_sizes: 5 kernel_sizes: 3 } """ config = text_format.Merge(task_proto_txt, center_net_pb2.CenterNet.KeypointEstimation()) return config def get_fake_object_center_proto(self, customize_head_params=False): proto_txt = """ object_center_loss_weight: 0.5 heatmap_bias_init: 3.14 min_box_overlap_iou: 0.2 max_box_predictions: 15 classification_loss { penalty_reduced_logistic_focal_loss { alpha: 3.0 beta: 4.0 } } peak_max_pool_kernel_size: 5 """ if customize_head_params: proto_txt += """ center_head_params { num_filters: 64 num_filters: 32 kernel_sizes: 5 kernel_sizes: 3 } """ return text_format.Merge(proto_txt, center_net_pb2.CenterNet.ObjectCenterParams()) def get_fake_object_center_from_keypoints_proto(self): proto_txt = """ object_center_loss_weight: 0.5 heatmap_bias_init: 3.14 min_box_overlap_iou: 0.2 max_box_predictions: 15 classification_loss { penalty_reduced_logistic_focal_loss { alpha: 3.0 beta: 4.0 } } keypoint_weights_for_center: 1.0 keypoint_weights_for_center: 0.0 keypoint_weights_for_center: 1.0 keypoint_weights_for_center: 0.0 """ return text_format.Merge(proto_txt, center_net_pb2.CenterNet.ObjectCenterParams()) def get_fake_object_detection_proto(self, customize_head_params=False): proto_txt = """ task_loss_weight: 0.5 offset_loss_weight: 0.1 scale_loss_weight: 0.2 localization_loss { l1_localization_loss { } } """ if customize_head_params: proto_txt += """ scale_head_params { num_filters: 128 num_filters: 64 kernel_sizes: 5 kernel_sizes: 3 } """ return text_format.Merge(proto_txt, center_net_pb2.CenterNet.ObjectDetection()) def get_fake_mask_proto(self, customize_head_params=False): proto_txt = """ task_loss_weight: 0.7 classification_loss { weighted_softmax {} } mask_height: 8 mask_width: 8 score_threshold: 0.7 heatmap_bias_init: -2.0 """ if customize_head_params: proto_txt += """ mask_head_params { num_filters: 128 num_filters: 64 kernel_sizes: 5 kernel_sizes: 3 } """ return text_format.Merge(proto_txt, center_net_pb2.CenterNet.MaskEstimation()) def get_fake_densepose_proto(self): proto_txt = """ task_loss_weight: 0.5 class_id: 0 loss { classification_loss { weighted_softmax {} } localization_loss { l1_localization_loss { } } } num_parts: 24 part_loss_weight: 1.0 coordinate_loss_weight: 2.0 upsample_to_input_res: true heatmap_bias_init: -2.0 """ return text_format.Merge(proto_txt, center_net_pb2.CenterNet.DensePoseEstimation()) @parameterized.parameters( {'customize_head_params': True}, {'customize_head_params': False} ) def test_create_center_net_model(self, customize_head_params): """Test building a CenterNet model from proto txt.""" proto_txt = """ center_net { num_classes: 10 feature_extractor { type: "hourglass_52" channel_stds: [4, 5, 6] bgr_ordering: true } image_resizer { keep_aspect_ratio_resizer { min_dimension: 512 max_dimension: 512 pad_to_max_dimension: true } } } """ # Set up the configuration proto. config = text_format.Merge(proto_txt, model_pb2.DetectionModel()) config.center_net.object_center_params.CopyFrom( self.get_fake_object_center_proto( customize_head_params=customize_head_params)) config.center_net.object_detection_task.CopyFrom( self.get_fake_object_detection_proto( customize_head_params=customize_head_params)) config.center_net.keypoint_estimation_task.append( self.get_fake_keypoint_proto( customize_head_params=customize_head_params)) config.center_net.keypoint_label_map_path = ( self.get_fake_label_map_file_path()) config.center_net.mask_estimation_task.CopyFrom( self.get_fake_mask_proto( customize_head_params=customize_head_params)) config.center_net.densepose_estimation_task.CopyFrom( self.get_fake_densepose_proto()) # Build the model from the configuration. model = model_builder.build(config, is_training=True) # Check object center related parameters. self.assertEqual(model._num_classes, 10) self.assertIsInstance(model._center_params.classification_loss, losses.PenaltyReducedLogisticFocalLoss) self.assertEqual(model._center_params.classification_loss._alpha, 3.0) self.assertEqual(model._center_params.classification_loss._beta, 4.0) self.assertAlmostEqual(model._center_params.min_box_overlap_iou, 0.2) self.assertAlmostEqual( model._center_params.heatmap_bias_init, 3.14, places=4) self.assertEqual(model._center_params.max_box_predictions, 15) if customize_head_params: self.assertEqual(model._center_params.center_head_num_filters, [64, 32]) self.assertEqual(model._center_params.center_head_kernel_sizes, [5, 3]) else: self.assertEqual(model._center_params.center_head_num_filters, [256]) self.assertEqual(model._center_params.center_head_kernel_sizes, [3]) self.assertEqual(model._center_params.peak_max_pool_kernel_size, 5) # Check object detection related parameters. self.assertAlmostEqual(model._od_params.offset_loss_weight, 0.1) self.assertAlmostEqual(model._od_params.scale_loss_weight, 0.2) self.assertAlmostEqual(model._od_params.task_loss_weight, 0.5) self.assertIsInstance(model._od_params.localization_loss, losses.L1LocalizationLoss) self.assertEqual(model._od_params.offset_head_num_filters, [256]) self.assertEqual(model._od_params.offset_head_kernel_sizes, [3]) if customize_head_params: self.assertEqual(model._od_params.scale_head_num_filters, [128, 64]) self.assertEqual(model._od_params.scale_head_kernel_sizes, [5, 3]) else: self.assertEqual(model._od_params.scale_head_num_filters, [256]) self.assertEqual(model._od_params.scale_head_kernel_sizes, [3]) # Check keypoint estimation related parameters. kp_params = model._kp_params_dict['human_pose'] self.assertAlmostEqual(kp_params.task_loss_weight, 0.9) self.assertAlmostEqual(kp_params.keypoint_regression_loss_weight, 1.0) self.assertAlmostEqual(kp_params.keypoint_offset_loss_weight, 0.5) self.assertAlmostEqual(kp_params.heatmap_bias_init, 2.14, places=4) self.assertEqual(kp_params.classification_loss._alpha, 3.0) self.assertEqual(kp_params.keypoint_indices, [0, 1, 2, 3]) self.assertEqual(kp_params.keypoint_labels, ['nose', 'left_shoulder', 'right_shoulder', 'hip']) self.assertAllClose(kp_params.keypoint_std_dev, [0.3, 1.0, 1.0, 0.0]) self.assertEqual(kp_params.classification_loss._beta, 4.0) self.assertIsInstance(kp_params.localization_loss, losses.L1LocalizationLoss) self.assertAlmostEqual(kp_params.keypoint_candidate_score_threshold, 0.3) self.assertEqual(kp_params.num_candidates_per_keypoint, 12) self.assertEqual(kp_params.peak_max_pool_kernel_size, 5) self.assertAlmostEqual(kp_params.unmatched_keypoint_score, 0.05) self.assertAlmostEqual(kp_params.box_scale, 1.7) self.assertAlmostEqual(kp_params.candidate_search_scale, 0.2) self.assertEqual(kp_params.candidate_ranking_mode, 'score_distance_ratio') self.assertEqual(kp_params.offset_peak_radius, 3) self.assertEqual(kp_params.per_keypoint_offset, True) self.assertEqual(kp_params.predict_depth, True) self.assertEqual(kp_params.per_keypoint_depth, True) self.assertAlmostEqual(kp_params.keypoint_depth_loss_weight, 0.3) self.assertAlmostEqual(kp_params.score_distance_multiplier, 11.0) self.assertAlmostEqual(kp_params.std_dev_multiplier, 2.8) self.assertAlmostEqual(kp_params.rescoring_threshold, 0.5) if customize_head_params: # Set by the config. self.assertEqual(kp_params.heatmap_head_num_filters, [64, 32]) self.assertEqual(kp_params.heatmap_head_kernel_sizes, [5, 3]) self.assertEqual(kp_params.offset_head_num_filters, [128, 64]) self.assertEqual(kp_params.offset_head_kernel_sizes, [5, 3]) else: # Default values: self.assertEqual(kp_params.heatmap_head_num_filters, [256]) self.assertEqual(kp_params.heatmap_head_kernel_sizes, [3]) self.assertEqual(kp_params.offset_head_num_filters, [256]) self.assertEqual(kp_params.offset_head_kernel_sizes, [3]) self.assertAlmostEqual(kp_params.gaussian_denom_ratio, 0.3) self.assertEqual(kp_params.argmax_postprocessing, True) # Check mask related parameters. self.assertAlmostEqual(model._mask_params.task_loss_weight, 0.7) self.assertIsInstance(model._mask_params.classification_loss, losses.WeightedSoftmaxClassificationLoss) self.assertEqual(model._mask_params.mask_height, 8) self.assertEqual(model._mask_params.mask_width, 8) self.assertAlmostEqual(model._mask_params.score_threshold, 0.7) self.assertAlmostEqual( model._mask_params.heatmap_bias_init, -2.0, places=4) if customize_head_params: self.assertEqual(model._mask_params.mask_head_num_filters, [128, 64]) self.assertEqual(model._mask_params.mask_head_kernel_sizes, [5, 3]) else: self.assertEqual(model._mask_params.mask_head_num_filters, [256]) self.assertEqual(model._mask_params.mask_head_kernel_sizes, [3]) # Check DensePose related parameters. self.assertEqual(model._densepose_params.class_id, 0) self.assertIsInstance(model._densepose_params.classification_loss, losses.WeightedSoftmaxClassificationLoss) self.assertIsInstance(model._densepose_params.localization_loss, losses.L1LocalizationLoss) self.assertAlmostEqual(model._densepose_params.part_loss_weight, 1.0) self.assertAlmostEqual(model._densepose_params.coordinate_loss_weight, 2.0) self.assertEqual(model._densepose_params.num_parts, 24) self.assertAlmostEqual(model._densepose_params.task_loss_weight, 0.5) self.assertTrue(model._densepose_params.upsample_to_input_res) self.assertEqual(model._densepose_params.upsample_method, 'bilinear') self.assertAlmostEqual( model._densepose_params.heatmap_bias_init, -2.0, places=4) # Check feature extractor parameters. self.assertIsInstance( model._feature_extractor, center_net_hourglass_feature_extractor .CenterNetHourglassFeatureExtractor) self.assertAllClose(model._feature_extractor._channel_means, [0, 0, 0]) self.assertAllClose(model._feature_extractor._channel_stds, [4, 5, 6]) self.assertTrue(model._feature_extractor._bgr_ordering) backbone = model._feature_extractor._network self.assertIsInstance(backbone, hourglass_network.HourglassNetwork) self.assertTrue(backbone.num_hourglasses, 1) def test_create_center_net_model_from_keypoints(self): """Test building a CenterNet model from proto txt.""" proto_txt = """ center_net { num_classes: 10 feature_extractor { type: "hourglass_52" channel_stds: [4, 5, 6] bgr_ordering: true } image_resizer { keep_aspect_ratio_resizer { min_dimension: 512 max_dimension: 512 pad_to_max_dimension: true } } } """ # Set up the configuration proto. config = text_format.Parse(proto_txt, model_pb2.DetectionModel()) # Only add object center and keypoint estimation configs here. config.center_net.object_center_params.CopyFrom( self.get_fake_object_center_from_keypoints_proto()) config.center_net.keypoint_estimation_task.append( self.get_fake_keypoint_proto()) config.center_net.keypoint_label_map_path = ( self.get_fake_label_map_file_path()) # Build the model from the configuration. model = model_builder.build(config, is_training=True) # Check object center related parameters. self.assertEqual(model._num_classes, 10) self.assertEqual(model._center_params.keypoint_weights_for_center, [1.0, 0.0, 1.0, 0.0]) # Check keypoint estimation related parameters. kp_params = model._kp_params_dict['human_pose'] self.assertAlmostEqual(kp_params.task_loss_weight, 0.9) self.assertEqual(kp_params.keypoint_indices, [0, 1, 2, 3]) self.assertEqual(kp_params.keypoint_labels, ['nose', 'left_shoulder', 'right_shoulder', 'hip']) def test_create_center_net_model_mobilenet(self): """Test building a CenterNet model using bilinear interpolation.""" proto_txt = """ center_net { num_classes: 10 feature_extractor { type: "mobilenet_v2_fpn" depth_multiplier: 2.0 use_separable_conv: true upsampling_interpolation: "bilinear" } image_resizer { keep_aspect_ratio_resizer { min_dimension: 512 max_dimension: 512 pad_to_max_dimension: true } } } """ # Set up the configuration proto. config = text_format.Parse(proto_txt, model_pb2.DetectionModel()) # Only add object center and keypoint estimation configs here. config.center_net.object_center_params.CopyFrom( self.get_fake_object_center_from_keypoints_proto()) config.center_net.keypoint_estimation_task.append( self.get_fake_keypoint_proto()) config.center_net.keypoint_label_map_path = ( self.get_fake_label_map_file_path()) # Build the model from the configuration. model = model_builder.build(config, is_training=True) feature_extractor = model._feature_extractor # Verify the upsampling layers in the FPN use 'bilinear' interpolation. fpn = feature_extractor.get_layer('model_1') num_up_sampling2d_layers = 0 for layer in fpn.layers: if 'up_sampling2d' in layer.name: num_up_sampling2d_layers += 1 self.assertEqual('bilinear', layer.interpolation) # Verify that there are up_sampling2d layers. self.assertGreater(num_up_sampling2d_layers, 0) # Verify that the FPN ops uses separable conv. for layer in fpn.layers: # Convolution layers with kernel size not equal to (1, 1) should be # separable 2D convolutions. if 'conv' in layer.name and layer.kernel_size != (1, 1): self.assertIsInstance(layer, tf.keras.layers.SeparableConv2D) # Verify that the backbone indeed double the number of channel according to # the depthmultiplier. backbone = feature_extractor.get_layer('model') first_conv = backbone.get_layer('Conv1') # Note that the first layer typically has 32 filters, but this model has # a depth multiplier of 2. self.assertEqual(64, first_conv.filters) def test_create_center_net_deepmac(self): """Test building a CenterNet DeepMAC model.""" proto_txt = """ center_net { num_classes: 90 feature_extractor { type: "hourglass_52" } image_resizer { keep_aspect_ratio_resizer { min_dimension: 512 max_dimension: 512 pad_to_max_dimension: true } } object_detection_task { task_loss_weight: 1.0 offset_loss_weight: 1.0 scale_loss_weight: 0.1 localization_loss { l1_localization_loss { } } } object_center_params { object_center_loss_weight: 1.0 min_box_overlap_iou: 0.7 max_box_predictions: 100 classification_loss { penalty_reduced_logistic_focal_loss { alpha: 2.0 beta: 4.0 } } } deepmac_mask_estimation { classification_loss { weighted_sigmoid {} } } } """ # Set up the configuration proto. config = text_format.Parse(proto_txt, model_pb2.DetectionModel()) # Build the model from the configuration. model = model_builder.build(config, is_training=True) self.assertIsInstance(model, deepmac_meta_arch.DeepMACMetaArch) if __name__ == '__main__': tf.test.main()