38 inline void configure_crop(
const ICLTensor *
input, ICLTensor *crop_boxes, ICLTensor *box_ind, ICLTensor *output, uint32_t crop_box_ind, Coordinates &
start, Coordinates &
end, uint32_t &batch_index)
40 batch_index = *(
reinterpret_cast<int32_t *
>(box_ind->ptr_to_element(Coordinates(crop_box_ind))));
44 const float x0 = *
reinterpret_cast<const float *
>(crop_boxes->ptr_to_element(Coordinates(1, crop_box_ind)));
45 const float y0 = *
reinterpret_cast<const float *
>(crop_boxes->ptr_to_element(Coordinates(0, crop_box_ind)));
46 const float x1 = *
reinterpret_cast<const float *
>(crop_boxes->ptr_to_element(Coordinates(3, crop_box_ind)));
47 const float y1 = *
reinterpret_cast<const float *
>(crop_boxes->ptr_to_element(Coordinates(2, crop_box_ind)));
49 start = Coordinates(std::floor(x0 * (input->info()->tensor_shape()[1] - 1) + 0.5f),
50 std::floor(y0 * (input->info()->tensor_shape()[2] - 1) + 0.5f));
51 end = Coordinates(std::floor(x1 * (input->info()->tensor_shape()[1] - 1) + 0.5f),
52 std::floor(y1 * (input->info()->tensor_shape()[2] - 1) + 0.5f));
53 const TensorShape out_shape(input->info()->tensor_shape()[0],
static_cast<uint32_t
>(abs(end[0] - start[0])) + 1, static_cast<uint32_t>(abs(end[1] - start[1])) + 1);
54 output->info()->set_tensor_shape(out_shape);
59 : _input(nullptr), _boxes(nullptr), _box_ind(nullptr), _output(nullptr), _num_boxes(0), _method(), _extrapolation_value(0), _scale(), _copy(), _crop_results(), _scaled_results(), _internal_functions()
122 for(
unsigned int num_box = 0; num_box <
_num_boxes; ++num_box)
124 auto crop_tensor = std::make_unique<CLTensor>();
127 crop_tensor->allocator()->init(crop_result_info);
130 auto scale_tensor = std::make_unique<CLTensor>();
133 scale_tensor->allocator()->init(scaled_result_info);
137 uint32_t batch_index;
142 auto scale_kernel = std::make_unique<CLScale>();
144 _scale.emplace_back(std::move(scale_kernel));
149 auto copy_kernel = std::make_unique<CLCopy>();
151 _copy.emplace_back(std::move(copy_kernel));
156 bool is_width_flipped = end[0] < start[0];
157 bool is_height_flipped = end[1] < start[1];
159 std::array<int32_t, 2> rows_out_of_bounds{ 0 };
161 std::array<int32_t, 2> cols_out_of_bounds{ 0 };
162 if(is_height_flipped)
164 rows_out_of_bounds[0] = start[1] >=
static_cast<int32_t
>(_input->info()->dimension(2)) ? std::min(start[1] - _input->info()->dimension(2) + 1,
_crop_results[num_box].get()->info()->dimension(2)) : 0;
165 rows_out_of_bounds[1] = end[1] < 0 ? std::min(-end[1], static_cast<int32_t>(
_crop_results[num_box].
get()->
info()->dimension(2))) : 0;
169 rows_out_of_bounds[0] = start[1] < 0 ? std::min(-start[1], static_cast<int32_t>(
_crop_results[num_box].
get()->
info()->dimension(2))) : 0;
170 rows_out_of_bounds[1] = end[1] >=
static_cast<int32_t
>(_input->info()->dimension(2)) ? std::min(end[1] - _input->info()->dimension(2) + 1,
_crop_results[num_box].get()->info()->dimension(2)) : 0;
174 cols_out_of_bounds[0] = start[0] >=
static_cast<int32_t
>(_input->info()->dimension(1)) ? std::min(start[0] - _input->info()->dimension(1) + 1,
_crop_results[num_box].get()->info()->dimension(1)) : 0;
175 cols_out_of_bounds[1] = end[0] < 0 ? std::min(-end[0], static_cast<int32_t>(
_crop_results[num_box].
get()->
info()->dimension(1))) : 0;
179 cols_out_of_bounds[0] = start[0] < 0 ? std::min(-start[0], static_cast<int32_t>(
_crop_results[num_box].
get()->
info()->dimension(1))) : 0;
180 cols_out_of_bounds[1] = end[0] >=
static_cast<int32_t
>(_input->info()->dimension(1)) ? std::min(end[0] - _input->info()->dimension(1) + 1,
_crop_results[num_box].get()->info()->dimension(1)) : 0;
203 if(rows_out_of_bounds[0] > 0)
205 Window slice_fill_rows_before(full_window);
207 auto kernel = std::make_unique<CLFill>();
208 kernel->configure(compile_context,
_crop_results[num_box].
get(), extrapolation_value, &slice_fill_rows_before);
213 Window slice_in(full_window);
217 int rows_in_bounds =
static_cast<int32_t
>(
_crop_results[num_box].get()->info()->dimension(2)) - rows_out_of_bounds[0] - rows_out_of_bounds[1];
218 if(rows_in_bounds > 0)
221 if(cols_out_of_bounds[0] > 0)
223 Window slice_fill_cols_before(slice_in);
225 auto kernel = std::make_unique<CLFill>();
226 kernel->configure(compile_context,
_crop_results[num_box].
get(), extrapolation_value, &slice_fill_cols_before);
231 if(cols_out_of_bounds[1] > 0)
233 Window slice_fill_cols_after(slice_in);
235 auto kernel = std::make_unique<CLFill>();
236 kernel->configure(compile_context,
_crop_results[num_box].
get(), extrapolation_value, &slice_fill_cols_after);
242 int cols_in_bounds =
static_cast<int32_t
>(
_crop_results[num_box].get()->info()->dimension(1)) - cols_out_of_bounds[0] - cols_out_of_bounds[1];
243 if(cols_in_bounds > 0)
245 Coordinates2D start_in{ is_width_flipped ? start[0] - cols_out_of_bounds[0] : start[0] + cols_out_of_bounds[0],
246 is_height_flipped ? start[1] - rows_out_of_bounds[0] : start[1] + rows_out_of_bounds[0] };
247 Coordinates2D end_in{ is_width_flipped ? start_in.
x - cols_in_bounds + 1 : start_in.x + cols_in_bounds - 1,
248 is_height_flipped ? start_in.y - rows_in_bounds + 1 : start_in.y + rows_in_bounds - 1 };
249 auto kernel = std::make_unique<CLCrop>();
251 kernel->configure(compile_context, _input,
_crop_results[num_box].
get(), start_in, end_in, batch_index, extrapolation_value, &slice_in);
258 if(rows_out_of_bounds[1] > 0)
260 Window slice_fill_rows_after(full_window);
262 auto kernel = std::make_unique<CLFill>();
263 kernel->configure(compile_context,
_crop_results[num_box].
get(), extrapolation_value, &slice_fill_rows_after);
283 for(
auto &kernel :
_scale)
288 for(
auto &kernel :
_copy)
Class describing the value of a pixel for any image format.
Window calculate_max_window(const ValidRegion &valid_region, const Steps &steps, bool skip_border, BorderSize border_size)
InterpolationPolicy
Interpolation method.
std::vector< std::unique_ptr< CLTensor > > _crop_results
CLCropResize()
Default constructor.
void map(cl::CommandQueue &q, bool blocking=true)
Enqueue a map operation of the allocated buffer on the given queue.
~CLCropResize()
Default destructor.
#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT(...)
std::vector< std::unique_ptr< CLCopy > > _copy
virtual size_t dimension(size_t index) const =0
Return the size of the requested dimension.
std::vector< std::unique_ptr< IFunction > > _internal_functions
static CLScheduler & get()
Access the scheduler singleton.
#define ARM_COMPUTE_RETURN_ON_ERROR(status)
Checks if a status contains an error and returns it.
1 channel, 1 F32 per channel
static CLKernelLibrary & get()
Access the KernelLibrary singleton.
Store the tensor's metadata.
#define ARM_COMPUTE_ERROR_THROW_ON(status)
Describe one of the image's dimensions with a start, end and step.
#define ARM_COMPUTE_RETURN_ERROR_ON(cond)
If the condition is true, an error is returned.
#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(...)
Copyright (c) 2017-2021 Arm Limited.
std::vector< std::unique_ptr< CLTensor > > _scaled_results
InterpolationPolicy _method
Interface to enqueue OpenCL kernels and get/set the OpenCL CommandQueue and ICLTuner.
virtual const TensorShape & tensor_shape() const =0
Size for each dimension of the tensor.
void unmap(cl::CommandQueue &q)
Enqueue an unmap operation of the allocated and mapped buffer on the given queue. ...
#define ARM_COMPUTE_ERROR_ON_MSG(cond, msg)
static Status validate(const ITensorInfo *input, ITensorInfo *boxes, ITensorInfo *box_ind, const ITensorInfo *output, Coordinates2D crop_size, InterpolationPolicy method, float extrapolation_value)
Static function to check if given info will lead to a valid configuration of NESlice.
bool auto_init_if_empty(ITensorInfo &info, const TensorShape &shape, int num_channels, DataType data_type, QuantizationInfo quantization_info=QuantizationInfo())
Auto initialize the tensor info (shape, number of channels and data type) if the current assignment i...
virtual std::unique_ptr< T > clone() const =0
Provide a clone of the current object of class T.
void run() override
Run the kernels contained in the function.
virtual ITensorInfo * info() const =0
Interface to be implemented by the child class to return the tensor's metadata.
Samples are taken at pixel top left corner.
void end(TokenStream &in, bool &valid)
void set(size_t dimension, const Dimension &dim)
Set the values of a given dimension.
Output values are determined by averaging the source pixels whose areas fall under the area of the de...
void sync()
Blocks until all commands in the associated command queue have finished.
static Status validate(const ITensorInfo *input, const ITensorInfo *output, Coordinates2D start, Coordinates2D end, uint32_t batch_index, float extrapolation_value=0, Window *output_window=nullptr)
Static function to check if given info will lead to a valid configuration of CLStridedSliceKernel.
float _extrapolation_value
ScaleKernelInfo info(interpolation_policy, default_border_mode, PixelValue(), sampling_policy, false)
Interface for OpenCL tensor.
virtual size_t total_size() const =0
Returns the total size of the tensor in bytes.
Num samples, height, width, channels.
void configure(const ICLTensor *input, ICLTensor *boxes, ICLTensor *box_ind, ICLTensor *output, Coordinates2D crop_size, InterpolationPolicy method=InterpolationPolicy::BILINEAR, float extrapolation_value=0)
Configure kernel.
std::vector< std::unique_ptr< CLScale > > _scale
#define ARM_COMPUTE_ERROR_ON_NULLPTR(...)
Store the tensor's metadata.
#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(t,...)
Describe a multidimensional execution window.