test_predictor.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. # Copyright (c) 2022 PaddlePaddle 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. import os.path as osp
  15. import tempfile
  16. import unittest.mock as mock
  17. import cv2
  18. import paddle
  19. import paddlers as pdrs
  20. from testing_utils import CommonTest, run_script
  21. __all__ = [
  22. 'TestCDPredictor', 'TestClasPredictor', 'TestDetPredictor',
  23. 'TestSegPredictor'
  24. ]
  25. class TestPredictor(CommonTest):
  26. MODULE = pdrs.tasks
  27. TRAINER_NAME_TO_EXPORT_OPTS = {}
  28. @staticmethod
  29. def add_tests(cls):
  30. """
  31. Automatically patch testing functions to cls.
  32. """
  33. def _test_predictor(trainer_name):
  34. def _test_predictor_impl(self):
  35. trainer_class = getattr(self.MODULE, trainer_name)
  36. # Construct trainer with default parameters
  37. trainer = trainer_class()
  38. with tempfile.TemporaryDirectory() as td:
  39. dynamic_model_dir = osp.join(td, "dynamic")
  40. static_model_dir = osp.join(td, "static")
  41. # HACK: BaseModel.save_model() requires BaseModel().optimizer to be set
  42. optimizer = mock.Mock()
  43. optimizer.state_dict.return_value = {'foo': 'bar'}
  44. trainer.optimizer = optimizer
  45. trainer.save_model(dynamic_model_dir)
  46. export_cmd = f"python export_model.py --model_dir {dynamic_model_dir} --save_dir {static_model_dir} "
  47. if trainer_name in self.TRAINER_NAME_TO_EXPORT_OPTS:
  48. export_cmd += self.TRAINER_NAME_TO_EXPORT_OPTS[
  49. trainer_name]
  50. elif '_default' in self.TRAINER_NAME_TO_EXPORT_OPTS:
  51. export_cmd += self.TRAINER_NAME_TO_EXPORT_OPTS[
  52. '_default']
  53. run_script(export_cmd, wd="../deploy/export")
  54. # Construct predictor
  55. # TODO: Test trt and mkl
  56. predictor = pdrs.deploy.Predictor(
  57. static_model_dir,
  58. use_gpu=paddle.device.get_device().startswith('gpu'))
  59. self.check_predictor(predictor, trainer)
  60. return _test_predictor_impl
  61. for trainer_name in cls.MODULE.__all__:
  62. setattr(cls, 'test_' + trainer_name, _test_predictor(trainer_name))
  63. return cls
  64. def check_predictor(self, predictor, trainer):
  65. raise NotImplementedError
  66. def check_dict_equal(self, dict_, expected_dict):
  67. if isinstance(dict_, list):
  68. self.assertIsInstance(expected_dict, list)
  69. self.assertEqual(len(dict_), len(expected_dict))
  70. for d1, d2 in zip(dict_, expected_dict):
  71. self.check_dict_equal(d1, d2)
  72. else:
  73. assert isinstance(dict_, dict)
  74. assert isinstance(expected_dict, dict)
  75. self.assertEqual(dict_.keys(), expected_dict.keys())
  76. for key in dict_.keys():
  77. self.check_output_equal(dict_[key], expected_dict[key])
  78. @TestPredictor.add_tests
  79. class TestCDPredictor(TestPredictor):
  80. MODULE = pdrs.tasks.change_detector
  81. TRAINER_NAME_TO_EXPORT_OPTS = {
  82. 'BIT': "--fixed_input_shape [1,3,256,256]",
  83. '_default': "--fixed_input_shape [-1,3,256,256]"
  84. }
  85. def check_predictor(self, predictor, trainer):
  86. t1_path = "data/ssmt/optical_t1.bmp"
  87. t2_path = "data/ssmt/optical_t2.bmp"
  88. single_input = (t1_path, t2_path)
  89. num_inputs = 2
  90. transforms = pdrs.transforms.Compose([pdrs.transforms.Normalize()])
  91. # Expected failure
  92. with self.assertRaises(ValueError):
  93. predictor.predict(t1_path, transforms=transforms)
  94. # Single input (file paths)
  95. input_ = single_input
  96. out_single_file_p = predictor.predict(input_, transforms=transforms)
  97. out_single_file_t = trainer.predict(input_, transforms=transforms)
  98. self.check_dict_equal(out_single_file_p, out_single_file_t)
  99. out_single_file_list_p = predictor.predict(
  100. [input_], transforms=transforms)
  101. self.assertEqual(len(out_single_file_list_p), 1)
  102. self.check_dict_equal(out_single_file_list_p[0], out_single_file_p)
  103. out_single_file_list_t = trainer.predict(
  104. [input_], transforms=transforms)
  105. self.check_dict_equal(out_single_file_list_p[0],
  106. out_single_file_list_t[0])
  107. # Single input (ndarrays)
  108. input_ = (
  109. cv2.imread(t1_path).astype('float32'),
  110. cv2.imread(t2_path).astype('float32')) # Reuse the name `input_`
  111. out_single_array_p = predictor.predict(input_, transforms=transforms)
  112. self.check_dict_equal(out_single_array_p, out_single_file_p)
  113. out_single_array_t = trainer.predict(input_, transforms=transforms)
  114. self.check_dict_equal(out_single_array_p, out_single_array_t)
  115. out_single_array_list_p = predictor.predict(
  116. [input_], transforms=transforms)
  117. self.assertEqual(len(out_single_array_list_p), 1)
  118. self.check_dict_equal(out_single_array_list_p[0], out_single_array_p)
  119. out_single_array_list_t = trainer.predict(
  120. [input_], transforms=transforms)
  121. self.check_dict_equal(out_single_array_list_p[0],
  122. out_single_array_list_t[0])
  123. if isinstance(trainer, pdrs.tasks.change_detector.BIT):
  124. return
  125. # Multiple inputs (file paths)
  126. input_ = [single_input] * num_inputs # Reuse the name `input_`
  127. out_multi_file_p = predictor.predict(input_, transforms=transforms)
  128. self.assertEqual(len(out_multi_file_p), num_inputs)
  129. out_multi_file_t = trainer.predict(input_, transforms=transforms)
  130. self.check_dict_equal(out_multi_file_p, out_multi_file_t)
  131. # Multiple inputs (ndarrays)
  132. input_ = [(cv2.imread(t1_path).astype('float32'), cv2.imread(t2_path)
  133. .astype('float32'))] * num_inputs # Reuse the name `input_`
  134. out_multi_array_p = predictor.predict(input_, transforms=transforms)
  135. self.assertEqual(len(out_multi_array_p), num_inputs)
  136. out_multi_array_t = trainer.predict(input_, transforms=transforms)
  137. self.check_dict_equal(out_multi_array_p, out_multi_array_t)
  138. @TestPredictor.add_tests
  139. class TestClasPredictor(TestPredictor):
  140. MODULE = pdrs.tasks.classifier
  141. TRAINER_NAME_TO_EXPORT_OPTS = {
  142. '_default': "--fixed_input_shape [-1,3,256,256]"
  143. }
  144. def check_predictor(self, predictor, trainer):
  145. single_input = "data/ssmt/optical_t1.bmp"
  146. num_inputs = 2
  147. transforms = pdrs.transforms.Compose([pdrs.transforms.Normalize()])
  148. labels = list(range(2))
  149. trainer.labels = labels
  150. predictor._model.labels = labels
  151. # Single input (file path)
  152. input_ = single_input
  153. out_single_file_p = predictor.predict(input_, transforms=transforms)
  154. out_single_file_t = trainer.predict(input_, transforms=transforms)
  155. self.check_dict_equal(out_single_file_p, out_single_file_t)
  156. out_single_file_list_p = predictor.predict(
  157. [input_], transforms=transforms)
  158. self.assertEqual(len(out_single_file_list_p), 1)
  159. self.check_dict_equal(out_single_file_list_p[0], out_single_file_p)
  160. out_single_file_list_t = trainer.predict(
  161. [input_], transforms=transforms)
  162. self.check_dict_equal(out_single_file_list_p[0],
  163. out_single_file_list_t[0])
  164. # Single input (ndarray)
  165. input_ = cv2.imread(single_input).astype(
  166. 'float32') # Reuse the name `input_`
  167. out_single_array_p = predictor.predict(input_, transforms=transforms)
  168. self.check_dict_equal(out_single_array_p, out_single_file_p)
  169. out_single_array_t = trainer.predict(input_, transforms=transforms)
  170. self.check_dict_equal(out_single_array_p, out_single_array_t)
  171. out_single_array_list_p = predictor.predict(
  172. [input_], transforms=transforms)
  173. self.assertEqual(len(out_single_array_list_p), 1)
  174. self.check_dict_equal(out_single_array_list_p[0], out_single_array_p)
  175. out_single_array_list_t = trainer.predict(
  176. [input_], transforms=transforms)
  177. self.check_dict_equal(out_single_array_list_p[0],
  178. out_single_array_list_t[0])
  179. # Multiple inputs (file paths)
  180. input_ = [single_input] * num_inputs # Reuse the name `input_`
  181. out_multi_file_p = predictor.predict(input_, transforms=transforms)
  182. self.assertEqual(len(out_multi_file_p), num_inputs)
  183. out_multi_file_t = trainer.predict(input_, transforms=transforms)
  184. self.assertEqual(len(out_multi_file_p), len(out_multi_file_t))
  185. self.check_dict_equal(out_multi_file_p, out_multi_file_t)
  186. # Multiple inputs (ndarrays)
  187. input_ = [cv2.imread(single_input).astype('float32')
  188. ] * num_inputs # Reuse the name `input_`
  189. out_multi_array_p = predictor.predict(input_, transforms=transforms)
  190. self.assertEqual(len(out_multi_array_p), num_inputs)
  191. out_multi_array_t = trainer.predict(input_, transforms=transforms)
  192. self.assertEqual(len(out_multi_array_p), len(out_multi_array_t))
  193. self.check_dict_equal(out_multi_array_p, out_multi_array_t)
  194. @TestPredictor.add_tests
  195. class TestDetPredictor(TestPredictor):
  196. MODULE = pdrs.tasks.object_detector
  197. TRAINER_NAME_TO_EXPORT_OPTS = {
  198. '_default': "--fixed_input_shape [-1,3,256,256]"
  199. }
  200. def check_predictor(self, predictor, trainer):
  201. single_input = "data/ssmt/optical_t1.bmp"
  202. num_inputs = 2
  203. transforms = pdrs.transforms.Compose([pdrs.transforms.Normalize()])
  204. labels = list(range(80))
  205. trainer.labels = labels
  206. predictor._model.labels = labels
  207. # Single input (file path)
  208. input_ = single_input
  209. out_single_file_p = predictor.predict(input_, transforms=transforms)
  210. out_single_file_t = trainer.predict(input_, transforms=transforms)
  211. self.check_dict_equal(out_single_file_p, out_single_file_t)
  212. out_single_file_list_p = predictor.predict(
  213. [input_], transforms=transforms)
  214. self.assertEqual(len(out_single_file_list_p), 1)
  215. self.check_dict_equal(out_single_file_list_p[0], out_single_file_p)
  216. out_single_file_list_t = trainer.predict(
  217. [input_], transforms=transforms)
  218. self.check_dict_equal(out_single_file_list_p[0],
  219. out_single_file_list_t[0])
  220. # Single input (ndarray)
  221. input_ = cv2.imread(single_input).astype(
  222. 'float32') # Reuse the name `input_`
  223. out_single_array_p = predictor.predict(input_, transforms=transforms)
  224. self.check_dict_equal(out_single_array_p, out_single_file_p)
  225. out_single_array_t = trainer.predict(input_, transforms=transforms)
  226. self.check_dict_equal(out_single_array_p, out_single_array_t)
  227. out_single_array_list_p = predictor.predict(
  228. [input_], transforms=transforms)
  229. self.assertEqual(len(out_single_array_list_p), 1)
  230. self.check_dict_equal(out_single_array_list_p[0], out_single_array_p)
  231. out_single_array_list_t = trainer.predict(
  232. [input_], transforms=transforms)
  233. self.check_dict_equal(out_single_array_list_p[0],
  234. out_single_array_list_t[0])
  235. # Multiple inputs (file paths)
  236. input_ = [single_input] * num_inputs # Reuse the name `input_`
  237. out_multi_file_p = predictor.predict(input_, transforms=transforms)
  238. self.assertEqual(len(out_multi_file_p), num_inputs)
  239. out_multi_file_t = trainer.predict(input_, transforms=transforms)
  240. self.assertEqual(len(out_multi_file_p), len(out_multi_file_t))
  241. self.check_dict_equal(out_multi_file_p, out_multi_file_t)
  242. # Multiple inputs (ndarrays)
  243. input_ = [cv2.imread(single_input).astype('float32')
  244. ] * num_inputs # Reuse the name `input_`
  245. out_multi_array_p = predictor.predict(input_, transforms=transforms)
  246. self.assertEqual(len(out_multi_array_p), num_inputs)
  247. out_multi_array_t = trainer.predict(input_, transforms=transforms)
  248. self.assertEqual(len(out_multi_array_p), len(out_multi_array_t))
  249. self.check_dict_equal(out_multi_array_p, out_multi_array_t)
  250. @TestPredictor.add_tests
  251. class TestSegPredictor(TestPredictor):
  252. MODULE = pdrs.tasks.segmenter
  253. TRAINER_NAME_TO_EXPORT_OPTS = {
  254. '_default': "--fixed_input_shape [-1,3,256,256]"
  255. }
  256. def check_predictor(self, predictor, trainer):
  257. single_input = "data/ssmt/optical_t1.bmp"
  258. num_inputs = 2
  259. transforms = pdrs.transforms.Compose([pdrs.transforms.Normalize()])
  260. # Single input (file path)
  261. input_ = single_input
  262. out_single_file_p = predictor.predict(input_, transforms=transforms)
  263. out_single_file_t = trainer.predict(input_, transforms=transforms)
  264. self.check_dict_equal(out_single_file_p, out_single_file_t)
  265. out_single_file_list_p = predictor.predict(
  266. [input_], transforms=transforms)
  267. self.assertEqual(len(out_single_file_list_p), 1)
  268. self.check_dict_equal(out_single_file_list_p[0], out_single_file_p)
  269. out_single_file_list_t = trainer.predict(
  270. [input_], transforms=transforms)
  271. self.check_dict_equal(out_single_file_list_p[0],
  272. out_single_file_list_t[0])
  273. # Single input (ndarray)
  274. input_ = cv2.imread(single_input).astype(
  275. 'float32') # Reuse the name `input_`
  276. out_single_array_p = predictor.predict(input_, transforms=transforms)
  277. self.check_dict_equal(out_single_array_p, out_single_file_p)
  278. out_single_array_t = trainer.predict(input_, transforms=transforms)
  279. self.check_dict_equal(out_single_array_p, out_single_array_t)
  280. out_single_array_list_p = predictor.predict(
  281. [input_], transforms=transforms)
  282. self.assertEqual(len(out_single_array_list_p), 1)
  283. self.check_dict_equal(out_single_array_list_p[0], out_single_array_p)
  284. out_single_array_list_t = trainer.predict(
  285. [input_], transforms=transforms)
  286. self.check_dict_equal(out_single_array_list_p[0],
  287. out_single_array_list_t[0])
  288. # Multiple inputs (file paths)
  289. input_ = [single_input] * num_inputs # Reuse the name `input_`
  290. out_multi_file_p = predictor.predict(input_, transforms=transforms)
  291. self.assertEqual(len(out_multi_file_p), num_inputs)
  292. out_multi_file_t = trainer.predict(input_, transforms=transforms)
  293. self.assertEqual(len(out_multi_file_p), len(out_multi_file_t))
  294. self.check_dict_equal(out_multi_file_p, out_multi_file_t)
  295. # Multiple inputs (ndarrays)
  296. input_ = [cv2.imread(single_input).astype('float32')
  297. ] * num_inputs # Reuse the name `input_`
  298. out_multi_array_p = predictor.predict(input_, transforms=transforms)
  299. self.assertEqual(len(out_multi_array_p), num_inputs)
  300. out_multi_array_t = trainer.predict(input_, transforms=transforms)
  301. self.assertEqual(len(out_multi_array_p), len(out_multi_array_t))
  302. self.check_dict_equal(out_multi_array_p, out_multi_array_t)