Compute Library
 21.02
NEGenerateProposalsLayer Class Reference

Basic function to generate proposals for a RPN (Region Proposal Network) More...

#include <NEGenerateProposalsLayer.h>

Collaboration diagram for NEGenerateProposalsLayer:
[legend]

Public Member Functions

 NEGenerateProposalsLayer (std::shared_ptr< IMemoryManager > memory_manager=nullptr)
 Default constructor. More...
 
 NEGenerateProposalsLayer (const NEGenerateProposalsLayer &)=delete
 Prevent instances of this class from being copied (As this class contains pointers) More...
 
NEGenerateProposalsLayeroperator= (const NEGenerateProposalsLayer &)=delete
 Prevent instances of this class from being copied (As this class contains pointers) More...
 
 ~NEGenerateProposalsLayer ()
 Default destructor. More...
 
void configure (const ITensor *scores, const ITensor *deltas, const ITensor *anchors, ITensor *proposals, ITensor *scores_out, ITensor *num_valid_proposals, const GenerateProposalsInfo &info)
 Set the input and output tensors. More...
 
void run () override
 Run the kernels contained in the function. More...
 
- Public Member Functions inherited from IFunction
virtual ~IFunction ()=default
 Destructor. More...
 
virtual void prepare ()
 Prepare the function for executing. More...
 

Static Public Member Functions

static Status validate (const ITensorInfo *scores, const ITensorInfo *deltas, const ITensorInfo *anchors, const ITensorInfo *proposals, const ITensorInfo *scores_out, const ITensorInfo *num_valid_proposals, const GenerateProposalsInfo &info)
 Static function to check if given info will lead to a valid configuration of NEGenerateProposalsLayer. More...
 

Detailed Description

Basic function to generate proposals for a RPN (Region Proposal Network)

This function calls the following Neon kernels:

  1. NEComputeAllAnchorsKernel
  2. NEPermute x 2
  3. NEReshapeLayer x 2
  4. NEBoundingBoxTransform
  5. NEPadLayerKernel
  6. NEDequantizationLayerKernel x 2
  7. NEQuantizationLayerKernel And the following CPP kernels:
  8. CPPBoxWithNonMaximaSuppressionLimit

Definition at line 58 of file NEGenerateProposalsLayer.h.

Constructor & Destructor Documentation

◆ NEGenerateProposalsLayer() [1/2]

NEGenerateProposalsLayer ( std::shared_ptr< IMemoryManager memory_manager = nullptr)

Default constructor.

Parameters
[in]memory_manager(Optional) Memory manager.

Definition at line 35 of file NEGenerateProposalsLayer.cpp.

References NEGenerateProposalsLayer::~NEGenerateProposalsLayer().

36  : _memory_group(memory_manager),
37  _permute_deltas(),
38  _flatten_deltas(),
39  _permute_scores(),
40  _flatten_scores(),
41  _compute_anchors(nullptr),
42  _bounding_box(),
43  _pad(),
44  _dequantize_anchors(),
45  _dequantize_deltas(),
46  _quantize_all_proposals(),
47  _cpp_nms(memory_manager),
48  _is_nhwc(false),
49  _is_qasymm8(false),
50  _deltas_permuted(),
51  _deltas_flattened(),
52  _deltas_flattened_f32(),
53  _scores_permuted(),
54  _scores_flattened(),
55  _all_anchors(),
56  _all_anchors_f32(),
57  _all_proposals(),
58  _all_proposals_quantized(),
59  _keeps_nms_unused(),
60  _classes_nms_unused(),
61  _proposals_4_roi_values(),
62  _all_proposals_to_use(nullptr),
63  _num_valid_proposals(nullptr),
64  _scores_out(nullptr)
65 {
66 }

◆ NEGenerateProposalsLayer() [2/2]

Prevent instances of this class from being copied (As this class contains pointers)

◆ ~NEGenerateProposalsLayer()

Default destructor.

Referenced by NEGenerateProposalsLayer::NEGenerateProposalsLayer().

Member Function Documentation

◆ configure()

void configure ( const ITensor scores,
const ITensor deltas,
const ITensor anchors,
ITensor proposals,
ITensor scores_out,
ITensor num_valid_proposals,
const GenerateProposalsInfo info 
)

Set the input and output tensors.

