1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef TENSORFLOW_LITE_EXAMPLES_LABEL_CLASSIFY_BITMAP_HELPERS_H
17 #define TENSORFLOW_LITE_EXAMPLES_LABEL_CLASSIFY_BITMAP_HELPERS_H
18
19 #include "tflite/label_classify/label_classify.h"
20 #include "tensorflow/lite/builtin_op_data.h"
21 #include "tensorflow/lite/interpreter.h"
22 #include "tensorflow/lite/kernels/register.h"
23 #include "tensorflow/lite/string_util.h"
24 #include "log.h"
25
26
27 namespace tflite {
28 namespace label_classify {
29 const int INPUT_NUMBER = 2;
30 const int OUPUT_NUMBER = 1;
31 const int INT8_OFFSET_NUMBER = 128;
32 const int BIT_TO_BYTE = 8;
33 const int BLUE_OFFSET = 2;
34 const int GREEN_OFFSET = 1;
35 const int ALPHA_OFFSET = 3;
36 const int HEADER_ADDRESS_OFFSET = 10;
37 const int WIDTH_ADDRESS_OFFSET = 18;
38 const int HEIGHT_ADDRESS_OFFSET = 22;
39 const int BBP_ADDRESS_OFFSET = 28;
40 enum ChannelDim : int {
41 GRAYSCALE_DIM = 1,
42 BGR_DIM = 3,
43 BGRA_DIM = 4
44 };
45
46 struct BmpAddressOffset {
47 int headerAddressOffset = 0;
48 int widthAddressOffset = 0;
49 int heightAddressOffset = 0;
50 int bbpAddressOffset = 0;
51 };
52
53 struct ColorChannelOffset {
54 int blueOffset = 0;
55 int greenOffset = 0;
56 int alphaOffset = 0;
57 };
58
59 struct ImageInfo {
60 int32_t width = 0;
61 int32_t height = 0;
62 int32_t channels = 0;
63 };
64
65 void ReadBmp(const std::string& input_bmp_name, ImageInfo& imageInfo, Settings* s, std::vector<uint8_t>& input);
66
67 template <typename T>
Resize(T * out,uint8_t * in,ImageInfo inputImageInfo,ImageInfo wantedImageInfo,Settings * s)68 void Resize(T* out, uint8_t* in, ImageInfo inputImageInfo, ImageInfo wantedImageInfo, Settings* s)
69 {
70 std::unique_ptr<Interpreter> interpreter = std::make_unique<Interpreter>();
71
72 int32_t baseIndex = 0;
73 int32_t outputIndex = 2;
74
75 // two inputs: input and new_sizes
76 interpreter->AddTensors(INPUT_NUMBER, &baseIndex);
77 // one output
78 interpreter->AddTensors(OUPUT_NUMBER, &baseIndex);
79 // set input and output tensors
80 interpreter->SetInputs({ 0, 1 });
81 interpreter->SetOutputs({ 2 });
82
83 // set parameters of tensors
84 TfLiteQuantizationParams quant;
85 interpreter->SetTensorParametersReadWrite(0, kTfLiteFloat32, "input",
86 { 1, inputImageInfo.height, inputImageInfo.width, inputImageInfo.channels }, quant);
87 interpreter->SetTensorParametersReadWrite(1, kTfLiteInt32, "new_size", { 2 }, quant);
88 interpreter->SetTensorParametersReadWrite(outputIndex, kTfLiteFloat32, "output",
89 { 1, wantedImageInfo.height, wantedImageInfo.width, wantedImageInfo.channels }, quant);
90
91 ops::builtin::BuiltinOpResolver resolver;
92 const TfLiteRegistration* resizeOp = resolver.FindOp(BuiltinOperator_RESIZE_BILINEAR, 1);
93 auto* params = reinterpret_cast<TfLiteResizeBilinearParams*>(malloc(sizeof(TfLiteResizeBilinearParams)));
94 if (params == nullptr) {
95 LOG(ERROR) << "Malloc memory failed in BitmapHelperslmpl.";
96 return;
97 }
98 params->align_corners = false;
99 params->half_pixel_centers = false;
100 interpreter->AddNodeWithParameters({ 0, 1 }, { 2 }, nullptr, 0, params, resizeOp, nullptr);
101 interpreter->AllocateTensors();
102
103 // fill input image
104 // in[] are integers, cannot do memcpy() directly
105 auto input = interpreter->typed_tensor<float>(0);
106
107 for (int32_t i = 0; i < inputImageInfo.height * inputImageInfo.width * inputImageInfo.channels; ++i) {
108 input[i] = in[i];
109 }
110
111 // fill new_sizes
112 interpreter->typed_tensor<int32_t>(1)[0] = wantedImageInfo.height;
113 interpreter->typed_tensor<int32_t>(1)[1] = wantedImageInfo.width;
114 interpreter->Invoke();
115 auto output = interpreter->typed_tensor<float>(2);
116 for (int32_t i = 0; i < wantedImageInfo.height * wantedImageInfo.width * wantedImageInfo.channels; ++i) {
117 switch (s->inputType) {
118 case kTfLiteFloat32:
119 out[i] = (output[i] - s->inputMean) / s->inputStd;
120 break;
121 case kTfLiteInt8:
122 out[i] = static_cast<int8_t>(output[i] - INT8_OFFSET_NUMBER);
123 break;
124 case kTfLiteUInt8:
125 out[i] = static_cast<uint8_t>(output[i]);
126 break;
127 default:
128 break;
129 }
130 }
131 }
132
133 // explicit instantiation
134 template void Resize<float>(float*, uint8_t*, ImageInfo, ImageInfo, Settings*);
135 template void Resize<int8_t>(int8_t*, uint8_t*, ImageInfo, ImageInfo, Settings*);
136 template void Resize<uint8_t>(uint8_t*, uint8_t*, ImageInfo, ImageInfo, Settings*);
137 template void Resize<int64_t>(int64_t*, uint8_t*, ImageInfo, ImageInfo, Settings*);
138 } // namespace label_classify
139 } // namespace tflite
140
141 #endif // TENSORFLOW_LITE_EXAMPLES_LABEL_CLASSIFY_BITMAP_HELPERS_H
142