test_predictor.py 16 KB

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