Parameters
[in]scoresScores from convolution layer of size (W, H, A), where H and W are the height and width of the feature map, and A is the number of anchors. Data types supported: QASYMM8/F16/F32
[in]deltasBounding box deltas from convolution layer of size (W, H, 4*A). Data types supported: Same as scores
[in]anchorsAnchors tensor of size (4, A). Data types supported: QSYMM16 with scale of 0.125 if scores is QASYMM8, otherwise same as scores
[out]proposalsBox proposals output tensor of size (5, W*H*A). Data types supported: QASYMM16 with scale of 0.125 and 0 offset if scores is QASYMM8, otherwise same as scores
[out]scores_outBox scores output tensor of size (W*H*A). Data types supported: Same as input
[out]num_valid_proposalsScalar output tensor which says which of the first proposals are valid. Data types supported: U32
[in]infoContains GenerateProposals operation information described in GenerateProposalsInfo
Note
Only single image prediction is supported. Height and Width (and scale) of the image will be contained in the GenerateProposalsInfo struct.
Proposals contains all the proposals. Of those, only the first num_valid_proposals are valid.

Definition at line 70 of file NEGenerateProposalsLayer.cpp.

References TensorAllocator::allocate(), Tensor::allocator(), ARM_COMPUTE_ERROR_ON_NULLPTR, ARM_COMPUTE_ERROR_THROW_ON, arm_compute::auto_init_if_empty(), arm_compute::CHANNEL, NEDequantizationLayer::configure(), NEQuantizationLayer::configure(), NEBoundingBoxTransform::configure(), NEReshapeLayer::configure(), NEPermute::configure(), CPPBoxWithNonMaximaSuppressionLimit::configure(), NEPadLayer::configure(), ITensorInfo::data_layout(), ITensorInfo::data_type(), ITensorInfo::dimension(), arm_compute::F32, arm_compute::get_data_layout_dimension_index(), arm_compute::HEIGHT, GenerateProposalsInfo::im_height(), GenerateProposalsInfo::im_scale(), GenerateProposalsInfo::im_width(), ITensor::info(), Tensor::info(), arm_compute::test::validation::info, TensorAllocator::init(), arm_compute::LINEAR, MemoryGroup::manage(), GenerateProposalsInfo::min_size(), arm_compute::NHWC, GenerateProposalsInfo::nms_thres(), GenerateProposalsInfo::post_nms_topN(), GenerateProposalsInfo::pre_nms_topN(), arm_compute::QASYMM16, arm_compute::QASYMM8, ITensorInfo::quantization_info(), GenerateProposalsInfo::spatial_scale(), ITensorInfo::tensor_shape(), arm_compute::U32, NEGenerateProposalsLayer::validate(), GenerateProposalsInfo::values_per_roi(), and arm_compute::WIDTH.

