Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
pooling.h
00001 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved. 00002 00003 Licensed under the Apache License, Version 2.0 (the "License"); 00004 you may not use this file except in compliance with the License. 00005 You may obtain a copy of the License at 00006 00007 http://www.apache.org/licenses/LICENSE-2.0 00008 00009 Unless required by applicable law or agreed to in writing, software 00010 distributed under the License is distributed on an "AS IS" BASIS, 00011 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 See the License for the specific language governing permissions and 00013 limitations under the License. 00014 ==============================================================================*/ 00015 #ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_POOLING_H_ 00016 #define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_POOLING_H_ 00017 00018 #include "tensorflow/lite/kernels/internal/common.h" 00019 #include "tensorflow/lite/kernels/internal/quantization_util.h" 00020 #include "tensorflow/lite/kernels/internal/round.h" 00021 #include "tensorflow/lite/kernels/internal/types.h" 00022 00023 namespace tflite { 00024 namespace reference_ops { 00025 00026 inline void AveragePool(const PoolParams& params, 00027 const RuntimeShape& input_shape, 00028 const float* input_data, 00029 const RuntimeShape& output_shape, float* output_data) { 00030 TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); 00031 TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); 00032 const int batches = MatchingDim(input_shape, 0, output_shape, 0); 00033 const int depth = MatchingDim(input_shape, 3, output_shape, 3); 00034 const int input_height = input_shape.Dims(1); 00035 const int input_width = input_shape.Dims(2); 00036 const int output_height = output_shape.Dims(1); 00037 const int output_width = output_shape.Dims(2); 00038 const int stride_height = params.stride_height; 00039 const int stride_width = params.stride_width; 00040 for (int batch = 0; batch < batches; ++batch) { 00041 for (int out_y = 0; out_y < output_height; ++out_y) { 00042 for (int out_x = 0; out_x < output_width; ++out_x) { 00043 for (int channel = 0; channel < depth; ++channel) { 00044 const int in_x_origin = 00045 (out_x * stride_width) - params.padding_values.width; 00046 const int in_y_origin = 00047 (out_y * stride_height) - params.padding_values.height; 00048 // Compute the boundaries of the filter region clamped so as to 00049 // ensure that the filter window fits in the input array. 00050 const int filter_x_start = std::max(0, -in_x_origin); 00051 const int filter_x_end = 00052 std::min(params.filter_width, input_width - in_x_origin); 00053 const int filter_y_start = std::max(0, -in_y_origin); 00054 const int filter_y_end = 00055 std::min(params.filter_height, input_height - in_y_origin); 00056 float total = 0.f; 00057 float filter_count = 0; 00058 for (int filter_y = filter_y_start; filter_y < filter_y_end; 00059 ++filter_y) { 00060 for (int filter_x = filter_x_start; filter_x < filter_x_end; 00061 ++filter_x) { 00062 const int in_x = in_x_origin + filter_x; 00063 const int in_y = in_y_origin + filter_y; 00064 total += 00065 input_data[Offset(input_shape, batch, in_y, in_x, channel)]; 00066 filter_count++; 00067 } 00068 } 00069 const float average = total / filter_count; 00070 output_data[Offset(output_shape, batch, out_y, out_x, channel)] = 00071 ActivationFunctionWithMinMax(average, params.float_activation_min, 00072 params.float_activation_max); 00073 } 00074 } 00075 } 00076 } 00077 } 00078 00079 inline void AveragePool(const PoolParams& params, 00080 const RuntimeShape& input_shape, 00081 const uint8* input_data, 00082 const RuntimeShape& output_shape, uint8* output_data) { 00083 TFLITE_DCHECK_LE(params.quantized_activation_min, 00084 params.quantized_activation_max); 00085 TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); 00086 TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); 00087 const int batches = MatchingDim(input_shape, 0, output_shape, 0); 00088 const int depth = MatchingDim(input_shape, 3, output_shape, 3); 00089 const int input_height = input_shape.Dims(1); 00090 const int input_width = input_shape.Dims(2); 00091 const int output_height = output_shape.Dims(1); 00092 const int output_width = output_shape.Dims(2); 00093 const int stride_height = params.stride_height; 00094 const int stride_width = params.stride_width; 00095 for (int batch = 0; batch < batches; ++batch) { 00096 for (int out_y = 0; out_y < output_height; ++out_y) { 00097 for (int out_x = 0; out_x < output_width; ++out_x) { 00098 for (int channel = 0; channel < depth; ++channel) { 00099 const int in_x_origin = 00100 (out_x * stride_width) - params.padding_values.width; 00101 const int in_y_origin = 00102 (out_y * stride_height) - params.padding_values.height; 00103 // Compute the boundaries of the filter region clamped so as to 00104 // ensure that the filter window fits in the input array. 00105 const int filter_x_start = std::max(0, -in_x_origin); 00106 const int filter_x_end = 00107 std::min(params.filter_width, input_width - in_x_origin); 00108 const int filter_y_start = std::max(0, -in_y_origin); 00109 const int filter_y_end = 00110 std::min(params.filter_height, input_height - in_y_origin); 00111 int32 acc = 0; 00112 int filter_count = 0; 00113 for (int filter_y = filter_y_start; filter_y < filter_y_end; 00114 ++filter_y) { 00115 for (int filter_x = filter_x_start; filter_x < filter_x_end; 00116 ++filter_x) { 00117 const int in_x = in_x_origin + filter_x; 00118 const int in_y = in_y_origin + filter_y; 00119 acc += 00120 input_data[Offset(input_shape, batch, in_y, in_x, channel)]; 00121 filter_count++; 00122 } 00123 } 00124 acc = (acc + filter_count / 2) / filter_count; 00125 acc = std::max(acc, params.quantized_activation_min); 00126 acc = std::min(acc, params.quantized_activation_max); 00127 output_data[Offset(output_shape, batch, out_y, out_x, channel)] = 00128 static_cast<uint8>(acc); 00129 } 00130 } 00131 } 00132 } 00133 } 00134 00135 inline void L2Pool(const PoolParams& params, const RuntimeShape& input_shape, 00136 const float* input_data, const RuntimeShape& output_shape, 00137 float* output_data) { 00138 TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); 00139 TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); 00140 const int batches = MatchingDim(input_shape, 0, output_shape, 0); 00141 const int depth = MatchingDim(input_shape, 3, output_shape, 3); 00142 const int input_height = input_shape.Dims(1); 00143 const int input_width = input_shape.Dims(2); 00144 const int output_height = output_shape.Dims(1); 00145 const int output_width = output_shape.Dims(2); 00146 const int stride_height = params.stride_height; 00147 const int stride_width = params.stride_width; 00148 for (int batch = 0; batch < batches; ++batch) { 00149 for (int out_y = 0; out_y < output_height; ++out_y) { 00150 for (int out_x = 0; out_x < output_width; ++out_x) { 00151 for (int channel = 0; channel < depth; ++channel) { 00152 const int in_x_origin = 00153 (out_x * stride_width) - params.padding_values.width; 00154 const int in_y_origin = 00155 (out_y * stride_height) - params.padding_values.height; 00156 // Compute the boundaries of the filter region clamped so as to 00157 // ensure that the filter window fits in the input array. 00158 const int filter_x_start = std::max(0, -in_x_origin); 00159 const int filter_x_end = 00160 std::min(params.filter_width, input_width - in_x_origin); 00161 const int filter_y_start = std::max(0, -in_y_origin); 00162 const int filter_y_end = 00163 std::min(params.filter_height, input_height - in_y_origin); 00164 float sum_squares = 0.f; 00165 int filter_count = 0; 00166 for (int filter_y = filter_y_start; filter_y < filter_y_end; 00167 ++filter_y) { 00168 for (int filter_x = filter_x_start; filter_x < filter_x_end; 00169 ++filter_x) { 00170 const int in_x = in_x_origin + filter_x; 00171 const int in_y = in_y_origin + filter_y; 00172 const float val = 00173 input_data[Offset(input_shape, batch, in_y, in_x, channel)]; 00174 sum_squares += val * val; 00175 filter_count++; 00176 } 00177 } 00178 const float l2pool_result = std::sqrt(sum_squares / filter_count); 00179 output_data[Offset(output_shape, batch, out_y, out_x, channel)] = 00180 ActivationFunctionWithMinMax(l2pool_result, 00181 params.float_activation_min, 00182 params.float_activation_max); 00183 } 00184 } 00185 } 00186 } 00187 } 00188 00189 inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape, 00190 const float* input_data, const RuntimeShape& output_shape, 00191 float* output_data) { 00192 TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); 00193 TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); 00194 const int batches = MatchingDim(input_shape, 0, output_shape, 0); 00195 const int depth = MatchingDim(input_shape, 3, output_shape, 3); 00196 const int input_height = input_shape.Dims(1); 00197 const int input_width = input_shape.Dims(2); 00198 const int output_height = output_shape.Dims(1); 00199 const int output_width = output_shape.Dims(2); 00200 const int stride_height = params.stride_height; 00201 const int stride_width = params.stride_width; 00202 for (int batch = 0; batch < batches; ++batch) { 00203 for (int out_y = 0; out_y < output_height; ++out_y) { 00204 for (int out_x = 0; out_x < output_width; ++out_x) { 00205 for (int channel = 0; channel < depth; ++channel) { 00206 const int in_x_origin = 00207 (out_x * stride_width) - params.padding_values.width; 00208 const int in_y_origin = 00209 (out_y * stride_height) - params.padding_values.height; 00210 // Compute the boundaries of the filter region clamped so as to 00211 // ensure that the filter window fits in the input array. 00212 const int filter_x_start = std::max(0, -in_x_origin); 00213 const int filter_x_end = 00214 std::min(params.filter_width, input_width - in_x_origin); 00215 const int filter_y_start = std::max(0, -in_y_origin); 00216 const int filter_y_end = 00217 std::min(params.filter_height, input_height - in_y_origin); 00218 float max = std::numeric_limits<float>::lowest(); 00219 for (int filter_y = filter_y_start; filter_y < filter_y_end; 00220 ++filter_y) { 00221 for (int filter_x = filter_x_start; filter_x < filter_x_end; 00222 ++filter_x) { 00223 const int in_x = in_x_origin + filter_x; 00224 const int in_y = in_y_origin + filter_y; 00225 max = std::max( 00226 max, 00227 input_data[Offset(input_shape, batch, in_y, in_x, channel)]); 00228 } 00229 } 00230 output_data[Offset(output_shape, batch, out_y, out_x, channel)] = 00231 ActivationFunctionWithMinMax(max, params.float_activation_min, 00232 params.float_activation_max); 00233 } 00234 } 00235 } 00236 } 00237 } 00238 00239 inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape, 00240 const uint8* input_data, const RuntimeShape& output_shape, 00241 uint8* output_data) { 00242 TFLITE_DCHECK_LE(params.quantized_activation_min, 00243 params.quantized_activation_max); 00244 TFLITE_DCHECK_GE(params.quantized_activation_min, 0); 00245 TFLITE_DCHECK_LE(params.quantized_activation_max, 255); 00246 TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); 00247 TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); 00248 const int batches = MatchingDim(input_shape, 0, output_shape, 0); 00249 const int depth = MatchingDim(input_shape, 3, output_shape, 3); 00250 const int input_height = input_shape.Dims(1); 00251 const int input_width = input_shape.Dims(2); 00252 const int output_height = output_shape.Dims(1); 00253 const int output_width = output_shape.Dims(2); 00254 const int stride_height = params.stride_height; 00255 const int stride_width = params.stride_width; 00256 for (int batch = 0; batch < batches; ++batch) { 00257 for (int out_y = 0; out_y < output_height; ++out_y) { 00258 for (int out_x = 0; out_x < output_width; ++out_x) { 00259 for (int channel = 0; channel < depth; ++channel) { 00260 const int in_x_origin = 00261 (out_x * stride_width) - params.padding_values.width; 00262 const int in_y_origin = 00263 (out_y * stride_height) - params.padding_values.height; 00264 // Compute the boundaries of the filter region clamped so as to 00265 // ensure that the filter window fits in the input array. 00266 const int filter_x_start = std::max(0, -in_x_origin); 00267 const int filter_x_end = 00268 std::min(params.filter_width, input_width - in_x_origin); 00269 const int filter_y_start = std::max(0, -in_y_origin); 00270 const int filter_y_end = 00271 std::min(params.filter_height, input_height - in_y_origin); 00272 uint8 max = 0; 00273 for (int filter_y = filter_y_start; filter_y < filter_y_end; 00274 ++filter_y) { 00275 for (int filter_x = filter_x_start; filter_x < filter_x_end; 00276 ++filter_x) { 00277 const int in_x = in_x_origin + filter_x; 00278 const int in_y = in_y_origin + filter_y; 00279 max = std::max( 00280 max, 00281 input_data[Offset(input_shape, batch, in_y, in_x, channel)]); 00282 } 00283 } 00284 max = std::max<uint8>(max, params.quantized_activation_min); 00285 max = std::min<uint8>(max, params.quantized_activation_max); 00286 output_data[Offset(output_shape, batch, out_y, out_x, channel)] = 00287 static_cast<uint8>(max); 00288 } 00289 } 00290 } 00291 } 00292 } 00293 } // namespace reference_ops 00294 } // namespace tflite 00295 00296 #endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_POOLING_H_
Generated on Wed Jul 13 2022 16:03:35 by
