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.

roialign.cpp 4.6 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Tencent is pleased to support the open source community by making ncnn available.
  2. //
  3. // Copyright (C) 2018 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 "roialign.h"
  15. #include <math.h>
  16. #include <algorithm>
  17. namespace ncnn {
  18. DEFINE_LAYER_CREATOR(ROIAlign)
  19. ROIAlign::ROIAlign()
  20. {
  21. }
  22. int ROIAlign::load_param(const ParamDict& pd)
  23. {
  24. pooled_width = pd.get(0, 0);
  25. pooled_height = pd.get(1, 0);
  26. spatial_scale = pd.get(2, 1.f);
  27. return 0;
  28. }
  29. static inline float bilinear_interpolate(const float* ptr, int w, int h, float x, float y)
  30. {
  31. int x0 = x;
  32. int x1 = x0 + 1;
  33. int y0 = y;
  34. int y1 = y0 + 1;
  35. float a0 = x1 - x;
  36. float a1 = x - x0;
  37. float b0 = y1 - y;
  38. float b1 = y - y0;
  39. if (x1 >= w)
  40. {
  41. x1 = w-1;
  42. a0 = 1.f;
  43. a1 = 0.f;
  44. }
  45. if (y1 >= h)
  46. {
  47. y1 = h-1;
  48. b0 = 1.f;
  49. b1 = 0.f;
  50. }
  51. float r0 = ptr[ y0 * w + x0 ] * a0 + ptr[ y0 * w + x1 ] * a1;
  52. float r1 = ptr[ y1 * w + x0 ] * a0 + ptr[ y1 * w + x1 ] * a1;
  53. float v = r0 * b0 + r1 * b1;
  54. return v;
  55. }
  56. int ROIAlign::forward(const std::vector<Mat>& bottom_blobs, std::vector<Mat>& top_blobs, const Option& opt) const
  57. {
  58. const Mat& bottom_blob = bottom_blobs[0];
  59. int w = bottom_blob.w;
  60. int h = bottom_blob.h;
  61. size_t elemsize = bottom_blob.elemsize;
  62. int channels = bottom_blob.c;
  63. const Mat& roi_blob = bottom_blobs[1];
  64. Mat& top_blob = top_blobs[0];
  65. top_blob.create(pooled_width, pooled_height, channels, elemsize, opt.blob_allocator);
  66. if (top_blob.empty())
  67. return -100;
  68. // For each ROI R = [x y w h]: avg pool over R
  69. const float* roi_ptr = roi_blob;
  70. float roi_x1 = roi_ptr[0] * spatial_scale;
  71. float roi_y1 = roi_ptr[1] * spatial_scale;
  72. float roi_x2 = roi_ptr[2] * spatial_scale;
  73. float roi_y2 = roi_ptr[3] * spatial_scale;
  74. float roi_w = std::max(roi_x2 - roi_x1, 1.f);
  75. float roi_h = std::max(roi_y2 - roi_y1, 1.f);
  76. float bin_size_w = roi_w / (float)pooled_width;
  77. float bin_size_h = roi_h / (float)pooled_height;
  78. #pragma omp parallel for num_threads(opt.num_threads)
  79. for (int q=0; q<channels; q++)
  80. {
  81. const float* ptr = bottom_blob.channel(q);
  82. float* outptr = top_blob.channel(q);
  83. for (int ph = 0; ph < pooled_height; ph++)
  84. {
  85. for (int pw = 0; pw < pooled_width; pw++)
  86. {
  87. // Compute pooling region for this output unit:
  88. // start (included) = ph * roi_height / pooled_height
  89. // end (excluded) = (ph + 1) * roi_height / pooled_height
  90. float hstart = roi_y1 + ph * bin_size_h;
  91. float wstart = roi_x1 + pw * bin_size_w;
  92. float hend = roi_y1 + (ph + 1) * bin_size_h;
  93. float wend = roi_x1 + (pw + 1) * bin_size_w;
  94. hstart = std::min(std::max(hstart, 0.f), (float)h);
  95. wstart = std::min(std::max(wstart, 0.f), (float)w);
  96. hend = std::min(std::max(hend, 0.f), (float)h);
  97. wend = std::min(std::max(wend, 0.f), (float)w);
  98. int bin_grid_h = ceil(hend - hstart);
  99. int bin_grid_w = ceil(wend - wstart);
  100. bool is_empty = (hend <= hstart) || (wend <= wstart);
  101. int area = bin_grid_h * bin_grid_w;
  102. float sum = 0.f;
  103. for (int by = 0; by < bin_grid_h; by++)
  104. {
  105. float y = hstart + (by + 0.5f) * bin_size_h / (float)bin_grid_h;
  106. for (int bx = 0; bx < bin_grid_w; bx++)
  107. {
  108. float x = wstart + (bx + 0.5f) * bin_size_w / (float)bin_grid_w;
  109. // bilinear interpolate at (x,y)
  110. float v = bilinear_interpolate(ptr, w, h, x, y);
  111. sum += v;
  112. }
  113. }
  114. outptr[pw] = is_empty ? 0.f : (sum / (float)area);
  115. }
  116. outptr += pooled_width;
  117. }
  118. }
  119. return 0;
  120. }
  121. } // namespace ncnn