72 {
73  ARM_COMPUTE_ERROR_ON_NULLPTR(scores, deltas, anchors, proposals, scores_out, num_valid_proposals);
74  ARM_COMPUTE_ERROR_THROW_ON(NEGenerateProposalsLayer::validate(scores->info(), deltas->info(), anchors->info(), proposals->info(), scores_out->info(), num_valid_proposals->info(), info));
75 
76  _is_nhwc = scores->info()->data_layout() == DataLayout::NHWC;
77  const DataType scores_data_type = scores->info()->data_type();
78  _is_qasymm8 = scores_data_type == DataType::QASYMM8;
79  const int num_anchors = scores->info()->dimension(get_data_layout_dimension_index(scores->info()->data_layout(), DataLayoutDimension::CHANNEL));
80  const int feat_width = scores->info()->dimension(get_data_layout_dimension_index(scores->info()->data_layout(), DataLayoutDimension::WIDTH));
81  const int feat_height = scores->info()->dimension(get_data_layout_dimension_index(scores->info()->data_layout(), DataLayoutDimension::HEIGHT));
82  const int total_num_anchors = num_anchors * feat_width * feat_height;
83  const int pre_nms_topN = info.pre_nms_topN();
84  const int post_nms_topN = info.post_nms_topN();
85  const size_t values_per_roi = info.values_per_roi();
86 
87  const QuantizationInfo scores_qinfo = scores->info()->quantization_info();
88  const DataType rois_data_type = (_is_qasymm8) ? DataType::QASYMM16 : scores_data_type;
89  const QuantizationInfo rois_qinfo = (_is_qasymm8) ? QuantizationInfo(0.125f, 0) : scores->info()->quantization_info();
90 
91  // Compute all the anchors
92  _memory_group.manage(&_all_anchors);
93  _compute_anchors = std::make_unique<NEComputeAllAnchorsKernel>();
94  _compute_anchors->configure(anchors, &_all_anchors, ComputeAnchorsInfo(feat_width, feat_height, info.spatial_scale()));
95 
96  const TensorShape flatten_shape_deltas(values_per_roi, total_num_anchors);
97  _deltas_flattened.allocator()->init(TensorInfo(flatten_shape_deltas, 1, scores_data_type, deltas->info()->quantization_info()));
98 
99  // Permute and reshape deltas
100  _memory_group.manage(&_deltas_flattened);
101  if(!_is_nhwc)
102  {
103  _memory_group.manage(&_deltas_permuted);
104  _permute_deltas.configure(deltas, &_deltas_permuted, PermutationVector{ 2, 0, 1 });
105  _flatten_deltas.configure(&_deltas_permuted, &_deltas_flattened);
106  _deltas_permuted.allocator()->allocate();
107  }
108  else
109  {
110  _flatten_deltas.configure(deltas, &_deltas_flattened);
111  }
112 
113  const TensorShape flatten_shape_scores(1, total_num_anchors);
114  _scores_flattened.allocator()->init(TensorInfo(flatten_shape_scores, 1, scores_data_type, scores_qinfo));
115 
116  // Permute and reshape scores
117  _memory_group.manage(&_scores_flattened);
118  if(!_is_nhwc)
119  {
120  _memory_group.manage(&_scores_permuted);
121  _permute_scores.configure(scores, &_scores_permuted, PermutationVector{ 2, 0, 1 });
122  _flatten_scores.configure(&_scores_permuted, &_scores_flattened);
123  _scores_permuted.allocator()->allocate();
124  }
125  else
126  {
127  _flatten_scores.configure(scores, &_scores_flattened);
128  }
129 
130  Tensor *anchors_to_use = &_all_anchors;
131  Tensor *deltas_to_use = &_deltas_flattened;
132  if(_is_qasymm8)
133  {
134  _all_anchors_f32.allocator()->init(TensorInfo(_all_anchors.info()->tensor_shape(), 1, DataType::F32));
135  _deltas_flattened_f32.allocator()->init(TensorInfo(_deltas_flattened.info()->tensor_shape(), 1, DataType::F32));
136  _memory_group.manage(&_all_anchors_f32);
137  _memory_group.manage(&_deltas_flattened_f32);
138  // Dequantize anchors to float
139  _dequantize_anchors.configure(&_all_anchors, &_all_anchors_f32);
140  _all_anchors.allocator()->allocate();
141  anchors_to_use = &_all_anchors_f32;
142  // Dequantize deltas to float
143  _dequantize_deltas.configure(&_deltas_flattened, &_deltas_flattened_f32);
144  _deltas_flattened.allocator()->allocate();
145  deltas_to_use = &_deltas_flattened_f32;
146  }
147  // Bounding box transform
148  _memory_group.manage(&_all_proposals);
149  BoundingBoxTransformInfo bbox_info(info.im_width(), info.im_height(), 1.f);
150  _bounding_box.configure(anchors_to_use, &_all_proposals, deltas_to_use, bbox_info);
151  deltas_to_use->allocator()->allocate();
152  anchors_to_use->allocator()->allocate();
153 
154  _all_proposals_to_use = &_all_proposals;
155  if(_is_qasymm8)
156  {
157  _memory_group.manage(&_all_proposals_quantized);
158  // Requantize all_proposals to QASYMM16 with 0.125 scale and 0 offset
159  _all_proposals_quantized.allocator()->init(TensorInfo(_all_proposals.info()->tensor_shape(), 1, DataType::QASYMM16, QuantizationInfo(0.125f, 0)));
160  _quantize_all_proposals.configure(&_all_proposals, &_all_proposals_quantized);
161  _all_proposals.allocator()->allocate();
162  _all_proposals_to_use = &_all_proposals_quantized;
163  }
164  // The original layer implementation first selects the best pre_nms_topN anchors (thus having a lightweight sort)
165  // that are then transformed by bbox_transform. The boxes generated are then fed into a non-sorting NMS operation.
166  // Since we are reusing the NMS layer and we don't implement any CL/sort, we let NMS do the sorting (of all the input)
167  // and the filtering
168  const int scores_nms_size = std::min<int>(std::min<int>(post_nms_topN, pre_nms_topN), total_num_anchors);
169  const float min_size_scaled = info.min_size() * info.im_scale();
170  _memory_group.manage(&_classes_nms_unused);
171  _memory_group.manage(&_keeps_nms_unused);
172 
173  // Note that NMS needs outputs preinitialized.
174  auto_init_if_empty(*scores_out->info(), TensorShape(scores_nms_size), 1, scores_data_type, scores_qinfo);
175  auto_init_if_empty(*_proposals_4_roi_values.info(), TensorShape(values_per_roi, scores_nms_size), 1, rois_data_type, rois_qinfo);
176  auto_init_if_empty(*num_valid_proposals->info(), TensorShape(1), 1, DataType::U32);
177 
178  // Initialize temporaries (unused) outputs
179  _classes_nms_unused.allocator()->init(TensorInfo(TensorShape(scores_nms_size), 1, scores_data_type, scores_qinfo));
180  _keeps_nms_unused.allocator()->init(*scores_out->info());
181 
182  // Save the output (to map and unmap them at run)
183  _scores_out = scores_out;
184  _num_valid_proposals = num_valid_proposals;
185 
186  _memory_group.manage(&_proposals_4_roi_values);
187 
188  const BoxNMSLimitInfo box_nms_info(0.0f, info.nms_thres(), scores_nms_size, false, NMSType::LINEAR, 0.5f, 0.001f, true, min_size_scaled, info.im_width(), info.im_height());
189  _cpp_nms.configure(&_scores_flattened /*scores_in*/,
190  _all_proposals_to_use /*boxes_in,*/,
191  nullptr /* batch_splits_in*/,
192  scores_out /* scores_out*/,
193  &_proposals_4_roi_values /*boxes_out*/,
194  &_classes_nms_unused /*classes*/,
195  nullptr /*batch_splits_out*/,
196  &_keeps_nms_unused /*keeps*/,
197  num_valid_proposals /* keeps_size*/,
198  box_nms_info);
199 
200  _keeps_nms_unused.allocator()->allocate();
201  _classes_nms_unused.allocator()->allocate();
202  _all_proposals_to_use->allocator()->allocate();
203  _scores_flattened.allocator()->allocate();
204 
205  // Add the first column that represents the batch id. This will be all zeros, as we don't support multiple images
206  _pad.configure(&_proposals_4_roi_values, proposals, PaddingList{ { 1, 0 } });
207  _proposals_4_roi_values.allocator()->allocate();
208 }
void init(const TensorAllocator &allocator, const Coordinates &coords, TensorInfo &sub_info)
Shares the same backing memory with another tensor allocator, while the tensor info might be differen...
std::vector< PaddingInfo > PaddingList
List of padding information.
Definition: Types.h:481
void configure(const ITensor *input, ITensor *output)
Configure the kernel.
1 channel, 1 F32 per channel
Strides PermutationVector
Permutation vector.
Definition: Types.h:49
#define ARM_COMPUTE_ERROR_THROW_ON(status)
Definition: Error.h:455
quantized, asymmetric fixed-point 16-bit number
static Status validate(const ITensorInfo *scores, const ITensorInfo *deltas, const ITensorInfo *anchors, const ITensorInfo *proposals, const ITensorInfo *scores_out, const ITensorInfo *num_valid_proposals, const GenerateProposalsInfo &info)
Static function to check if given info will lead to a valid configuration of NEGenerateProposalsLayer...
TensorAllocator * allocator()
Return a pointer to the tensor&#39;s allocator.
Definition: Tensor.cpp:48
ITensorInfo * info() const override
Interface to be implemented by the child class to return the tensor&#39;s metadata.
Definition: Tensor.cpp:33
void manage(IMemoryManageable *obj) override
Sets a object to be managed by the given memory group.
Definition: MemoryGroup.h:79
1 channel, 1 U32 per channel
virtual const TensorShape & tensor_shape() const =0
Size for each dimension of the tensor.
quantized, asymmetric fixed-point 8-bit number unsigned
void allocate() override
Allocate size specified by TensorInfo of CPU memory.
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...
void configure(const ITensor *input, ITensor *output)
Set the input and output tensors.
void configure(const ITensor *boxes, ITensor *pred_boxes, const ITensor *deltas, const BoundingBoxTransformInfo &info)
Set the input and output tensors.
ScaleKernelInfo info(interpolation_policy, default_border_mode, PixelValue(), sampling_policy, false)
Num samples, height, width, channels.
void configure(ITensor *input, ITensor *output, const PaddingList &padding, const PixelValue constant_value=PixelValue(), const PaddingMode mode=PaddingMode::CONSTANT)
Initialize the function.
Definition: NEPadLayer.cpp:167
void configure(const ITensor *input, ITensor *output)
Initialise the kernel&#39;s inputs and outputs.
#define ARM_COMPUTE_ERROR_ON_NULLPTR(...)
Definition: Validate.h:161
size_t get_data_layout_dimension_index(const DataLayout data_layout, const DataLayoutDimension data_layout_dimension)
Get the index of the given dimension.
Definition: Helpers.inl:193
void configure(const ITensor *input, ITensor *output, const PermutationVector &perm)
Configure the permute Neon kernel.
Definition: NEPermute.cpp:49
DataType
Available data types.
Definition: Types.h:77
void configure(const ITensor *scores_in, const ITensor *boxes_in, const ITensor *batch_splits_in, ITensor *scores_out, ITensor *boxes_out, ITensor *classes, ITensor *batch_splits_out=nullptr, ITensor *keeps=nullptr, ITensor *keeps_size=nullptr, const BoxNMSLimitInfo info=BoxNMSLimitInfo())
Configure the BoxWithNonMaximaSuppressionLimit CPP kernel.

