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.

test_mat_pixel_affine.cpp 16 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. // Tencent is pleased to support the open source community by making ncnn available.
  2. //
  3. // Copyright (C) 2020 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 "mat.h"
  15. #include "prng.h"
  16. #include <string.h>
  17. static struct prng_rand_t g_prng_rand_state;
  18. #define SRAND(seed) prng_srand(seed, &g_prng_rand_state)
  19. #define RAND() prng_rand(&g_prng_rand_state)
  20. static ncnn::Mat generate_ncnn_logo(int w, int h)
  21. {
  22. // clang-format off
  23. // *INDENT-OFF*
  24. static const unsigned char ncnn_logo_data[16][16] =
  25. {
  26. {245, 245, 33, 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, 33, 245, 245},
  27. {245, 33, 33, 33, 245, 245, 245, 245, 245, 245, 245, 245, 33, 33, 33, 245},
  28. {245, 33, 158, 158, 33, 245, 245, 245, 245, 245, 245, 33, 158, 158, 33, 245},
  29. { 33, 117, 158, 224, 158, 33, 245, 245, 245, 245, 33, 158, 224, 158, 117, 33},
  30. { 33, 117, 224, 224, 224, 66, 33, 33, 33, 33, 66, 224, 224, 224, 117, 33},
  31. { 33, 189, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 189, 33},
  32. { 33, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 33},
  33. { 33, 224, 224, 97, 97, 97, 97, 224, 224, 97, 97, 97, 97, 224, 224, 33},
  34. { 33, 224, 224, 97, 33, 0, 189, 224, 224, 97, 0, 33, 97, 224, 224, 33},
  35. { 33, 224, 224, 97, 33, 0, 189, 224, 224, 97, 0, 33, 97, 224, 224, 33},
  36. { 33, 224, 224, 97, 97, 97, 97, 224, 224, 97, 189, 189, 97, 224, 224, 33},
  37. { 33, 66, 66, 66, 224, 224, 224, 224, 224, 224, 224, 224, 66, 66, 66, 33},
  38. { 66, 158, 158, 66, 66, 224, 224, 224, 224, 224, 224, 66, 158, 158, 66, 66},
  39. { 66, 158, 158, 208, 66, 224, 224, 224, 224, 224, 224, 66, 158, 158, 208, 66},
  40. { 66, 224, 202, 158, 66, 224, 224, 224, 224, 224, 224, 66, 224, 202, 158, 66},
  41. { 66, 158, 224, 158, 66, 224, 224, 224, 224, 224, 224, 66, 158, 224, 158, 66}
  42. };
  43. // *INDENT-ON*
  44. // clang-format on
  45. ncnn::Mat m(w, h, (size_t)1, 1);
  46. resize_bilinear_c1((const unsigned char*)ncnn_logo_data, 16, 16, m, w, h);
  47. return m;
  48. }
  49. static ncnn::Mat RandomMat(int w, int h, int elempack)
  50. {
  51. ncnn::Mat image = generate_ncnn_logo(w, h);
  52. ncnn::Mat m(w, h, 1, (size_t)elempack, elempack);
  53. for (int i = 0; i < h; i++)
  54. {
  55. unsigned char* p = m.row<unsigned char>(i);
  56. const unsigned char* pb = image.row<const unsigned char>(i);
  57. for (int j = 0; j < w; j++)
  58. {
  59. for (int k = 0; k < elempack; k++)
  60. {
  61. p[k] = pb[0];
  62. }
  63. p += elempack;
  64. pb += 1;
  65. }
  66. }
  67. return m;
  68. }
  69. static bool NearlyEqual(unsigned char a, unsigned char b)
  70. {
  71. return abs(a - b) <= 10;
  72. }
  73. static int CompareNearlyEqual(const ncnn::Mat& a, const ncnn::Mat& b)
  74. {
  75. for (int i = 0; i < a.h; i++)
  76. {
  77. const unsigned char* pa = a.row<const unsigned char>(i);
  78. const unsigned char* pb = b.row<const unsigned char>(i);
  79. for (int j = 0; j < a.w; j++)
  80. {
  81. for (int k = 0; k < a.elempack; k++)
  82. {
  83. if (!NearlyEqual(pa[k], pb[k]))
  84. {
  85. fprintf(stderr, "value not match at h:%d w:%d [%d] expect %d but got %d\n", i, j, k, pa[k], pb[k]);
  86. return -1;
  87. }
  88. }
  89. pa += a.elempack;
  90. pb += a.elempack;
  91. }
  92. }
  93. return 0;
  94. }
  95. static int test_mat_pixel_affine_a(int w, int h)
  96. {
  97. for (int c = 1; c <= 4; c++)
  98. {
  99. ncnn::Mat a0 = RandomMat(w, h, c);
  100. float tm[6];
  101. float tm_inv[6];
  102. ncnn::get_rotation_matrix(10.f, 0.15f, w / 2, h / 2, tm);
  103. ncnn::invert_affine_transform(tm, tm_inv);
  104. ncnn::Mat a1(w / 2, h / 2, (size_t)c, c);
  105. ncnn::Mat a2 = a0.clone();
  106. if (c == 1)
  107. {
  108. ncnn::warpaffine_bilinear_c1(a0, w, h, a1, w / 2, h / 2, tm, 0);
  109. ncnn::warpaffine_bilinear_c1(a1, w / 2, h / 2, a2, w, h, tm_inv, -233);
  110. }
  111. if (c == 2)
  112. {
  113. ncnn::warpaffine_bilinear_c2(a0, w, h, a1, w / 2, h / 2, tm, 0);
  114. ncnn::warpaffine_bilinear_c2(a1, w / 2, h / 2, a2, w, h, tm_inv, -233);
  115. }
  116. if (c == 3)
  117. {
  118. ncnn::warpaffine_bilinear_c3(a0, w, h, a1, w / 2, h / 2, tm, 0);
  119. ncnn::warpaffine_bilinear_c3(a1, w / 2, h / 2, a2, w, h, tm_inv, -233);
  120. }
  121. if (c == 4)
  122. {
  123. ncnn::warpaffine_bilinear_c4(a0, w, h, a1, w / 2, h / 2, tm, 0);
  124. ncnn::warpaffine_bilinear_c4(a1, w / 2, h / 2, a2, w, h, tm_inv, -233);
  125. }
  126. if (CompareNearlyEqual(a0, a2) != 0)
  127. {
  128. fprintf(stderr, "test_mat_pixel_affine_a failed w=%d h=%d c=%d\n", w, h, c);
  129. return -1;
  130. }
  131. }
  132. return 0;
  133. }
  134. static int test_mat_pixel_affine_b(int w, int h)
  135. {
  136. for (int c = 1; c <= 4; c++)
  137. {
  138. ncnn::Mat a0 = RandomMat(w, h, c);
  139. float tm[6];
  140. float tm_inv[6];
  141. ncnn::get_rotation_matrix(20.f, 0.25f, w / 4, h / 4, tm);
  142. ncnn::invert_affine_transform(tm, tm_inv);
  143. ncnn::Mat a1(w / 4, h / 4, (size_t)c, c);
  144. ncnn::Mat a2 = a0.clone();
  145. if (c == 1)
  146. {
  147. ncnn::warpaffine_bilinear_c1(a0, w, h, a1, w / 4, h / 4, tm, 0);
  148. ncnn::warpaffine_bilinear_c1(a1, w / 4, h / 4, a2, w, h, tm_inv, -233);
  149. }
  150. if (c == 2)
  151. {
  152. ncnn::warpaffine_bilinear_c2(a0, w, h, a1, w / 4, h / 4, tm, 0);
  153. ncnn::warpaffine_bilinear_c2(a1, w / 4, h / 4, a2, w, h, tm_inv, -233);
  154. }
  155. if (c == 3)
  156. {
  157. ncnn::warpaffine_bilinear_c3(a0, w, h, a1, w / 4, h / 4, tm, 0);
  158. ncnn::warpaffine_bilinear_c3(a1, w / 4, h / 4, a2, w, h, tm_inv, -233);
  159. }
  160. if (c == 4)
  161. {
  162. ncnn::warpaffine_bilinear_c4(a0, w, h, a1, w / 4, h / 4, tm, 0);
  163. ncnn::warpaffine_bilinear_c4(a1, w / 4, h / 4, a2, w, h, tm_inv, -233);
  164. }
  165. if (CompareNearlyEqual(a0, a2) != 0)
  166. {
  167. fprintf(stderr, "test_mat_pixel_affine_b failed w=%d h=%d c=%d\n", w, h, c);
  168. return -1;
  169. }
  170. }
  171. return 0;
  172. }
  173. static int test_mat_pixel_affine_c(int w, int h)
  174. {
  175. for (int c = 1; c <= 4; c++)
  176. {
  177. ncnn::Mat a0 = RandomMat(w, h, c);
  178. float tm[6];
  179. float tm_inv[6];
  180. ncnn::get_rotation_matrix(-30.f, 0.6f, w / 2, h / 2, tm);
  181. ncnn::invert_affine_transform(tm, tm_inv);
  182. ncnn::Mat a1(w / 2, h / 2, (size_t)c, c);
  183. ncnn::Mat a2 = a0.clone();
  184. if (c == 1)
  185. {
  186. ncnn::warpaffine_bilinear_c1(a0, w, h, a1, w / 2, h / 2, tm, 0);
  187. ncnn::warpaffine_bilinear_c1(a1, w / 2, h / 2, a2, w, h, tm_inv, -233);
  188. }
  189. if (c == 2)
  190. {
  191. ncnn::warpaffine_bilinear_c2(a0, w, h, a1, w / 2, h / 2, tm, 0);
  192. ncnn::warpaffine_bilinear_c2(a1, w / 2, h / 2, a2, w, h, tm_inv, -233);
  193. }
  194. if (c == 3)
  195. {
  196. ncnn::warpaffine_bilinear_c3(a0, w, h, a1, w / 2, h / 2, tm, 0);
  197. ncnn::warpaffine_bilinear_c3(a1, w / 2, h / 2, a2, w, h, tm_inv, -233);
  198. }
  199. if (c == 4)
  200. {
  201. ncnn::warpaffine_bilinear_c4(a0, w, h, a1, w / 2, h / 2, tm, 0);
  202. ncnn::warpaffine_bilinear_c4(a1, w / 2, h / 2, a2, w, h, tm_inv, -233);
  203. }
  204. if (CompareNearlyEqual(a0, a2) != 0)
  205. {
  206. fprintf(stderr, "test_mat_pixel_affine_c failed w=%d h=%d c=%d\n", w, h, c);
  207. return -1;
  208. }
  209. }
  210. return 0;
  211. }
  212. static int test_mat_pixel_affine_d(int w, int h)
  213. {
  214. for (int c = 1; c <= 4; c++)
  215. {
  216. ncnn::Mat a0 = RandomMat(w, h, c);
  217. const float points_from[4] = {w / 8.f, h / 8.f, w / 8.f + 1.f, h / 8.f + 3.f};
  218. const float points_to[4] = {w / 2.f, h / 2.f, w / 2.f + 2.f, h / 2.f};
  219. float tm[6];
  220. float tm_inv[6];
  221. ncnn::get_affine_transform(points_from, points_to, 2, tm);
  222. ncnn::invert_affine_transform(tm, tm_inv);
  223. ncnn::Mat a1(w / 4, h / 4, (size_t)c, c);
  224. ncnn::Mat a2 = a0.clone();
  225. if (c == 1)
  226. {
  227. ncnn::warpaffine_bilinear_c1(a0, w, h, a1, w / 4, h / 4, tm, 0);
  228. ncnn::warpaffine_bilinear_c1(a1, w / 4, h / 4, a2, w, h, tm_inv, -233);
  229. }
  230. if (c == 2)
  231. {
  232. ncnn::warpaffine_bilinear_c2(a0, w, h, a1, w / 4, h / 4, tm, 0);
  233. ncnn::warpaffine_bilinear_c2(a1, w / 4, h / 4, a2, w, h, tm_inv, -233);
  234. }
  235. if (c == 3)
  236. {
  237. ncnn::warpaffine_bilinear_c3(a0, w, h, a1, w / 4, h / 4, tm, 0);
  238. ncnn::warpaffine_bilinear_c3(a1, w / 4, h / 4, a2, w, h, tm_inv, -233);
  239. }
  240. if (c == 4)
  241. {
  242. ncnn::warpaffine_bilinear_c4(a0, w, h, a1, w / 4, h / 4, tm, 0);
  243. ncnn::warpaffine_bilinear_c4(a1, w / 4, h / 4, a2, w, h, tm_inv, -233);
  244. }
  245. if (CompareNearlyEqual(a0, a2) != 0)
  246. {
  247. fprintf(stderr, "test_mat_pixel_affine_d failed w=%d h=%d c=%d\n", w, h, c);
  248. return -1;
  249. }
  250. }
  251. return 0;
  252. }
  253. static int test_mat_pixel_affine_e(int w, int h)
  254. {
  255. for (int c = 1; c <= 4; c++)
  256. {
  257. ncnn::Mat a0 = RandomMat(w, h, c);
  258. float tm[6];
  259. float tm_inv[6];
  260. ncnn::get_rotation_matrix(-180.f, 0.5f, w / 2, h / 2, tm);
  261. ncnn::invert_affine_transform(tm, tm_inv);
  262. ncnn::Mat a1(w, h, (size_t)c, c);
  263. ncnn::Mat a2 = a0.clone();
  264. if (c == 1)
  265. {
  266. ncnn::warpaffine_bilinear_c1(a0, w, h, a1, w, h, tm, 0);
  267. ncnn::warpaffine_bilinear_c1(a1, w, h, a2, w, h, tm_inv, -233);
  268. }
  269. if (c == 2)
  270. {
  271. ncnn::warpaffine_bilinear_c2(a0, w, h, a1, w, h, tm, 0);
  272. ncnn::warpaffine_bilinear_c2(a1, w, h, a2, w, h, tm_inv, -233);
  273. }
  274. if (c == 3)
  275. {
  276. ncnn::warpaffine_bilinear_c3(a0, w, h, a1, w, h, tm, 0);
  277. ncnn::warpaffine_bilinear_c3(a1, w, h, a2, w, h, tm_inv, -233);
  278. }
  279. if (c == 4)
  280. {
  281. ncnn::warpaffine_bilinear_c4(a0, w, h, a1, w, h, tm, 0);
  282. ncnn::warpaffine_bilinear_c4(a1, w, h, a2, w, h, tm_inv, -233);
  283. }
  284. if (CompareNearlyEqual(a0, a2) != 0)
  285. {
  286. fprintf(stderr, "test_mat_pixel_affine_e failed w=%d h=%d c=%d\n", w, h, c);
  287. return -1;
  288. }
  289. }
  290. return 0;
  291. }
  292. static int test_mat_pixel_affine_f(int w, int h)
  293. {
  294. for (int c = 1; c <= 4; c++)
  295. {
  296. ncnn::Mat a0 = RandomMat(w, h, c);
  297. float tm[6];
  298. float tm_inv[6];
  299. ncnn::get_rotation_matrix(0.002f, 1.0f, w / 2, h / 2, tm);
  300. ncnn::invert_affine_transform(tm, tm_inv);
  301. ncnn::Mat a1(w * 2, h * 2, (size_t)c, c);
  302. ncnn::Mat a2 = a0.clone();
  303. if (c == 1)
  304. {
  305. ncnn::warpaffine_bilinear_c1(a0, w, h, a1, w * 2, h * 2, tm, 0);
  306. ncnn::warpaffine_bilinear_c1(a1, w * 2, h * 2, a2, w, h, tm_inv, -233);
  307. }
  308. if (c == 2)
  309. {
  310. ncnn::warpaffine_bilinear_c2(a0, w, h, a1, w * 2, h * 2, tm, 0);
  311. ncnn::warpaffine_bilinear_c2(a1, w * 2, h * 2, a2, w, h, tm_inv, -233);
  312. }
  313. if (c == 3)
  314. {
  315. ncnn::warpaffine_bilinear_c3(a0, w, h, a1, w * 2, h * 2, tm, 0);
  316. ncnn::warpaffine_bilinear_c3(a1, w * 2, h * 2, a2, w, h, tm_inv, -233);
  317. }
  318. if (c == 4)
  319. {
  320. ncnn::warpaffine_bilinear_c4(a0, w, h, a1, w * 2, h * 2, tm, 0);
  321. ncnn::warpaffine_bilinear_c4(a1, w * 2, h * 2, a2, w, h, tm_inv, -233);
  322. }
  323. if (CompareNearlyEqual(a0, a2) != 0)
  324. {
  325. fprintf(stderr, "test_mat_pixel_affine_f failed w=%d h=%d c=%d\n", w, h, c);
  326. return -1;
  327. }
  328. }
  329. return 0;
  330. }
  331. static int test_mat_pixel_affine_g(int w, int h)
  332. {
  333. for (int c = 1; c <= 4; c++)
  334. {
  335. ncnn::Mat a0 = RandomMat(w, h, c);
  336. float tm[6];
  337. float tm_inv[6];
  338. ncnn::get_rotation_matrix(0.f, 0.5f, w / 2 + 4, h / 2 - 3, tm);
  339. ncnn::invert_affine_transform(tm, tm_inv);
  340. ncnn::Mat a1(w, h, (size_t)c, c);
  341. ncnn::Mat a2 = a0.clone();
  342. if (c == 1)
  343. {
  344. ncnn::warpaffine_bilinear_c1(a0, w, h, a1, w, h, tm, 0);
  345. ncnn::warpaffine_bilinear_c1(a1, w, h, a2, w, h, tm_inv, -233);
  346. }
  347. if (c == 2)
  348. {
  349. ncnn::warpaffine_bilinear_c2(a0, w, h, a1, w, h, tm, 0);
  350. ncnn::warpaffine_bilinear_c2(a1, w, h, a2, w, h, tm_inv, -233);
  351. }
  352. if (c == 3)
  353. {
  354. ncnn::warpaffine_bilinear_c3(a0, w, h, a1, w, h, tm, 0);
  355. ncnn::warpaffine_bilinear_c3(a1, w, h, a2, w, h, tm_inv, -233);
  356. }
  357. if (c == 4)
  358. {
  359. ncnn::warpaffine_bilinear_c4(a0, w, h, a1, w, h, tm, 0);
  360. ncnn::warpaffine_bilinear_c4(a1, w, h, a2, w, h, tm_inv, -233);
  361. }
  362. if (CompareNearlyEqual(a0, a2) != 0)
  363. {
  364. fprintf(stderr, "test_mat_pixel_affine_g failed w=%d h=%d c=%d\n", w, h, c);
  365. return -1;
  366. }
  367. }
  368. return 0;
  369. }
  370. static int test_mat_pixel_affine_0()
  371. {
  372. return 0
  373. || test_mat_pixel_affine_a(60, 70)
  374. || test_mat_pixel_affine_b(60, 70)
  375. || test_mat_pixel_affine_c(60, 70)
  376. || test_mat_pixel_affine_d(60, 70)
  377. || test_mat_pixel_affine_e(60, 70)
  378. || test_mat_pixel_affine_f(60, 70)
  379. || test_mat_pixel_affine_g(60, 70)
  380. || test_mat_pixel_affine_a(120, 160)
  381. || test_mat_pixel_affine_b(120, 160)
  382. || test_mat_pixel_affine_c(120, 160)
  383. || test_mat_pixel_affine_d(120, 160)
  384. || test_mat_pixel_affine_e(120, 160)
  385. || test_mat_pixel_affine_f(120, 160)
  386. || test_mat_pixel_affine_g(120, 160)
  387. || test_mat_pixel_affine_a(220, 330)
  388. || test_mat_pixel_affine_b(220, 330)
  389. || test_mat_pixel_affine_c(220, 330)
  390. || test_mat_pixel_affine_d(220, 330)
  391. || test_mat_pixel_affine_e(220, 330)
  392. || test_mat_pixel_affine_f(220, 330)
  393. || test_mat_pixel_affine_g(220, 330);
  394. }
  395. static int test_mat_pixel_affine_yuv420sp(int w, int h)
  396. {
  397. ncnn::Mat a0(w, h * 3 / 2, (size_t)1u, 1);
  398. ncnn::Mat a0_y = RandomMat(w, h, 1);
  399. ncnn::Mat a0_uv = RandomMat(w / 2, h / 2, 2);
  400. memcpy(a0, a0_y, w * h);
  401. memcpy((unsigned char*)a0 + w * h, a0_uv, w * h / 2);
  402. float tm[6];
  403. float tm_inv[6];
  404. ncnn::get_rotation_matrix(-70.f, 0.3f, w / 2, h / 2, tm);
  405. ncnn::invert_affine_transform(tm, tm_inv);
  406. ncnn::Mat a1(w / 2, (h / 2) * 3 / 2, (size_t)1u, 1);
  407. ncnn::Mat a2 = a0.clone();
  408. ncnn::warpaffine_bilinear_yuv420sp(a0, w, h, a1, w / 2, h / 2, tm, 0);
  409. ncnn::warpaffine_bilinear_yuv420sp(a1, w / 2, h / 2, a2, w, h, tm_inv, -233);
  410. // Y
  411. if (CompareNearlyEqual(ncnn::Mat(w, h, (unsigned char*)a0, (size_t)1u, 1), ncnn::Mat(w, h, (unsigned char*)a2, (size_t)1u, 1)) != 0)
  412. {
  413. fprintf(stderr, "test_mat_pixel_affine_yuv420sp Y failed w=%d h=%d\n", w, h);
  414. return -1;
  415. }
  416. // UV
  417. if (CompareNearlyEqual(ncnn::Mat(w / 2, h / 2, (unsigned char*)a0 + w * h, (size_t)2u, 2), ncnn::Mat(w / 2, h / 2, (unsigned char*)a2 + w * h, (size_t)2u, 2)) != 0)
  418. {
  419. fprintf(stderr, "test_mat_pixel_affine_yuv420sp UV failed w=%d h=%d\n", w, h);
  420. return -1;
  421. }
  422. return 0;
  423. }
  424. static int test_mat_pixel_affine_1()
  425. {
  426. return 0
  427. || test_mat_pixel_affine_yuv420sp(40, 40)
  428. || test_mat_pixel_affine_yuv420sp(120, 160)
  429. || test_mat_pixel_affine_yuv420sp(220, 340);
  430. }
  431. int main()
  432. {
  433. SRAND(7767517);
  434. return test_mat_pixel_affine_0() || test_mat_pixel_affine_1();
  435. }