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

warp_perspective.cpp 8.7 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /**
  2. * \file dnn/test/common/warp_perspective.cpp
  3. * MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  4. *
  5. * Copyright (c) 2014-2020 Megvii Inc. All rights reserved.
  6. *
  7. * Unless required by applicable law or agreed to in writing,
  8. * software distributed under the License is distributed on an
  9. * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. */
  11. #include "test/common/warp_perspective.h"
  12. #include "test/common/benchmarker.h"
  13. #include "test/common/checker.h"
  14. using namespace megdnn;
  15. using namespace test;
  16. using namespace warp_perspective;
  17. void WarpPerspectiveMatIdxProxy::deduce_layout(WarpPerspective*,
  18. TensorLayoutArray&) {}
  19. void WarpPerspectiveMatIdxProxy::exec(WarpPerspective* opr,
  20. const TensorNDArray& tensors) {
  21. if (!W.valid()) {
  22. W = WorkspaceWrapper(opr->handle(), 0);
  23. }
  24. megdnn_assert(tensors.size() == 4);
  25. W.update(opr->get_workspace_in_bytes(tensors[0].layout, tensors[1].layout,
  26. tensors[2].layout, tensors[3].layout));
  27. opr->exec(tensors[0], tensors[1], tensors[2], tensors[3], W.workspace());
  28. }
  29. std::vector<TestArg> warp_perspective::get_cv_args() {
  30. std::vector<TestArg> args;
  31. // in warp_perspective_cv INTER_AREA == INTER_LINEAR
  32. using BorderMode = param::WarpPerspective::BorderMode;
  33. using InterpolationMode = param::WarpPerspective::InterpolationMode;
  34. param::WarpPerspective cur_param;
  35. for (size_t i = 4; i < 129; i *= 4) {
  36. for (size_t ic : {1, 2, 3}) {
  37. for (BorderMode bmode : {
  38. BorderMode::REPLICATE,
  39. BorderMode::REFLECT,
  40. BorderMode::REFLECT_101,
  41. BorderMode::WRAP,
  42. BorderMode::CONSTANT,
  43. }) {
  44. for (InterpolationMode imode :
  45. {InterpolationMode::NEAREST, InterpolationMode::LINEAR,
  46. InterpolationMode::CUBIC, InterpolationMode::LANCZOS4}) {
  47. cur_param.bmode = bmode;
  48. cur_param.format = param::WarpPerspective::Format::NHWC;
  49. cur_param.imode = imode;
  50. args.emplace_back(cur_param, TensorShape{1, i, i, ic},
  51. TensorShape{1, 3, 3}, TensorShape{1},
  52. TensorShape{1, i, i, ic});
  53. args.emplace_back(cur_param, TensorShape{1, i, i * 2, ic},
  54. TensorShape{1, 3, 3}, TensorShape{1},
  55. TensorShape{1, i, i * 2, ic});
  56. args.emplace_back(cur_param, TensorShape{1, i * 3, i, ic},
  57. TensorShape{1, 3, 3}, TensorShape{1},
  58. TensorShape{1, i * 3, i, ic});
  59. cur_param.border_val = 0.78f;
  60. args.emplace_back(cur_param, TensorShape{1, i, i, ic},
  61. TensorShape{1, 3, 3}, TensorShape{1},
  62. TensorShape{1, 8, 8, ic});
  63. args.emplace_back(cur_param, TensorShape{1, i, i * 2, ic},
  64. TensorShape{1, 3, 3}, TensorShape{1},
  65. TensorShape{1, 8, 8, ic});
  66. args.emplace_back(cur_param, TensorShape{1, i * 3, i, ic},
  67. TensorShape{1, 3, 3}, TensorShape{1},
  68. TensorShape{1, 8, 8, ic});
  69. }
  70. }
  71. }
  72. }
  73. return args;
  74. }
  75. void warp_perspective::run_mat_idx_test(Handle* handle) {
  76. constexpr int N_SRC = 5;
  77. Checker<WarpPerspectiveForward, WarpPerspectiveMatIdxProxy> checker(handle);
  78. WarpPerspectiveMatRNG mat_rng;
  79. checker.set_rng(1, &mat_rng);
  80. UniformIntRNG mat_idx_rng{0, N_SRC - 1};
  81. checker.set_dtype(2, dtype::Int32());
  82. checker.set_rng(2, &mat_idx_rng);
  83. WarpPerspective::Param param;
  84. param.bmode = WarpPerspective::Param::BorderMode::REFLECT;
  85. param.imode = param::WarpPerspective::InterpolationMode::LINEAR;
  86. checker.set_param(param);
  87. checker.execs({{N_SRC, 3, 10, 11}, {2, 3, 3}, {2}, {2, 3, 11, 12}});
  88. checker.execs({{N_SRC, 14, 17, 13}, {123, 3, 3}, {123}, {123, 14, 16, 15}});
  89. // test NHWC
  90. param.format = WarpPerspective::Param::Format::NHWC;
  91. checker.set_param(param)
  92. .set_rng(2, &mat_idx_rng)
  93. .set_epsilon(1e-1)
  94. .set_dtype(2, dtype::Int32());
  95. checker.execs({{N_SRC, 10, 11, 3}, {2, 3, 3}, {2}, {2, 11, 12, 3}});
  96. }
  97. void warp_perspective::run_int8_test(Handle* handle) {
  98. using Param = WarpPerspective::Param;
  99. Checker<WarpPerspectiveForward> checker(handle);
  100. UniformIntRNG input_rng{-128, 127};
  101. WarpPerspectiveMatRNG mat_rng;
  102. class ResizeBy2xMatRNG : public RNG {
  103. void gen(const TensorND& tensor_) override {
  104. float* ptr = tensor_.ptr<float>();
  105. auto N = tensor_.layout.shape[0];
  106. megdnn_assert(tensor_.layout.is_contiguous() &&
  107. tensor_.layout.ndim == 3 && tensor_.layout[1] == 3 &&
  108. tensor_.layout[2] == 3);
  109. for (size_t n = 0; n < N; ++n) {
  110. // | 1 0 0 |
  111. // mat = | 0 1 0 |
  112. // | 0 0 2 |
  113. // resize_2x
  114. ptr[0] = ptr[4] = 1;
  115. ptr[8] = 2;
  116. ptr[1] = ptr[2] = ptr[3] = ptr[5] = ptr[6] = ptr[7] = 0;
  117. ptr += 9;
  118. }
  119. }
  120. } resize_2x_mat_rng;
  121. if (handle->type() == Handle::HandleType::CUDA) {
  122. // As currently the computation is performed in floating points instead
  123. // of full int, it could be slightly different on GPU.
  124. checker.set_epsilon(1.1).set_max_avg_error(7e-5);
  125. }
  126. checker.set_rng(0, &input_rng)
  127. .set_rng(1, &mat_rng)
  128. .set_dtype(0, dtype::Int8())
  129. .set_dtype(1, dtype::Float32())
  130. .set_dtype(2, dtype::Int8())
  131. .set_param({Param::InterpolationMode::LINEAR,
  132. Param::BorderMode::CONSTANT, Param::Format::NCHW, 0.f});
  133. checker.execs({{99, 48, 17, 17}, {99, 3, 3}, {99, 48, 22, 22}})
  134. .execs({{12, 3, 224, 224}, {12, 3, 3}, {12, 3, 256, 256}});
  135. checker.set_rng(1, &resize_2x_mat_rng);
  136. checker.execs({{98, 48, 17, 17}, {98, 3, 3}, {98, 48, 34, 34}})
  137. .execs({{13, 3, 224, 224}, {13, 3, 3}, {13, 3, 448, 448}});
  138. }
  139. void warp_perspective::run_quint8_test(Handle* handle) {
  140. using Param = WarpPerspective::Param;
  141. Checker<WarpPerspectiveForward> checker(handle);
  142. UniformIntRNG input_rng{0, 255};
  143. WarpPerspectiveMatRNG mat_rng;
  144. class ResizeBy2xMatRNG : public RNG {
  145. void gen(const TensorND& tensor_) override {
  146. float* ptr = tensor_.ptr<float>();
  147. auto N = tensor_.layout.shape[0];
  148. megdnn_assert(tensor_.layout.is_contiguous() &&
  149. tensor_.layout.ndim == 3 && tensor_.layout[1] == 3 &&
  150. tensor_.layout[2] == 3);
  151. for (size_t n = 0; n < N; ++n) {
  152. // | 1 0 0 |
  153. // mat = | 0 1 0 |
  154. // | 0 0 2 |
  155. // resize_2x
  156. ptr[0] = ptr[4] = 1;
  157. ptr[8] = 2;
  158. ptr[1] = ptr[2] = ptr[3] = ptr[5] = ptr[6] = ptr[7] = 0;
  159. ptr += 9;
  160. }
  161. }
  162. } resize_2x_mat_rng;
  163. if (handle->type() == Handle::HandleType::CUDA) {
  164. // As currently the computation is performed in floating points instead
  165. // of full int, it could be slightly different on GPU.
  166. checker.set_epsilon(1.1).set_max_avg_error(7e-5);
  167. }
  168. checker.set_rng(0, &input_rng)
  169. .set_rng(1, &mat_rng)
  170. .set_dtype(0,
  171. dtype::Quantized8Asymm(0.6f, static_cast<uint8_t>(127)))
  172. .set_dtype(1, dtype::Float32())
  173. .set_dtype(2,
  174. dtype::Quantized8Asymm(0.6f, static_cast<uint8_t>(127)))
  175. .set_param({Param::InterpolationMode::LINEAR,
  176. Param::BorderMode::CONSTANT, Param::Format::NCHW, 0.f});
  177. checker.execs({{99, 48, 17, 17}, {99, 3, 3}, {99, 48, 22, 22}})
  178. .execs({{12, 3, 224, 224}, {12, 3, 3}, {12, 3, 256, 256}});
  179. checker.set_rng(1, &resize_2x_mat_rng);
  180. checker.execs({{98, 48, 17, 17}, {98, 3, 3}, {98, 48, 34, 34}})
  181. .execs({{13, 3, 224, 224}, {13, 3, 3}, {13, 3, 448, 448}});
  182. }
  183. // vim: syntax=cpp.doxygen

MegEngine 安装包中集成了使用 GPU 运行代码所需的 CUDA 环境,不用区分 CPU 和 GPU 版。 如果想要运行 GPU 程序,请确保机器本身配有 GPU 硬件设备并安装好驱动。 如果你想体验在云端 GPU 算力平台进行深度学习开发的感觉,欢迎访问 MegStudio 平台