◆ operator=()

NEGenerateProposalsLayer& operator= ( const NEGenerateProposalsLayer )
delete

Prevent instances of this class from being copied (As this class contains pointers)

◆ run()

void run ( )
overridevirtual

Run the kernels contained in the function.

For Neon kernels:

  • Multi-threading is used for the kernels which are parallelisable.
  • By default std::thread::hardware_concurrency() threads are used.
Note
CPPScheduler::set_num_threads() can be used to manually set the number of threads

For OpenCL kernels:

  • All the kernels are enqueued on the queue associated with CLScheduler.
  • The queue is then flushed.
Note
The function will not block until the kernels are executed. It is the user's responsibility to wait.
Will call prepare() on first run if hasn't been done

Implements IFunction.

Definition at line 322 of file NEGenerateProposalsLayer.cpp.

References Window::DimY, Scheduler::get(), INESimpleFunctionNoBorder::run(), NEReshapeLayer::run(), NEPermute::run(), CPPBoxWithNonMaximaSuppressionLimit::run(), NEPadLayer::run(), and IScheduler::schedule().

323 {
324  // Acquire all the temporaries
325  MemoryGroupResourceScope scope_mg(_memory_group);
326 
327  // Compute all the anchors
328  NEScheduler::get().schedule(_compute_anchors.get(), Window::DimY);
329 
330  // Transpose and reshape the inputs
331  if(!_is_nhwc)
332  {
333  _permute_deltas.run();
334  _permute_scores.run();
335  }
336 
337  _flatten_deltas.run();
338  _flatten_scores.run();
339 
340  if(_is_qasymm8)
341  {
342  _dequantize_anchors.run();
343  _dequantize_deltas.run();
344  }
345 
346  // Build the boxes
347  _bounding_box.run();
348 
349  if(_is_qasymm8)
350  {
351  _quantize_all_proposals.run();
352  }
353 
354  // Non maxima suppression
355  _cpp_nms.run();
356 
357  // Add dummy batch indexes
358  _pad.run();
359 }
void run() override final
Run the kernels contained in the function.
void run() override
Run the kernels contained in the function.
static constexpr size_t DimY
Alias for dimension 1 also known as Y dimension.
Definition: Window.h:45
void run() override
Run the kernels contained in the function.
Definition: NEPermute.cpp:67
virtual void schedule(ICPPKernel *kernel, const Hints &hints)=0
Runs the kernel in the same thread as the caller synchronously.
void run() override
Run the kernels contained in the function.
Definition: NEPadLayer.cpp:250
void run() override
Run the kernels contained in the function.
static IScheduler & get()
Access the scheduler singleton.
Definition: Scheduler.cpp:94

