You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

337 lines
14 KiB

6 years ago
  1. # Copyright 2017 The TensorFlow Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. # ==============================================================================
  15. """Tests for object_detection.utils.shape_utils."""
  16. import numpy as np
  17. import tensorflow as tf
  18. from object_detection.utils import shape_utils
  19. class UtilTest(tf.test.TestCase):
  20. def test_pad_tensor_using_integer_input(self):
  21. t1 = tf.constant([1], dtype=tf.int32)
  22. pad_t1 = shape_utils.pad_tensor(t1, 2)
  23. t2 = tf.constant([[0.1, 0.2]], dtype=tf.float32)
  24. pad_t2 = shape_utils.pad_tensor(t2, 2)
  25. self.assertEqual(2, pad_t1.get_shape()[0])
  26. self.assertEqual(2, pad_t2.get_shape()[0])
  27. with self.test_session() as sess:
  28. pad_t1_result, pad_t2_result = sess.run([pad_t1, pad_t2])
  29. self.assertAllEqual([1, 0], pad_t1_result)
  30. self.assertAllClose([[0.1, 0.2], [0, 0]], pad_t2_result)
  31. def test_pad_tensor_using_tensor_input(self):
  32. t1 = tf.constant([1], dtype=tf.int32)
  33. pad_t1 = shape_utils.pad_tensor(t1, tf.constant(2))
  34. t2 = tf.constant([[0.1, 0.2]], dtype=tf.float32)
  35. pad_t2 = shape_utils.pad_tensor(t2, tf.constant(2))
  36. with self.test_session() as sess:
  37. pad_t1_result, pad_t2_result = sess.run([pad_t1, pad_t2])
  38. self.assertAllEqual([1, 0], pad_t1_result)
  39. self.assertAllClose([[0.1, 0.2], [0, 0]], pad_t2_result)
  40. def test_clip_tensor_using_integer_input(self):
  41. t1 = tf.constant([1, 2, 3], dtype=tf.int32)
  42. clip_t1 = shape_utils.clip_tensor(t1, 2)
  43. t2 = tf.constant([[0.1, 0.2], [0.2, 0.4], [0.5, 0.8]], dtype=tf.float32)
  44. clip_t2 = shape_utils.clip_tensor(t2, 2)
  45. self.assertEqual(2, clip_t1.get_shape()[0])
  46. self.assertEqual(2, clip_t2.get_shape()[0])
  47. with self.test_session() as sess:
  48. clip_t1_result, clip_t2_result = sess.run([clip_t1, clip_t2])
  49. self.assertAllEqual([1, 2], clip_t1_result)
  50. self.assertAllClose([[0.1, 0.2], [0.2, 0.4]], clip_t2_result)
  51. def test_clip_tensor_using_tensor_input(self):
  52. t1 = tf.constant([1, 2, 3], dtype=tf.int32)
  53. clip_t1 = shape_utils.clip_tensor(t1, tf.constant(2))
  54. t2 = tf.constant([[0.1, 0.2], [0.2, 0.4], [0.5, 0.8]], dtype=tf.float32)
  55. clip_t2 = shape_utils.clip_tensor(t2, tf.constant(2))
  56. with self.test_session() as sess:
  57. clip_t1_result, clip_t2_result = sess.run([clip_t1, clip_t2])
  58. self.assertAllEqual([1, 2], clip_t1_result)
  59. self.assertAllClose([[0.1, 0.2], [0.2, 0.4]], clip_t2_result)
  60. def test_pad_or_clip_tensor_using_integer_input(self):
  61. t1 = tf.constant([1], dtype=tf.int32)
  62. tt1 = shape_utils.pad_or_clip_tensor(t1, 2)
  63. t2 = tf.constant([[0.1, 0.2]], dtype=tf.float32)
  64. tt2 = shape_utils.pad_or_clip_tensor(t2, 2)
  65. t3 = tf.constant([1, 2, 3], dtype=tf.int32)
  66. tt3 = shape_utils.clip_tensor(t3, 2)
  67. t4 = tf.constant([[0.1, 0.2], [0.2, 0.4], [0.5, 0.8]], dtype=tf.float32)
  68. tt4 = shape_utils.clip_tensor(t4, 2)
  69. self.assertEqual(2, tt1.get_shape()[0])
  70. self.assertEqual(2, tt2.get_shape()[0])
  71. self.assertEqual(2, tt3.get_shape()[0])
  72. self.assertEqual(2, tt4.get_shape()[0])
  73. with self.test_session() as sess:
  74. tt1_result, tt2_result, tt3_result, tt4_result = sess.run(
  75. [tt1, tt2, tt3, tt4])
  76. self.assertAllEqual([1, 0], tt1_result)
  77. self.assertAllClose([[0.1, 0.2], [0, 0]], tt2_result)
  78. self.assertAllEqual([1, 2], tt3_result)
  79. self.assertAllClose([[0.1, 0.2], [0.2, 0.4]], tt4_result)
  80. def test_pad_or_clip_tensor_using_tensor_input(self):
  81. t1 = tf.constant([1], dtype=tf.int32)
  82. tt1 = shape_utils.pad_or_clip_tensor(t1, tf.constant(2))
  83. t2 = tf.constant([[0.1, 0.2]], dtype=tf.float32)
  84. tt2 = shape_utils.pad_or_clip_tensor(t2, tf.constant(2))
  85. t3 = tf.constant([1, 2, 3], dtype=tf.int32)
  86. tt3 = shape_utils.clip_tensor(t3, tf.constant(2))
  87. t4 = tf.constant([[0.1, 0.2], [0.2, 0.4], [0.5, 0.8]], dtype=tf.float32)
  88. tt4 = shape_utils.clip_tensor(t4, tf.constant(2))
  89. with self.test_session() as sess:
  90. tt1_result, tt2_result, tt3_result, tt4_result = sess.run(
  91. [tt1, tt2, tt3, tt4])
  92. self.assertAllEqual([1, 0], tt1_result)
  93. self.assertAllClose([[0.1, 0.2], [0, 0]], tt2_result)
  94. self.assertAllEqual([1, 2], tt3_result)
  95. self.assertAllClose([[0.1, 0.2], [0.2, 0.4]], tt4_result)
  96. def test_combines_static_dynamic_shape(self):
  97. tensor = tf.placeholder(tf.float32, shape=(None, 2, 3))
  98. combined_shape = shape_utils.combined_static_and_dynamic_shape(
  99. tensor)
  100. self.assertTrue(tf.contrib.framework.is_tensor(combined_shape[0]))
  101. self.assertListEqual(combined_shape[1:], [2, 3])
  102. def test_pad_or_clip_nd_tensor(self):
  103. tensor_placeholder = tf.placeholder(tf.float32, [None, 5, 4, 7])
  104. output_tensor = shape_utils.pad_or_clip_nd(
  105. tensor_placeholder, [None, 3, 5, tf.constant(6)])
  106. self.assertAllEqual(output_tensor.shape.as_list(), [None, 3, 5, None])
  107. with self.test_session() as sess:
  108. output_tensor_np = sess.run(
  109. output_tensor,
  110. feed_dict={
  111. tensor_placeholder: np.random.rand(2, 5, 4, 7),
  112. })
  113. self.assertAllEqual(output_tensor_np.shape, [2, 3, 5, 6])
  114. class StaticOrDynamicMapFnTest(tf.test.TestCase):
  115. def test_with_dynamic_shape(self):
  116. def fn(input_tensor):
  117. return tf.reduce_sum(input_tensor)
  118. input_tensor = tf.placeholder(tf.float32, shape=(None, 2))
  119. map_fn_output = shape_utils.static_or_dynamic_map_fn(fn, input_tensor)
  120. op_names = [op.name for op in tf.get_default_graph().get_operations()]
  121. self.assertTrue(any(['map' == op_name[:3] for op_name in op_names]))
  122. with self.test_session() as sess:
  123. result1 = sess.run(
  124. map_fn_output, feed_dict={
  125. input_tensor: [[1, 2], [3, 1], [0, 4]]})
  126. result2 = sess.run(
  127. map_fn_output, feed_dict={
  128. input_tensor: [[-1, 1], [0, 9]]})
  129. self.assertAllEqual(result1, [3, 4, 4])
  130. self.assertAllEqual(result2, [0, 9])
  131. def test_with_static_shape(self):
  132. def fn(input_tensor):
  133. return tf.reduce_sum(input_tensor)
  134. input_tensor = tf.constant([[1, 2], [3, 1], [0, 4]], dtype=tf.float32)
  135. map_fn_output = shape_utils.static_or_dynamic_map_fn(fn, input_tensor)
  136. op_names = [op.name for op in tf.get_default_graph().get_operations()]
  137. self.assertTrue(all(['map' != op_name[:3] for op_name in op_names]))
  138. with self.test_session() as sess:
  139. result = sess.run(map_fn_output)
  140. self.assertAllEqual(result, [3, 4, 4])
  141. def test_with_multiple_dynamic_shapes(self):
  142. def fn(elems):
  143. input_tensor, scalar_index_tensor = elems
  144. return tf.reshape(tf.slice(input_tensor, scalar_index_tensor, [1]), [])
  145. input_tensor = tf.placeholder(tf.float32, shape=(None, 3))
  146. scalar_index_tensor = tf.placeholder(tf.int32, shape=(None, 1))
  147. map_fn_output = shape_utils.static_or_dynamic_map_fn(
  148. fn, [input_tensor, scalar_index_tensor], dtype=tf.float32)
  149. op_names = [op.name for op in tf.get_default_graph().get_operations()]
  150. self.assertTrue(any(['map' == op_name[:3] for op_name in op_names]))
  151. with self.test_session() as sess:
  152. result1 = sess.run(
  153. map_fn_output, feed_dict={
  154. input_tensor: [[1, 2, 3], [4, 5, -1], [0, 6, 9]],
  155. scalar_index_tensor: [[0], [2], [1]],
  156. })
  157. result2 = sess.run(
  158. map_fn_output, feed_dict={
  159. input_tensor: [[-1, 1, 0], [3, 9, 30]],
  160. scalar_index_tensor: [[1], [0]]
  161. })
  162. self.assertAllEqual(result1, [1, -1, 6])
  163. self.assertAllEqual(result2, [1, 3])
  164. def test_with_multiple_static_shapes(self):
  165. def fn(elems):
  166. input_tensor, scalar_index_tensor = elems
  167. return tf.reshape(tf.slice(input_tensor, scalar_index_tensor, [1]), [])
  168. input_tensor = tf.constant([[1, 2, 3], [4, 5, -1], [0, 6, 9]],
  169. dtype=tf.float32)
  170. scalar_index_tensor = tf.constant([[0], [2], [1]], dtype=tf.int32)
  171. map_fn_output = shape_utils.static_or_dynamic_map_fn(
  172. fn, [input_tensor, scalar_index_tensor], dtype=tf.float32)
  173. op_names = [op.name for op in tf.get_default_graph().get_operations()]
  174. self.assertTrue(all(['map' != op_name[:3] for op_name in op_names]))
  175. with self.test_session() as sess:
  176. result = sess.run(map_fn_output)
  177. self.assertAllEqual(result, [1, -1, 6])
  178. def test_fails_with_nested_input(self):
  179. def fn(input_tensor):
  180. return input_tensor
  181. input_tensor1 = tf.constant([1])
  182. input_tensor2 = tf.constant([2])
  183. with self.assertRaisesRegexp(
  184. ValueError, '`elems` must be a Tensor or list of Tensors.'):
  185. shape_utils.static_or_dynamic_map_fn(
  186. fn, [input_tensor1, [input_tensor2]], dtype=tf.float32)
  187. class CheckMinImageShapeTest(tf.test.TestCase):
  188. def test_check_min_image_dim_static_shape(self):
  189. input_tensor = tf.constant(np.zeros([1, 42, 42, 3]))
  190. _ = shape_utils.check_min_image_dim(33, input_tensor)
  191. with self.assertRaisesRegexp(
  192. ValueError, 'image size must be >= 64 in both height and width.'):
  193. _ = shape_utils.check_min_image_dim(64, input_tensor)
  194. def test_check_min_image_dim_dynamic_shape(self):
  195. input_placeholder = tf.placeholder(tf.float32, shape=[1, None, None, 3])
  196. image_tensor = shape_utils.check_min_image_dim(33, input_placeholder)
  197. with self.test_session() as sess:
  198. sess.run(image_tensor,
  199. feed_dict={input_placeholder: np.zeros([1, 42, 42, 3])})
  200. with self.assertRaises(tf.errors.InvalidArgumentError):
  201. sess.run(image_tensor,
  202. feed_dict={input_placeholder: np.zeros([1, 32, 32, 3])})
  203. class AssertShapeEqualTest(tf.test.TestCase):
  204. def test_unequal_static_shape_raises_exception(self):
  205. shape_a = tf.constant(np.zeros([4, 2, 2, 1]))
  206. shape_b = tf.constant(np.zeros([4, 2, 3, 1]))
  207. with self.assertRaisesRegexp(
  208. ValueError, 'Unequal shapes'):
  209. shape_utils.assert_shape_equal(
  210. shape_utils.combined_static_and_dynamic_shape(shape_a),
  211. shape_utils.combined_static_and_dynamic_shape(shape_b))
  212. def test_equal_static_shape_succeeds(self):
  213. shape_a = tf.constant(np.zeros([4, 2, 2, 1]))
  214. shape_b = tf.constant(np.zeros([4, 2, 2, 1]))
  215. with self.test_session() as sess:
  216. op = shape_utils.assert_shape_equal(
  217. shape_utils.combined_static_and_dynamic_shape(shape_a),
  218. shape_utils.combined_static_and_dynamic_shape(shape_b))
  219. sess.run(op)
  220. def test_unequal_dynamic_shape_raises_tf_assert(self):
  221. tensor_a = tf.placeholder(tf.float32, shape=[1, None, None, 3])
  222. tensor_b = tf.placeholder(tf.float32, shape=[1, None, None, 3])
  223. op = shape_utils.assert_shape_equal(
  224. shape_utils.combined_static_and_dynamic_shape(tensor_a),
  225. shape_utils.combined_static_and_dynamic_shape(tensor_b))
  226. with self.test_session() as sess:
  227. with self.assertRaises(tf.errors.InvalidArgumentError):
  228. sess.run(op, feed_dict={tensor_a: np.zeros([1, 2, 2, 3]),
  229. tensor_b: np.zeros([1, 4, 4, 3])})
  230. def test_equal_dynamic_shape_succeeds(self):
  231. tensor_a = tf.placeholder(tf.float32, shape=[1, None, None, 3])
  232. tensor_b = tf.placeholder(tf.float32, shape=[1, None, None, 3])
  233. op = shape_utils.assert_shape_equal(
  234. shape_utils.combined_static_and_dynamic_shape(tensor_a),
  235. shape_utils.combined_static_and_dynamic_shape(tensor_b))
  236. with self.test_session() as sess:
  237. sess.run(op, feed_dict={tensor_a: np.zeros([1, 2, 2, 3]),
  238. tensor_b: np.zeros([1, 2, 2, 3])})
  239. def test_unequal_static_shape_along_first_dim_raises_exception(self):
  240. shape_a = tf.constant(np.zeros([4, 2, 2, 1]))
  241. shape_b = tf.constant(np.zeros([6, 2, 3, 1]))
  242. with self.assertRaisesRegexp(
  243. ValueError, 'Unequal first dimension'):
  244. shape_utils.assert_shape_equal_along_first_dimension(
  245. shape_utils.combined_static_and_dynamic_shape(shape_a),
  246. shape_utils.combined_static_and_dynamic_shape(shape_b))
  247. def test_equal_static_shape_along_first_dim_succeeds(self):
  248. shape_a = tf.constant(np.zeros([4, 2, 2, 1]))
  249. shape_b = tf.constant(np.zeros([4, 7, 2]))
  250. with self.test_session() as sess:
  251. op = shape_utils.assert_shape_equal_along_first_dimension(
  252. shape_utils.combined_static_and_dynamic_shape(shape_a),
  253. shape_utils.combined_static_and_dynamic_shape(shape_b))
  254. sess.run(op)
  255. def test_unequal_dynamic_shape_along_first_dim_raises_tf_assert(self):
  256. tensor_a = tf.placeholder(tf.float32, shape=[None, None, None, 3])
  257. tensor_b = tf.placeholder(tf.float32, shape=[None, None, 3])
  258. op = shape_utils.assert_shape_equal_along_first_dimension(
  259. shape_utils.combined_static_and_dynamic_shape(tensor_a),
  260. shape_utils.combined_static_and_dynamic_shape(tensor_b))
  261. with self.test_session() as sess:
  262. with self.assertRaises(tf.errors.InvalidArgumentError):
  263. sess.run(op, feed_dict={tensor_a: np.zeros([1, 2, 2, 3]),
  264. tensor_b: np.zeros([2, 4, 3])})
  265. def test_equal_dynamic_shape_along_first_dim_succeeds(self):
  266. tensor_a = tf.placeholder(tf.float32, shape=[None, None, None, 3])
  267. tensor_b = tf.placeholder(tf.float32, shape=[None])
  268. op = shape_utils.assert_shape_equal_along_first_dimension(
  269. shape_utils.combined_static_and_dynamic_shape(tensor_a),
  270. shape_utils.combined_static_and_dynamic_shape(tensor_b))
  271. with self.test_session() as sess:
  272. sess.run(op, feed_dict={tensor_a: np.zeros([5, 2, 2, 3]),
  273. tensor_b: np.zeros([5])})
  274. if __name__ == '__main__':
  275. tf.test.main()