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.

interp.cpp 16 kB

7 years ago
Fix warnings on Visual Studio (#1431) * Fix warnings C4244, C4267 in src/layer/yolov3detectionoutput.cpp C4244: '=': conversion from 'int' to 'float', possible loss of data C4244: 'initializing': conversion from 'float' to 'int', possible loss of data C4244: 'initializing': conversion from 'double' to 'float', possible loss of data C4244: 'return': conversion from 'double' to 'float', possible loss of data C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data * Fix warnings C4244, C4267 in src/layer/yolodetectionoutput.cpp C4244: '=': conversion from 'int' to 'float', possible loss of data C4244: 'initializing': conversion from 'float' to 'int', possible loss of data C4244: 'initializing': conversion from 'double' to 'float', possible loss of data C4244: 'return': conversion from 'double' to 'float', possible loss of data C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data * Fix warning C4244 in src/layer/quantize.cpp C4244: 'initializing': conversion from 'double' to 'int', possible loss of data * Fix warnings C4244, C4267 in src/layer/detectionoutput.cpp C4244: '=': conversion from 'int' to 'float', possible loss of data C4244: 'initializing': conversion from 'double' to 'float', possible loss of data C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data * Fix warning C4244 in src/layer/roipooling.cpp C4244: 'initializing': conversion from 'double' to 'int', possible loss of data * Fix warning C4244 in src/layer/sigmoid.cpp C4244: '=': conversion from 'double' to 'float', possible loss of data * Fix warning C4267 in src/layer/slice.cpp C4267: '=': conversion from 'size_t' to 'int', possible loss of data C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data * Fix warning C4267 in src/layer/softmax.cpp C4244: '=': conversion from 'double' to 'float', possible loss of data * Fix warning C4244 in src/layer/interp.cpp C4244: '=': conversion from 'float' to 'int', possible loss of data C4244: 'initializing': conversion from 'double' to 'int', possible loss of data * Fix warning C4244 in src/layer/instancenorm.cpp C4244: 'initializing': conversion from 'double' to 'float', possible loss of data * Fix warning C4244 in src/layer/deconvolutiondepthwise.cpp C4244: '=': conversion from 'double' to 'float', possible loss of data * Fix warning C4244 in src/layer/convolutiondepthwise.cpp C4244: '=': conversion from 'double' to 'float', possible loss of data * Fix warning C4244 in src/net.cpp C4244: 'return': conversion from '__int64' to 'int', possible loss of data C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data C4267: 'return': conversion from 'size_t' to 'int', possible loss of data * Fix warning C4244 in src/layer/bnll.cpp C4244: '=': conversion from 'double' to 'float', possible loss of data * Fix warning C4267 in src/layer/concat.cpp C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data * Fix warning C4267 in tools/mxnet/mxnet2ncnn.cpp C4244: 'initializing': conversion from 'double' to 'float', possible loss of data C4267: '=': conversion from 'size_t' to 'int', possible loss of data C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data C4305: 'initializing': truncation from 'double' to 'float'
6 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
Fix warnings on Visual Studio (#1431) * Fix warnings C4244, C4267 in src/layer/yolov3detectionoutput.cpp C4244: '=': conversion from 'int' to 'float', possible loss of data C4244: 'initializing': conversion from 'float' to 'int', possible loss of data C4244: 'initializing': conversion from 'double' to 'float', possible loss of data C4244: 'return': conversion from 'double' to 'float', possible loss of data C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data * Fix warnings C4244, C4267 in src/layer/yolodetectionoutput.cpp C4244: '=': conversion from 'int' to 'float', possible loss of data C4244: 'initializing': conversion from 'float' to 'int', possible loss of data C4244: 'initializing': conversion from 'double' to 'float', possible loss of data C4244: 'return': conversion from 'double' to 'float', possible loss of data C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data * Fix warning C4244 in src/layer/quantize.cpp C4244: 'initializing': conversion from 'double' to 'int', possible loss of data * Fix warnings C4244, C4267 in src/layer/detectionoutput.cpp C4244: '=': conversion from 'int' to 'float', possible loss of data C4244: 'initializing': conversion from 'double' to 'float', possible loss of data C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data * Fix warning C4244 in src/layer/roipooling.cpp C4244: 'initializing': conversion from 'double' to 'int', possible loss of data * Fix warning C4244 in src/layer/sigmoid.cpp C4244: '=': conversion from 'double' to 'float', possible loss of data * Fix warning C4267 in src/layer/slice.cpp C4267: '=': conversion from 'size_t' to 'int', possible loss of data C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data * Fix warning C4267 in src/layer/softmax.cpp C4244: '=': conversion from 'double' to 'float', possible loss of data * Fix warning C4244 in src/layer/interp.cpp C4244: '=': conversion from 'float' to 'int', possible loss of data C4244: 'initializing': conversion from 'double' to 'int', possible loss of data * Fix warning C4244 in src/layer/instancenorm.cpp C4244: 'initializing': conversion from 'double' to 'float', possible loss of data * Fix warning C4244 in src/layer/deconvolutiondepthwise.cpp C4244: '=': conversion from 'double' to 'float', possible loss of data * Fix warning C4244 in src/layer/convolutiondepthwise.cpp C4244: '=': conversion from 'double' to 'float', possible loss of data * Fix warning C4244 in src/net.cpp C4244: 'return': conversion from '__int64' to 'int', possible loss of data C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data C4267: 'return': conversion from 'size_t' to 'int', possible loss of data * Fix warning C4244 in src/layer/bnll.cpp C4244: '=': conversion from 'double' to 'float', possible loss of data * Fix warning C4267 in src/layer/concat.cpp C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data * Fix warning C4267 in tools/mxnet/mxnet2ncnn.cpp C4244: 'initializing': conversion from 'double' to 'float', possible loss of data C4267: '=': conversion from 'size_t' to 'int', possible loss of data C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data C4305: 'initializing': truncation from 'double' to 'float'
6 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. // Tencent is pleased to support the open source community by making ncnn available.
  2. //
  3. // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
  4. //
  5. // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // https://opensource.org/licenses/BSD-3-Clause
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed
  11. // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  12. // CONDITIONS OF ANY KIND, either express or implied. See the License for the
  13. // specific language governing permissions and limitations under the License.
  14. #include "interp.h"
  15. namespace ncnn {
  16. Interp::Interp()
  17. {
  18. one_blob_only = true;
  19. support_inplace = false;
  20. }
  21. int Interp::load_param(const ParamDict& pd)
  22. {
  23. resize_type = pd.get(0, 0);
  24. height_scale = pd.get(1, 1.f);
  25. width_scale = pd.get(2, 1.f);
  26. output_height = pd.get(3, 0);
  27. output_width = pd.get(4, 0);
  28. dynamic_target_size = pd.get(5, 0);
  29. if (resize_type < 0 || resize_type > 3)
  30. {
  31. NCNN_LOGE("unsupported resize type %d", resize_type);
  32. return -1;
  33. }
  34. if (dynamic_target_size == 1)
  35. {
  36. one_blob_only = false;
  37. }
  38. return 0;
  39. }
  40. #if defined(__GNUC__) && defined(__powerpc__) && defined(__ALTIVEC__)
  41. // NOTE gcc altivec optimized version produce wrong result
  42. // so I have to disable vectorize here --- nihui
  43. __attribute__((optimize("no-tree-vectorize")))
  44. #endif
  45. static void linear_coeffs(int w, int outw, int* xofs, float* alpha)
  46. {
  47. double scale = (double)w / outw;
  48. for (int dx = 0; dx < outw; dx++)
  49. {
  50. float fx = (float)((dx + 0.5) * scale - 0.5);
  51. int sx = static_cast<int>(floor(fx));
  52. fx -= sx;
  53. if (sx < 0)
  54. {
  55. sx = 0;
  56. fx = 0.f;
  57. }
  58. if (sx >= w - 1)
  59. {
  60. sx = w - 2;
  61. fx = 1.f;
  62. }
  63. xofs[dx] = sx;
  64. alpha[dx * 2] = 1.f - fx;
  65. alpha[dx * 2 + 1] = fx;
  66. }
  67. }
  68. static void resize_bilinear_image(const Mat& src, Mat& dst, float* alpha, int* xofs, float* beta, int* yofs)
  69. {
  70. int w = dst.w;
  71. int h = dst.h;
  72. // loop body
  73. Mat rowsbuf0(w);
  74. Mat rowsbuf1(w);
  75. float* rows0 = rowsbuf0;
  76. float* rows1 = rowsbuf1;
  77. int prev_sy1 = -2;
  78. for (int dy = 0; dy < h; dy++)
  79. {
  80. int sy = yofs[dy];
  81. if (sy == prev_sy1)
  82. {
  83. // reuse all rows
  84. }
  85. else if (sy == prev_sy1 + 1)
  86. {
  87. // hresize one row
  88. float* rows0_old = rows0;
  89. rows0 = rows1;
  90. rows1 = rows0_old;
  91. const float* S1 = src.row(sy + 1);
  92. const float* alphap = alpha;
  93. float* rows1p = rows1;
  94. for (int dx = 0; dx < w; dx++)
  95. {
  96. int sx = xofs[dx];
  97. const float* S1p = S1 + sx;
  98. float a0 = alphap[0];
  99. float a1 = alphap[1];
  100. rows1p[dx] = S1p[0] * a0 + S1p[1] * a1;
  101. alphap += 2;
  102. }
  103. }
  104. else
  105. {
  106. // hresize two rows
  107. const float* S0 = src.row(sy);
  108. const float* S1 = src.row(sy + 1);
  109. const float* alphap = alpha;
  110. float* rows0p = rows0;
  111. float* rows1p = rows1;
  112. for (int dx = 0; dx < w; dx++)
  113. {
  114. int sx = xofs[dx];
  115. const float* S0p = S0 + sx;
  116. const float* S1p = S1 + sx;
  117. float a0 = alphap[0];
  118. float a1 = alphap[1];
  119. rows0p[dx] = S0p[0] * a0 + S0p[1] * a1;
  120. rows1p[dx] = S1p[0] * a0 + S1p[1] * a1;
  121. alphap += 2;
  122. }
  123. }
  124. prev_sy1 = sy;
  125. // vresize
  126. float b0 = beta[0];
  127. float b1 = beta[1];
  128. float* rows0p = rows0;
  129. float* rows1p = rows1;
  130. float* Dp = dst.row(dy);
  131. for (int dx = 0; dx < w; dx++)
  132. {
  133. // D[x] = rows0[x]*b0 + rows1[x]*b1;
  134. *Dp++ = *rows0p++ * b0 + *rows1p++ * b1;
  135. }
  136. beta += 2;
  137. }
  138. }
  139. static inline void interpolate_cubic(float fx, float* coeffs)
  140. {
  141. const float A = -0.75f;
  142. float fx0 = fx + 1;
  143. float fx1 = fx;
  144. float fx2 = 1 - fx;
  145. // float fx3 = 2 - fx;
  146. coeffs[0] = A * fx0 * fx0 * fx0 - 5 * A * fx0 * fx0 + 8 * A * fx0 - 4 * A;
  147. coeffs[1] = (A + 2) * fx1 * fx1 * fx1 - (A + 3) * fx1 * fx1 + 1;
  148. coeffs[2] = (A + 2) * fx2 * fx2 * fx2 - (A + 3) * fx2 * fx2 + 1;
  149. coeffs[3] = 1.f - coeffs[0] - coeffs[1] - coeffs[2];
  150. }
  151. static void cubic_coeffs(int w, int outw, int* xofs, float* alpha)
  152. {
  153. double scale = (double)w / outw;
  154. for (int dx = 0; dx < outw; dx++)
  155. {
  156. float fx = (float)((dx + 0.5) * scale - 0.5);
  157. int sx = static_cast<int>(floor(fx));
  158. fx -= sx;
  159. interpolate_cubic(fx, alpha + dx * 4);
  160. if (sx <= -1)
  161. {
  162. sx = 1;
  163. alpha[dx * 4 + 0] = 1.f - alpha[dx * 4 + 3];
  164. alpha[dx * 4 + 1] = alpha[dx * 4 + 3];
  165. alpha[dx * 4 + 2] = 0.f;
  166. alpha[dx * 4 + 3] = 0.f;
  167. }
  168. if (sx == 0)
  169. {
  170. sx = 1;
  171. alpha[dx * 4 + 0] = alpha[dx * 4 + 0] + alpha[dx * 4 + 1];
  172. alpha[dx * 4 + 1] = alpha[dx * 4 + 2];
  173. alpha[dx * 4 + 2] = alpha[dx * 4 + 3];
  174. alpha[dx * 4 + 3] = 0.f;
  175. }
  176. if (sx == w - 2)
  177. {
  178. sx = w - 3;
  179. alpha[dx * 4 + 3] = alpha[dx * 4 + 2] + alpha[dx * 4 + 3];
  180. alpha[dx * 4 + 2] = alpha[dx * 4 + 1];
  181. alpha[dx * 4 + 1] = alpha[dx * 4 + 0];
  182. alpha[dx * 4 + 0] = 0.f;
  183. }
  184. if (sx >= w - 1)
  185. {
  186. sx = w - 3;
  187. alpha[dx * 4 + 3] = 1.f - alpha[dx * 4 + 0];
  188. alpha[dx * 4 + 2] = alpha[dx * 4 + 0];
  189. alpha[dx * 4 + 1] = 0.f;
  190. alpha[dx * 4 + 0] = 0.f;
  191. }
  192. xofs[dx] = sx;
  193. }
  194. }
  195. static void resize_bicubic_image(const Mat& src, Mat& dst, float* alpha, int* xofs, float* beta, int* yofs)
  196. {
  197. int w = dst.w;
  198. int h = dst.h;
  199. // loop body
  200. Mat rowsbuf0(w);
  201. Mat rowsbuf1(w);
  202. Mat rowsbuf2(w);
  203. Mat rowsbuf3(w);
  204. float* rows0 = rowsbuf0;
  205. float* rows1 = rowsbuf1;
  206. float* rows2 = rowsbuf2;
  207. float* rows3 = rowsbuf3;
  208. int prev_sy1 = -3;
  209. for (int dy = 0; dy < h; dy++)
  210. {
  211. int sy = yofs[dy];
  212. if (sy == prev_sy1)
  213. {
  214. // reuse all rows
  215. }
  216. else if (sy == prev_sy1 + 1)
  217. {
  218. // hresize one row
  219. float* rows0_old = rows0;
  220. rows0 = rows1;
  221. rows1 = rows2;
  222. rows2 = rows3;
  223. rows3 = rows0_old;
  224. const float* S3 = src.row(sy + 2);
  225. const float* alphap = alpha;
  226. float* rows3p = rows3;
  227. for (int dx = 0; dx < w; dx++)
  228. {
  229. int sx = xofs[dx];
  230. const float* S3p = S3 + sx;
  231. float a0 = alphap[0];
  232. float a1 = alphap[1];
  233. float a2 = alphap[2];
  234. float a3 = alphap[3];
  235. rows3p[dx] = S3p[-1] * a0 + S3p[0] * a1 + S3p[1] * a2 + S3p[2] * a3;
  236. alphap += 4;
  237. }
  238. }
  239. else if (sy == prev_sy1 + 2)
  240. {
  241. // hresize two rows
  242. float* rows0_old = rows0;
  243. float* rows1_old = rows1;
  244. rows0 = rows2;
  245. rows1 = rows3;
  246. rows2 = rows0_old;
  247. rows3 = rows1_old;
  248. const float* S2 = src.row(sy + 1);
  249. const float* S3 = src.row(sy + 2);
  250. const float* alphap = alpha;
  251. float* rows2p = rows2;
  252. float* rows3p = rows3;
  253. for (int dx = 0; dx < w; dx++)
  254. {
  255. int sx = xofs[dx];
  256. const float* S2p = S2 + sx;
  257. const float* S3p = S3 + sx;
  258. float a0 = alphap[0];
  259. float a1 = alphap[1];
  260. float a2 = alphap[2];
  261. float a3 = alphap[3];
  262. rows2p[dx] = S2p[-1] * a0 + S2p[0] * a1 + S2p[1] * a2 + S2p[2] * a3;
  263. rows3p[dx] = S3p[-1] * a0 + S3p[0] * a1 + S3p[1] * a2 + S3p[2] * a3;
  264. alphap += 4;
  265. }
  266. }
  267. else if (sy == prev_sy1 + 3)
  268. {
  269. // hresize three rows
  270. float* rows0_old = rows0;
  271. float* rows1_old = rows1;
  272. float* rows2_old = rows2;
  273. rows0 = rows3;
  274. rows1 = rows0_old;
  275. rows2 = rows1_old;
  276. rows3 = rows2_old;
  277. const float* S1 = src.row(sy);
  278. const float* S2 = src.row(sy + 1);
  279. const float* S3 = src.row(sy + 2);
  280. const float* alphap = alpha;
  281. float* rows1p = rows1;
  282. float* rows2p = rows2;
  283. float* rows3p = rows3;
  284. for (int dx = 0; dx < w; dx++)
  285. {
  286. int sx = xofs[dx];
  287. const float* S1p = S1 + sx;
  288. const float* S2p = S2 + sx;
  289. const float* S3p = S3 + sx;
  290. float a0 = alphap[0];
  291. float a1 = alphap[1];
  292. float a2 = alphap[2];
  293. float a3 = alphap[3];
  294. rows1p[dx] = S1p[-1] * a0 + S1p[0] * a1 + S1p[1] * a2 + S1p[2] * a3;
  295. rows2p[dx] = S2p[-1] * a0 + S2p[0] * a1 + S2p[1] * a2 + S2p[2] * a3;
  296. rows3p[dx] = S3p[-1] * a0 + S3p[0] * a1 + S3p[1] * a2 + S3p[2] * a3;
  297. alphap += 4;
  298. }
  299. }
  300. else
  301. {
  302. // hresize four rows
  303. const float* S0 = src.row(sy - 1);
  304. const float* S1 = src.row(sy);
  305. const float* S2 = src.row(sy + 1);
  306. const float* S3 = src.row(sy + 2);
  307. const float* alphap = alpha;
  308. float* rows0p = rows0;
  309. float* rows1p = rows1;
  310. float* rows2p = rows2;
  311. float* rows3p = rows3;
  312. for (int dx = 0; dx < w; dx++)
  313. {
  314. int sx = xofs[dx];
  315. const float* S0p = S0 + sx;
  316. const float* S1p = S1 + sx;
  317. const float* S2p = S2 + sx;
  318. const float* S3p = S3 + sx;
  319. float a0 = alphap[0];
  320. float a1 = alphap[1];
  321. float a2 = alphap[2];
  322. float a3 = alphap[3];
  323. rows0p[dx] = S0p[-1] * a0 + S0p[0] * a1 + S0p[1] * a2 + S0p[2] * a3;
  324. rows1p[dx] = S1p[-1] * a0 + S1p[0] * a1 + S1p[1] * a2 + S1p[2] * a3;
  325. rows2p[dx] = S2p[-1] * a0 + S2p[0] * a1 + S2p[1] * a2 + S2p[2] * a3;
  326. rows3p[dx] = S3p[-1] * a0 + S3p[0] * a1 + S3p[1] * a2 + S3p[2] * a3;
  327. alphap += 4;
  328. }
  329. }
  330. prev_sy1 = sy;
  331. // vresize
  332. float b0 = beta[0];
  333. float b1 = beta[1];
  334. float b2 = beta[2];
  335. float b3 = beta[3];
  336. float* rows0p = rows0;
  337. float* rows1p = rows1;
  338. float* rows2p = rows2;
  339. float* rows3p = rows3;
  340. float* Dp = dst.row(dy);
  341. for (int dx = 0; dx < w; dx++)
  342. {
  343. // D[x] = rows0[x]*b0 + rows1[x]*b1 + rows2[x]*b2 + rows3[x]*b3;
  344. *Dp++ = *rows0p++ * b0 + *rows1p++ * b1 + *rows2p++ * b2 + *rows3p++ * b3;
  345. }
  346. beta += 4;
  347. }
  348. }
  349. int Interp::forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const
  350. {
  351. int w = bottom_blob.w;
  352. int h = bottom_blob.h;
  353. int channels = bottom_blob.c;
  354. int outh = output_height;
  355. int outw = output_width;
  356. if (bottom_blob.dims == 1)
  357. {
  358. h = 1;
  359. w = 1;
  360. channels = bottom_blob.w;
  361. }
  362. if (outh == 0 || outw == 0)
  363. {
  364. outh = static_cast<int>(h * height_scale);
  365. outw = static_cast<int>(w * width_scale);
  366. }
  367. Mat reference_blob;
  368. reference_blob.w = outw;
  369. reference_blob.h = outh;
  370. std::vector<Mat> bottom_blobs(2);
  371. bottom_blobs[0] = bottom_blob;
  372. bottom_blobs[1] = reference_blob;
  373. std::vector<Mat> top_blobs(1);
  374. int ret = forward(bottom_blobs, top_blobs, opt);
  375. top_blob = top_blobs[0];
  376. return ret;
  377. }
  378. int Interp::forward(const std::vector<Mat>& bottom_blobs, std::vector<Mat>& top_blobs, const Option& opt) const
  379. {
  380. const Mat& bottom_blob = bottom_blobs[0];
  381. const Mat& reference_blob = bottom_blobs[1];
  382. Mat& top_blob = top_blobs[0];
  383. int w = bottom_blob.w;
  384. int h = bottom_blob.h;
  385. int channels = bottom_blob.c;
  386. size_t elemsize = bottom_blob.elemsize;
  387. int outh = reference_blob.h;
  388. int outw = reference_blob.w;
  389. if (outh == h && outw == w)
  390. {
  391. top_blob = bottom_blob;
  392. return 0;
  393. }
  394. top_blob.create(outw, outh, channels, elemsize, opt.blob_allocator);
  395. if (top_blob.empty())
  396. return -100;
  397. if (bottom_blob.dims == 1)
  398. {
  399. #pragma omp parallel for num_threads(opt.num_threads)
  400. for (int q = 0; q < channels; q++)
  401. {
  402. Mat top_blob_c = top_blob.channel(q);
  403. const float* ptr = ((const float*)bottom_blob.data + q);
  404. top_blob_c.fill(*ptr);
  405. }
  406. return 0;
  407. }
  408. if (resize_type == 1) // nearest
  409. {
  410. const float hs = outh ? h / (float)outh : 1.f / height_scale;
  411. const float ws = outw ? w / (float)outw : 1.f / width_scale;
  412. #pragma omp parallel for num_threads(opt.num_threads)
  413. for (int q = 0; q < channels; q++)
  414. {
  415. const float* ptr = bottom_blob.channel(q);
  416. float* outptr = top_blob.channel(q);
  417. for (int y = 0; y < outh; y++)
  418. {
  419. int in_y = std::min((int)(y * hs), (h - 1));
  420. for (int x = 0; x < outw; x++)
  421. {
  422. int in_x = std::min((int)(x * ws), (w - 1));
  423. *outptr++ = ptr[in_y * w + in_x];
  424. }
  425. }
  426. }
  427. }
  428. if (resize_type == 2) // bilinear
  429. {
  430. int* buf = new int[outw + outh + outw * 2 + outh * 2];
  431. int* xofs = buf; //new int[outw];
  432. int* yofs = buf + outw; //new int[outh];
  433. float* alpha = (float*)(buf + outw + outh); //new float[outw * 2];
  434. float* beta = (float*)(buf + outw + outh + outw * 2); //new float[outh * 2];
  435. linear_coeffs(w, outw, xofs, alpha);
  436. linear_coeffs(h, outh, yofs, beta);
  437. #pragma omp parallel for num_threads(opt.num_threads)
  438. for (int q = 0; q < channels; ++q)
  439. {
  440. const Mat src = bottom_blob.channel(q);
  441. Mat dst = top_blob.channel(q);
  442. resize_bilinear_image(src, dst, alpha, xofs, beta, yofs);
  443. }
  444. delete[] buf;
  445. }
  446. if (resize_type == 3) // bicubic
  447. {
  448. int* buf = new int[outw + outh + outw * 4 + outh * 4];
  449. int* xofs = buf; //new int[outw];
  450. int* yofs = buf + outw; //new int[outh];
  451. float* alpha = (float*)(buf + outw + outh); //new float[outw * 4];
  452. float* beta = (float*)(buf + outw + outh + outw * 4); //new float[outh * 4];
  453. cubic_coeffs(w, outw, xofs, alpha);
  454. cubic_coeffs(h, outh, yofs, beta);
  455. #pragma omp parallel for num_threads(opt.num_threads)
  456. for (int q = 0; q < channels; q++)
  457. {
  458. const Mat src = bottom_blob.channel(q);
  459. Mat dst = top_blob.channel(q);
  460. resize_bicubic_image(src, dst, alpha, xofs, beta, yofs);
  461. }
  462. delete[] buf;
  463. }
  464. return 0;
  465. }
  466. } // namespace ncnn