◆ validate()

Status validate ( const ITensorInfo scores,
const ITensorInfo deltas,
const ITensorInfo anchors,
const ITensorInfo proposals,
const ITensorInfo scores_out,
const ITensorInfo num_valid_proposals,
const GenerateProposalsInfo info 
)
static

Static function to check if given info will lead to a valid configuration of NEGenerateProposalsLayer.

Parameters
[in]scoresScores info from convolution layer of size (W, H, A), where H and W are the height and width of the feature map, and A is the number of anchors. Data types supported: QASYMM8/F16/F32
[in]deltasBounding box deltas info from convolution layer of size (W, H, 4*A). Data types supported: Same as scores
[in]anchorsAnchors tensor info of size (4, A). Data types supported: QSYMM16 with scale of 0.125 if scores is QASYMM8, otherwise same as scores
[in]proposalsBox proposals info output tensor of size (5, W*H*A). Data types supported: QASYMM16 with scale of 0.125 and 0 offset if scores is QASYMM8, otherwise same as scores
[in]scores_outBox scores output tensor info of size (W*H*A). Data types supported: Same as input
[in]num_valid_proposalsScalar output tensor info which says which of the first proposals are valid. Data types supported: U32
[in]infoContains GenerateProposals operation information described in GenerateProposalsInfo
Returns
a Status

