• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2023 Huawei Technologies Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "nnacl/kernel/prior_box.h"
18 #include <math.h>
19 #include "nnacl/kernel/default_kernel_base.h"
20 #include "nnacl/fp32/prior_box_fp32.h"
21 #include "nnacl/tensor_c_utils.h"
22 
PriorBoxInitOutput(PriorBoxStruct * prior_box,const PriorBoxParameter * param,const float * different_aspect_ratios,int different_aspect_ratios_size)23 int PriorBoxInitOutput(PriorBoxStruct *prior_box, const PriorBoxParameter *param, const float *different_aspect_ratios,
24                        int different_aspect_ratios_size) {
25   for (int i = 0; i < prior_box->fmap_h_; i++) {
26     float cy = i + param->offset;
27     for (int j = 0; j < prior_box->fmap_w_; j++) {
28       float cx = j + param->offset;
29       for (int32_t k = 0; k < param->min_sizes_size; k++) {
30         float min = param->min_sizes[k];
31         prior_box->output_[prior_box->output_size_++] = (cx - min / prior_box->step_w_ * 0.5f) / prior_box->fmap_w_;
32         prior_box->output_[prior_box->output_size_++] = (cy - min / prior_box->step_h_ * 0.5f) / prior_box->fmap_h_;
33         prior_box->output_[prior_box->output_size_++] = (cx + min / prior_box->step_w_ * 0.5f) / prior_box->fmap_w_;
34         prior_box->output_[prior_box->output_size_++] = (cy + min / prior_box->step_h_ * 0.5f) / prior_box->fmap_h_;
35 
36         if (param->max_sizes_size > 0) {
37           float max = param->max_sizes[k];
38           NNACL_CHECK_FALSE(min * max <= 0, NNACL_PRIOR_BOX_VALUE_INVALID);
39           float prime = sqrt(min * max);
40           prior_box->output_[prior_box->output_size_++] = (cx - prime / prior_box->step_w_ * 0.5f) / prior_box->fmap_w_;
41           prior_box->output_[prior_box->output_size_++] = (cy - prime / prior_box->step_h_ * 0.5f) / prior_box->fmap_h_;
42           prior_box->output_[prior_box->output_size_++] = (cx + prime / prior_box->step_w_ * 0.5f) / prior_box->fmap_w_;
43           prior_box->output_[prior_box->output_size_++] = (cy + prime / prior_box->step_h_ * 0.5f) / prior_box->fmap_h_;
44         }
45 
46         for (int m = 0; m < different_aspect_ratios_size; m++) {
47           float v = different_aspect_ratios[m];
48           if (fabs(v - 1.0f) < 1e-6) {
49             continue;
50           }
51           NNACL_CHECK_FALSE(v <= 0, NNACL_PRIOR_BOX_VALUE_INVALID);
52           float as_square_root = sqrt(v);
53           NNACL_CHECK_FALSE(as_square_root <= 0, NNACL_PRIOR_BOX_VALUE_INVALID);
54           float box_w = min * as_square_root;
55           float box_h = min / as_square_root;
56           prior_box->output_[prior_box->output_size_++] = (cx - box_w / prior_box->step_w_ * 0.5f) / prior_box->fmap_w_;
57           prior_box->output_[prior_box->output_size_++] = (cy - box_h / prior_box->step_h_ * 0.5f) / prior_box->fmap_h_;
58           prior_box->output_[prior_box->output_size_++] = (cx + box_w / prior_box->step_w_ * 0.5f) / prior_box->fmap_w_;
59           prior_box->output_[prior_box->output_size_++] = (cy + box_h / prior_box->step_h_ * 0.5f) / prior_box->fmap_h_;
60         }
61       }
62     }
63   }
64   return NNACL_OK;
65 }
66 
RunPriorBox(void * cdata,int task_id,float l,float r)67 int RunPriorBox(void *cdata, int task_id, float l, float r) {
68   PriorBoxStruct *prior_box = (PriorBoxStruct *)cdata;
69   NNACL_CHECK_NULL_RETURN_ERR(prior_box);
70   TensorC *output_tensor = prior_box->base_.out_[OUTPUT_INDEX];
71   NNACL_CHECK_NULL_RETURN_ERR(output_tensor);
72   float *output_data = output_tensor->data_;
73   NNACL_CHECK_NULL_RETURN_ERR(output_data);
74   return PriorBox(prior_box->output_, output_data, GetSize(output_tensor), task_id, prior_box->base_.thread_nr_);
75 }
76 
PriorBoxRelease(KernelBase * self)77 int PriorBoxRelease(KernelBase *self) {
78   PriorBoxStruct *prior_box = (PriorBoxStruct *)self;
79   NNACL_CHECK_NULL_RETURN_ERR(prior_box);
80   if (prior_box->output_ != NULL) {
81     self->env_->Free(self->env_->allocator_, prior_box->output_);
82     prior_box->output_ = NULL;
83     prior_box->output_size_ = 0;
84   }
85   return NNACL_OK;
86 }
87 
PriorBoxResize(KernelBase * self)88 int PriorBoxResize(KernelBase *self) {
89   PriorBoxStruct *prior_box = (PriorBoxStruct *)self;
90   NNACL_CHECK_NULL_RETURN_ERR(prior_box);
91   PriorBoxParameter *param = (PriorBoxParameter *)self->param_;
92   NNACL_CHECK_NULL_RETURN_ERR(param);
93   TensorC *input0_tensor = prior_box->base_.in_[FIRST_INPUT];
94   NNACL_CHECK_NULL_RETURN_ERR(input0_tensor);
95   TensorC *input1_tensor = prior_box->base_.in_[FIRST_INPUT];
96   NNACL_CHECK_NULL_RETURN_ERR(input1_tensor);
97   TensorC *output_tensor = prior_box->base_.out_[OUTPUT_INDEX];
98   NNACL_CHECK_NULL_RETURN_ERR(output_tensor);
99 
100   prior_box->fmap_w_ = GetWidth(input0_tensor);
101   NNACL_CHECK_ZERO_RETURN_ERR(prior_box->fmap_w_);
102   prior_box->fmap_h_ = GetHeight(input1_tensor);
103   NNACL_CHECK_ZERO_RETURN_ERR(prior_box->fmap_h_);
104   const int image_w = param->image_size_w > 0 ? param->image_size_w : GetWidth(input1_tensor);
105   const int image_h = param->image_size_h > 0 ? param->image_size_h : GetHeight(input1_tensor);
106 
107   prior_box->step_w_ = param->step_w > 0.0f ? param->step_w : (float)(image_w) / prior_box->fmap_w_;
108   prior_box->step_h_ = param->step_h > 0.0f ? param->step_h : (float)(image_h) / prior_box->fmap_h_;
109 
110   float *different_aspect_ratios =
111     (float *)self->env_->Alloc(self->env_->allocator_, param->aspect_ratios_size * sizeof(float) * Num2);
112   NNACL_MALLOC_CHECK_NULL_RETURN_ERR(different_aspect_ratios);
113   different_aspect_ratios[Index0] = 1.0f;
114   int different_aspect_ratios_size = 1;
115 
116   float *aspect_ratios = param->aspect_ratios;
117   for (int32_t i = 0; i < param->aspect_ratios_size; i++) {
118     float ratio = aspect_ratios[i];
119 
120     bool exist = false;
121     for (int k = 0; k < different_aspect_ratios_size; k++) {
122       if (fabs(ratio - different_aspect_ratios[k]) < 1e-6) {
123         exist = true;
124       }
125     }
126 
127     if (!exist) {
128       different_aspect_ratios[different_aspect_ratios_size++] = ratio;
129       if (param->flip) {
130         NNACL_CHECK_FALSE(fabs(ratio) <= 1e-5, NNACL_PRIOR_BOX_RATIO_INVALID);
131         different_aspect_ratios[different_aspect_ratios_size++] = 1.0f / ratio;
132       }
133     }
134   }
135 
136   PriorBoxRelease(self);
137   int size = Num4 + Num4 + different_aspect_ratios_size;
138   size = size * prior_box->fmap_h_ * prior_box->fmap_w_ * param->min_sizes_size;
139   size = size + UP_ROUND(GetHeight(output_tensor), COMM_SHAPE_SIZE);
140   size = size * sizeof(float);
141   NNACL_CHECK_MALLOC_SIZE(size);
142   prior_box->output_ = (float *)self->env_->Alloc(self->env_->allocator_, size);
143   NNACL_MALLOC_CHECK_NULL_RETURN_ERR(prior_box->output_);
144   prior_box->output_size_ = 0;
145 
146   int ret = PriorBoxInitOutput(prior_box, param, different_aspect_ratios, different_aspect_ratios_size);
147   if (ret != NNACL_OK) {
148     return ret;
149   }
150 
151   // do clip
152   if (param->clip) {
153     for (int i = 0; i < prior_box->output_size_; i++) {
154       float item = prior_box->output_[i];
155       if (item > 1.0f) {
156         item = 1.0f;
157       }
158       if (item < 0.0f) {
159         item = 0.0f;
160       }
161     }
162   }
163 
164   // variance
165   for (int i = 0; i < GetHeight(output_tensor) / COMM_SHAPE_SIZE; i++) {
166     for (int j = 0; j < COMM_SHAPE_SIZE; j++) {
167       prior_box->output_[prior_box->output_size_++] = param->variances[j];
168     }
169   }
170   return NNACL_OK;
171 }
172 
PriorBoxCompute(KernelBase * self)173 int PriorBoxCompute(KernelBase *self) {
174   return self->env_->ParallelLaunch(self->env_->thread_pool_, RunPriorBox, self, self->thread_nr_);
175 }
176 
CreatePriorBox(OpParameter * param,int data_type)177 KernelBase *CreatePriorBox(OpParameter *param, int data_type) {
178   PriorBoxStruct *prior_box = (PriorBoxStruct *)malloc(sizeof(PriorBoxStruct));
179   NNACL_MALLOC_CHECK_NULL_RETURN_NULL(prior_box);
180   memset(prior_box, 0, sizeof(PriorBoxStruct));
181 
182   prior_box->base_.Prepare = DefaultPrepare2In1Out;
183   prior_box->base_.Resize = PriorBoxResize;
184   prior_box->base_.Release = PriorBoxRelease;
185   prior_box->base_.Compute = PriorBoxCompute;
186   return (KernelBase *)prior_box;
187 }
188 
189 REG_KERNEL_CREATOR(PrimType_PriorBox, kNumberTypeFloat32, CreatePriorBox)
190 REG_KERNEL_CREATOR(PrimType_PriorBox, kNumberTypeInt8, CreatePriorBox)
191