| 140 | |
| 141 | template <> |
| 142 | SimpleTensor<float> roi_align_layer(const SimpleTensor<float> &src, |
| 143 | const SimpleTensor<float> &rois, |
| 144 | const ROIPoolingLayerInfo &pool_info, |
| 145 | const QuantizationInfo &output_qinfo) |
| 146 | { |
| 147 | ARM_COMPUTE_UNUSED(output_qinfo); |
| 148 | |
| 149 | const size_t values_per_roi = rois.shape()[0]; |
| 150 | const size_t num_rois = rois.shape()[1]; |
| 151 | DataType dst_data_type = src.data_type(); |
| 152 | |
| 153 | const auto *rois_ptr = static_cast<const float *>(rois.data()); |
| 154 | |
| 155 | TensorShape input_shape = src.shape(); |
| 156 | TensorShape output_shape(pool_info.pooled_width(), pool_info.pooled_height(), src.shape()[2], num_rois); |
| 157 | SimpleTensor<float> dst(output_shape, dst_data_type); |
| 158 | |
| 159 | // Iterate over every pixel of the input image |
| 160 | for (size_t px = 0; px < pool_info.pooled_width(); ++px) |
| 161 | { |
| 162 | for (size_t py = 0; py < pool_info.pooled_height(); ++py) |
| 163 | { |
| 164 | for (size_t pw = 0; pw < num_rois; ++pw) |
| 165 | { |
| 166 | const unsigned int roi_batch = rois_ptr[values_per_roi * pw]; |
| 167 | const auto x1 = float(rois_ptr[values_per_roi * pw + 1]); |
| 168 | const auto y1 = float(rois_ptr[values_per_roi * pw + 2]); |
| 169 | const auto x2 = float(rois_ptr[values_per_roi * pw + 3]); |
| 170 | const auto y2 = float(rois_ptr[values_per_roi * pw + 4]); |
| 171 | |
| 172 | const float roi_anchor_x = x1 * pool_info.spatial_scale(); |
| 173 | const float roi_anchor_y = y1 * pool_info.spatial_scale(); |
| 174 | const float roi_dims_x = std::max((x2 - x1) * pool_info.spatial_scale(), 1.0f); |
| 175 | const float roi_dims_y = std::max((y2 - y1) * pool_info.spatial_scale(), 1.0f); |
| 176 | |
| 177 | float bin_size_x = roi_dims_x / pool_info.pooled_width(); |
| 178 | float bin_size_y = roi_dims_y / pool_info.pooled_height(); |
| 179 | float region_start_x = px * bin_size_x + roi_anchor_x; |
| 180 | float region_start_y = py * bin_size_y + roi_anchor_y; |
| 181 | float region_end_x = (px + 1) * bin_size_x + roi_anchor_x; |
| 182 | float region_end_y = (py + 1) * bin_size_y + roi_anchor_y; |
| 183 | |
| 184 | region_start_x = utility::clamp(region_start_x, 0.0f, float(input_shape[0])); |
| 185 | region_start_y = utility::clamp(region_start_y, 0.0f, float(input_shape[1])); |
| 186 | region_end_x = utility::clamp(region_end_x, 0.0f, float(input_shape[0])); |
| 187 | region_end_y = utility::clamp(region_end_y, 0.0f, float(input_shape[1])); |
| 188 | |
| 189 | const int roi_bin_grid_x = |
| 190 | (pool_info.sampling_ratio() > 0) ? pool_info.sampling_ratio() : int(ceil(bin_size_x)); |
| 191 | const int roi_bin_grid_y = |
| 192 | (pool_info.sampling_ratio() > 0) ? pool_info.sampling_ratio() : int(ceil(bin_size_y)); |
| 193 | |
| 194 | // Move input and output pointer across the fourth dimension |
| 195 | const size_t input_stride_w = input_shape[0] * input_shape[1] * input_shape[2]; |
| 196 | const size_t output_stride_w = output_shape[0] * output_shape[1] * output_shape[2]; |
| 197 | const float *input_ptr = src.data() + roi_batch * input_stride_w; |
| 198 | float *output_ptr = dst.data() + px + py * output_shape[0] + pw * output_stride_w; |
| 199 |
no test coverage detected