Definition at line 210 of file NEGenerateProposalsLayer.cpp.

References ARM_COMPUTE_RETURN_ERROR_ON, ARM_COMPUTE_RETURN_ERROR_ON_DATA_LAYOUT_NOT_IN, ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN, ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT, ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES, ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES, ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR, ARM_COMPUTE_RETURN_ON_ERROR, arm_compute::CHANNEL, ICloneable< T >::clone(), ITensorInfo::data_layout(), ITensorInfo::data_type(), ITensorInfo::dimension(), arm_compute::F16, arm_compute::F32, arm_compute::get_data_layout_dimension_index(), arm_compute::HEIGHT, GenerateProposalsInfo::im_height(), GenerateProposalsInfo::im_width(), arm_compute::NCHW, arm_compute::NHWC, ITensorInfo::num_dimensions(), UniformQuantizationInfo::offset, arm_compute::QASYMM16, arm_compute::QASYMM8, arm_compute::QSYMM16, ITensorInfo::quantization_info(), UniformQuantizationInfo::scale, TensorInfo::set_data_type(), ITensorInfo::set_quantization_info(), GenerateProposalsInfo::spatial_scale(), ITensorInfo::total_size(), arm_compute::U32, QuantizationInfo::uniform(), NEDequantizationLayer::validate(), NEQuantizationLayer::validate(), NEReshapeLayer::validate(), NEBoundingBoxTransform::validate(), NEComputeAllAnchorsKernel::validate(), NEPermute::validate(), NEPadLayer::validate(), GenerateProposalsInfo::values_per_roi(), and arm_compute::WIDTH.

Referenced by NEGenerateProposalsLayer::configure().

