|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""Base test class SSDFeatureExtractors.""" |
|
|
|
from abc import abstractmethod |
|
|
|
import itertools |
|
import numpy as np |
|
import tensorflow as tf |
|
|
|
from google.protobuf import text_format |
|
from object_detection.builders import hyperparams_builder |
|
from object_detection.protos import hyperparams_pb2 |
|
from object_detection.utils import test_case |
|
|
|
|
|
class SsdFeatureExtractorTestBase(test_case.TestCase): |
|
|
|
def _build_conv_hyperparams(self, add_batch_norm=True): |
|
conv_hyperparams = hyperparams_pb2.Hyperparams() |
|
conv_hyperparams_text_proto = """ |
|
activation: RELU_6 |
|
regularizer { |
|
l2_regularizer { |
|
} |
|
} |
|
initializer { |
|
truncated_normal_initializer { |
|
} |
|
} |
|
""" |
|
if add_batch_norm: |
|
batch_norm_proto = """ |
|
batch_norm { |
|
scale: false |
|
} |
|
""" |
|
conv_hyperparams_text_proto += batch_norm_proto |
|
text_format.Merge(conv_hyperparams_text_proto, conv_hyperparams) |
|
return hyperparams_builder.KerasLayerHyperparams(conv_hyperparams) |
|
|
|
def conv_hyperparams_fn(self): |
|
with tf.contrib.slim.arg_scope([]) as sc: |
|
return sc |
|
|
|
@abstractmethod |
|
def _create_feature_extractor(self, depth_multiplier, pad_to_multiple, |
|
use_explicit_padding=False, use_keras=False): |
|
"""Constructs a new feature extractor. |
|
|
|
Args: |
|
depth_multiplier: float depth multiplier for feature extractor |
|
pad_to_multiple: the nearest multiple to zero pad the input height and |
|
width dimensions to. |
|
use_explicit_padding: use 'VALID' padding for convolutions, but prepad |
|
inputs so that the output dimensions are the same as if 'SAME' padding |
|
were used. |
|
use_keras: if True builds a keras-based feature extractor, if False builds |
|
a slim-based one. |
|
Returns: |
|
an ssd_meta_arch.SSDFeatureExtractor or an |
|
ssd_meta_arch.SSDKerasFeatureExtractor object. |
|
""" |
|
pass |
|
|
|
def _extract_features(self, image_tensor, depth_multiplier, pad_to_multiple, |
|
use_explicit_padding=False, use_keras=False): |
|
try: |
|
feature_extractor = self._create_feature_extractor(depth_multiplier, |
|
pad_to_multiple, |
|
use_explicit_padding, |
|
use_keras=use_keras) |
|
|
|
except TypeError: |
|
feature_extractor = self._create_feature_extractor(depth_multiplier, |
|
pad_to_multiple, |
|
use_explicit_padding) |
|
if use_keras: |
|
feature_maps = feature_extractor(image_tensor) |
|
else: |
|
feature_maps = feature_extractor.extract_features(image_tensor) |
|
return feature_maps |
|
|
|
def check_extract_features_returns_correct_shape( |
|
self, batch_size, image_height, image_width, depth_multiplier, |
|
pad_to_multiple, expected_feature_map_shapes, use_explicit_padding=False, |
|
use_keras=False): |
|
def graph_fn(image_tensor): |
|
return self._extract_features(image_tensor, |
|
depth_multiplier, |
|
pad_to_multiple, |
|
use_explicit_padding, |
|
use_keras=use_keras) |
|
|
|
image_tensor = np.random.rand(batch_size, image_height, image_width, |
|
3).astype(np.float32) |
|
feature_maps = self.execute(graph_fn, [image_tensor]) |
|
for feature_map, expected_shape in itertools.izip( |
|
feature_maps, expected_feature_map_shapes): |
|
self.assertAllEqual(feature_map.shape, expected_shape) |
|
|
|
def check_extract_features_returns_correct_shapes_with_dynamic_inputs( |
|
self, batch_size, image_height, image_width, depth_multiplier, |
|
pad_to_multiple, expected_feature_map_shapes, use_explicit_padding=False, |
|
use_keras=False): |
|
def graph_fn(image_height, image_width): |
|
image_tensor = tf.random_uniform([batch_size, image_height, image_width, |
|
3], dtype=tf.float32) |
|
return self._extract_features(image_tensor, |
|
depth_multiplier, |
|
pad_to_multiple, |
|
use_explicit_padding, |
|
use_keras=use_keras) |
|
|
|
feature_maps = self.execute_cpu(graph_fn, [ |
|
np.array(image_height, dtype=np.int32), |
|
np.array(image_width, dtype=np.int32) |
|
]) |
|
for feature_map, expected_shape in itertools.izip( |
|
feature_maps, expected_feature_map_shapes): |
|
self.assertAllEqual(feature_map.shape, expected_shape) |
|
|
|
def check_extract_features_raises_error_with_invalid_image_size( |
|
self, image_height, image_width, depth_multiplier, pad_to_multiple, |
|
use_keras=False): |
|
preprocessed_inputs = tf.placeholder(tf.float32, (4, None, None, 3)) |
|
feature_maps = self._extract_features(preprocessed_inputs, |
|
depth_multiplier, |
|
pad_to_multiple, |
|
use_keras=use_keras) |
|
test_preprocessed_image = np.random.rand(4, image_height, image_width, 3) |
|
with self.test_session() as sess: |
|
sess.run(tf.global_variables_initializer()) |
|
with self.assertRaises(tf.errors.InvalidArgumentError): |
|
sess.run(feature_maps, |
|
feed_dict={preprocessed_inputs: test_preprocessed_image}) |
|
|
|
def check_feature_extractor_variables_under_scope( |
|
self, depth_multiplier, pad_to_multiple, scope_name, use_keras=False): |
|
variables = self.get_feature_extractor_variables( |
|
depth_multiplier, pad_to_multiple, use_keras) |
|
for variable in variables: |
|
self.assertTrue(variable.name.startswith(scope_name)) |
|
|
|
def get_feature_extractor_variables( |
|
self, depth_multiplier, pad_to_multiple, use_keras=False): |
|
g = tf.Graph() |
|
with g.as_default(): |
|
preprocessed_inputs = tf.placeholder(tf.float32, (4, None, None, 3)) |
|
self._extract_features(preprocessed_inputs, |
|
depth_multiplier, |
|
pad_to_multiple, |
|
use_keras=use_keras) |
|
return g.get_collection(tf.GraphKeys.GLOBAL_VARIABLES) |
|
|