212 {
213  ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(scores, deltas, anchors, proposals, scores_out, num_valid_proposals);
218 
219  const int num_anchors = scores->dimension(get_data_layout_dimension_index(scores->data_layout(), DataLayoutDimension::CHANNEL));
220  const int feat_width = scores->dimension(get_data_layout_dimension_index(scores->data_layout(), DataLayoutDimension::WIDTH));
221  const int feat_height = scores->dimension(get_data_layout_dimension_index(scores->data_layout(), DataLayoutDimension::HEIGHT));
222  const int num_images = scores->dimension(3);
223  const int total_num_anchors = num_anchors * feat_width * feat_height;
224  const int values_per_roi = info.values_per_roi();
225 
226  const bool is_qasymm8 = scores->data_type() == DataType::QASYMM8;
227 
228  ARM_COMPUTE_RETURN_ERROR_ON(num_images > 1);
229 
230  if(is_qasymm8)
231  {
233  const UniformQuantizationInfo anchors_qinfo = anchors->quantization_info().uniform();
234  ARM_COMPUTE_RETURN_ERROR_ON(anchors_qinfo.scale != 0.125f);
235  }
236 
237  TensorInfo all_anchors_info(anchors->clone()->set_tensor_shape(TensorShape(values_per_roi, total_num_anchors)).set_is_resizable(true));
238  ARM_COMPUTE_RETURN_ON_ERROR(NEComputeAllAnchorsKernel::validate(anchors, &all_anchors_info, ComputeAnchorsInfo(feat_width, feat_height, info.spatial_scale())));
239 
240  TensorInfo deltas_permuted_info = deltas->clone()->set_tensor_shape(TensorShape(values_per_roi * num_anchors, feat_width, feat_height)).set_is_resizable(true);
241  TensorInfo scores_permuted_info = scores->clone()->set_tensor_shape(TensorShape(num_anchors, feat_width, feat_height)).set_is_resizable(true);
242  if(scores->data_layout() == DataLayout::NHWC)
243  {
244  ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(deltas, &deltas_permuted_info);
245  ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(scores, &scores_permuted_info);
246  }
247  else
248  {
249  ARM_COMPUTE_RETURN_ON_ERROR(NEPermute::validate(deltas, &deltas_permuted_info, PermutationVector{ 2, 0, 1 }));
250  ARM_COMPUTE_RETURN_ON_ERROR(NEPermute::validate(scores, &scores_permuted_info, PermutationVector{ 2, 0, 1 }));
251  }
252 
253  TensorInfo deltas_flattened_info(deltas->clone()->set_tensor_shape(TensorShape(values_per_roi, total_num_anchors)).set_is_resizable(true));
254  ARM_COMPUTE_RETURN_ON_ERROR(NEReshapeLayer::validate(&deltas_permuted_info, &deltas_flattened_info));
255 
256  TensorInfo scores_flattened_info(scores->clone()->set_tensor_shape(TensorShape(1, total_num_anchors)).set_is_resizable(true));
257  TensorInfo proposals_4_roi_values(deltas->clone()->set_tensor_shape(TensorShape(values_per_roi, total_num_anchors)).set_is_resizable(true));
258 
259  ARM_COMPUTE_RETURN_ON_ERROR(NEReshapeLayer::validate(&scores_permuted_info, &scores_flattened_info));
260 
261  TensorInfo *proposals_4_roi_values_to_use = &proposals_4_roi_values;
262  TensorInfo proposals_4_roi_values_quantized(deltas->clone()->set_tensor_shape(TensorShape(values_per_roi, total_num_anchors)).set_is_resizable(true));
263  proposals_4_roi_values_quantized.set_data_type(DataType::QASYMM16).set_quantization_info(QuantizationInfo(0.125f, 0));
264  if(is_qasymm8)
265  {
266  TensorInfo all_anchors_f32_info(anchors->clone()->set_tensor_shape(TensorShape(values_per_roi, total_num_anchors)).set_is_resizable(true).set_data_type(DataType::F32));
267  ARM_COMPUTE_RETURN_ON_ERROR(NEDequantizationLayer::validate(&all_anchors_info, &all_anchors_f32_info));
268 
269  TensorInfo deltas_flattened_f32_info(deltas->clone()->set_tensor_shape(TensorShape(values_per_roi, total_num_anchors)).set_is_resizable(true).set_data_type(DataType::F32));
270  ARM_COMPUTE_RETURN_ON_ERROR(NEDequantizationLayer::validate(&deltas_flattened_info, &deltas_flattened_f32_info));
271 
272  TensorInfo proposals_4_roi_values_f32(deltas->clone()->set_tensor_shape(TensorShape(values_per_roi, total_num_anchors)).set_is_resizable(true).set_data_type(DataType::F32));
273  ARM_COMPUTE_RETURN_ON_ERROR(NEBoundingBoxTransform::validate(&all_anchors_f32_info, &proposals_4_roi_values_f32, &deltas_flattened_f32_info,
274  BoundingBoxTransformInfo(info.im_width(), info.im_height(), 1.f)));
275 
276  ARM_COMPUTE_RETURN_ON_ERROR(NEQuantizationLayer::validate(&proposals_4_roi_values_f32, &proposals_4_roi_values_quantized));
277  proposals_4_roi_values_to_use = &proposals_4_roi_values_quantized;
278  }
279  else
280  {
281  ARM_COMPUTE_RETURN_ON_ERROR(NEBoundingBoxTransform::validate(&all_anchors_info, &proposals_4_roi_values, &deltas_flattened_info,
282  BoundingBoxTransformInfo(info.im_width(), info.im_height(), 1.f)));
283  }
284 
285  ARM_COMPUTE_RETURN_ON_ERROR(NEPadLayer::validate(proposals_4_roi_values_to_use, proposals, PaddingList{ { 1, 0 } }));
286 
287  if(num_valid_proposals->total_size() > 0)
288  {
289  ARM_COMPUTE_RETURN_ERROR_ON(num_valid_proposals->num_dimensions() > 1);
290  ARM_COMPUTE_RETURN_ERROR_ON(num_valid_proposals->dimension(0) > 1);
292  }
293 
294  if(proposals->total_size() > 0)
295  {
296  ARM_COMPUTE_RETURN_ERROR_ON(proposals->num_dimensions() > 2);
297  ARM_COMPUTE_RETURN_ERROR_ON(proposals->dimension(0) != size_t(values_per_roi) + 1);
298  ARM_COMPUTE_RETURN_ERROR_ON(proposals->dimension(1) != size_t(total_num_anchors));
299  if(is_qasymm8)
300  {
302  const UniformQuantizationInfo proposals_qinfo = proposals->quantization_info().uniform();
303  ARM_COMPUTE_RETURN_ERROR_ON(proposals_qinfo.scale != 0.125f);
304  ARM_COMPUTE_RETURN_ERROR_ON(proposals_qinfo.offset != 0);
305  }
306  else
307  {
309  }
310  }
311 
312  if(scores_out->total_size() > 0)
313  {
314  ARM_COMPUTE_RETURN_ERROR_ON(scores_out->num_dimensions() > 1);
315  ARM_COMPUTE_RETURN_ERROR_ON(scores_out->dimension(0) != size_t(total_num_anchors));
317  }
318 
319  return Status{};
320 }
#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_LAYOUT_NOT_IN(t,...)
Definition: Validate.h:746
quantized, symmetric fixed-point 16-bit number
#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT(...)
Definition: Validate.h:494
std::vector< PaddingInfo > PaddingList
List of padding information.
Definition: Types.h:481
static Status validate(const ITensorInfo *input, const ITensorInfo *output)
Static function to check if given info will lead to a valid configuration of NEReshapeLayer.
#define ARM_COMPUTE_RETURN_ON_ERROR(status)
Checks if a status contains an error and returns it.
Definition: Error.h:204
1 channel, 1 F32 per channel
Strides PermutationVector
Permutation vector.
Definition: Types.h:49
static Status validate(const ITensorInfo *input, const ITensorInfo *output, const PermutationVector &perm)
Static function to check if given info will lead to a valid configuration of NEPermute.
Definition: NEPermute.cpp:59
quantized, asymmetric fixed-point 16-bit number
static Status validate(const ITensorInfo *anchors, const ITensorInfo *all_anchors, const ComputeAnchorsInfo &info)
Static function to check if given info will lead to a valid configuration of NEComputeAllAnchorsKerne...
#define ARM_COMPUTE_RETURN_ERROR_ON(cond)
If the condition is true, an error is returned.
Definition: Error.h:296
1 channel, 1 F16 per channel
#define ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(...)
Definition: Validate.h:163
static Status validate(const ITensorInfo *input, const ITensorInfo *output)
Static function to check if given info will lead to a valid configuration of NEDequantizationLayer.
1 channel, 1 U32 per channel
static Status validate(const ITensorInfo *input, const ITensorInfo *output, const PaddingList &padding, const PixelValue constant_value=PixelValue(), const PaddingMode mode=PaddingMode::CONSTANT)
Static function to check if given info will lead to a valid configuration of NEPadLayer.
Definition: NEPadLayer.cpp:206
quantized, asymmetric fixed-point 8-bit number unsigned
Num samples, channels, height, width.
ScaleKernelInfo info(interpolation_policy, default_border_mode, PixelValue(), sampling_policy, false)
#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(...)
Definition: Validate.h:443
static Status validate(const ITensorInfo *boxes, const ITensorInfo *pred_boxes, const ITensorInfo *deltas, const BoundingBoxTransformInfo &info)
Static function to check if given info will lead to a valid configuration of NEBoundingBoxTransform.
#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(...)
Definition: Validate.h:545
Num samples, height, width, channels.
#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c,...)
Definition: Validate.h:792
size_t get_data_layout_dimension_index(const DataLayout data_layout, const DataLayoutDimension data_layout_dimension)
Get the index of the given dimension.
Definition: Helpers.inl:193
static Status validate(const ITensorInfo *input, const ITensorInfo *output)
Static function to check if given info will lead to a valid configuration of NEQuantizationLayer.

The documentation for this class was generated from the following files: