• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2021 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 "tools/converter/config_parser/preprocess_parser.h"
18 #include <dirent.h>
19 #include <sys/stat.h>
20 #include <map>
21 #include <vector>
22 #include "tools/converter/preprocess/opencv_utils.h"
23 #include "src/common/log_adapter.h"
24 #include "mindspore/lite/tools/common/string_util.h"
25 #include "src/common/file_utils.h"
26 #include "include/errorcode.h"
27 
28 namespace mindspore {
29 namespace lite {
30 namespace {
31 constexpr int kMinSize = 0;
32 constexpr int kMaxSize = 65535;
33 }  // namespace
ParseInputType(const std::string & input_type_str,preprocess::InputType * input_type)34 int PreprocessParser::ParseInputType(const std::string &input_type_str, preprocess::InputType *input_type) {
35   if (input_type_str == "IMAGE") {
36     (*input_type) = preprocess::IMAGE;
37   } else if (input_type_str == "BIN") {
38     (*input_type) = preprocess::BIN;
39   } else {
40     (*input_type) = preprocess::INPUT_TYPE_MAX;
41     MS_LOG(ERROR) << "INPUT ILLEGAL: input_type must be IMAGE|BIN.";
42     return RET_INPUT_PARAM_INVALID;
43   }
44   return RET_OK;
45 }
46 
ParsePreprocess(const DataPreProcessString & data_pre_process_str,preprocess::DataPreProcessParam * data_pre_process)47 int PreprocessParser::ParsePreprocess(const DataPreProcessString &data_pre_process_str,
48                                       preprocess::DataPreProcessParam *data_pre_process) {
49   int ret;
50   if (!data_pre_process_str.calibrate_path.empty()) {
51     ret = ParseCalibratePath(data_pre_process_str.calibrate_path, &data_pre_process->calibrate_path);
52     if (ret != RET_OK) {
53       MS_LOG(ERROR) << "Parse calibrate path failed.";
54       return ret;
55     }
56   }
57 
58   if (!data_pre_process_str.calibrate_size.empty()) {
59     if (!ConvertIntNum(data_pre_process_str.calibrate_size, &data_pre_process->calibrate_size)) {
60       MS_LOG(ERROR) << "calibrate_size should be a valid number.";
61       return RET_INPUT_PARAM_INVALID;
62     }
63     if (data_pre_process->calibrate_size < kMinSize) {
64       MS_LOG(ERROR) << "calibrate_size must larger 0.";
65       return RET_INPUT_PARAM_INVALID;
66     }
67   }
68 
69   if (!data_pre_process_str.input_type.empty()) {
70     ret = ParseInputType(data_pre_process_str.input_type, &data_pre_process->input_type);
71     if (ret != RET_OK) {
72       MS_LOG(ERROR) << "input_type parse failed.";
73       return ret;
74     }
75   }
76   if (!data_pre_process_str.image_to_format.empty()) {
77     ret =
78       ParseImageToFormat(data_pre_process_str.image_to_format, &data_pre_process->image_pre_process.image_to_format);
79     if (ret != RET_OK) {
80       MS_LOG(ERROR) << "image preprocess parse failed.";
81       return ret;
82     }
83     if (data_pre_process->image_pre_process.image_to_format == preprocess::RGB ||
84         data_pre_process->image_pre_process.image_to_format == preprocess::GRAY) {
85       data_pre_process->image_pre_process.image_to_format_code =
86         preprocess::ConvertColorConversionCodes(data_pre_process->image_pre_process.image_to_format);
87     }
88   }
89   ret = ParseImagePreProcess(data_pre_process_str, &data_pre_process->image_pre_process);
90   if (ret != RET_OK) {
91     MS_LOG(ERROR) << "image preprocess parse failed.";
92     return ret;
93   }
94 
95   ret = CollectCalibInputs(data_pre_process->calibrate_path, data_pre_process->calibrate_size,
96                            &data_pre_process->calibrate_path_vector);
97   if (ret != RET_OK) {
98     MS_LOG(ERROR) << "collect calibrate inputs failed.";
99     return ret;
100   }
101   return RET_OK;
102 }
103 
ParseCalibratePath(const std::string & str,std::map<std::string,std::string> * value)104 int PreprocessParser::ParseCalibratePath(const std::string &str, std::map<std::string, std::string> *value) {
105   if (value == nullptr) {
106     MS_LOG(ERROR) << "value is nullptr.";
107     return RET_ERROR;
108   }
109   auto key_values = SplitStringToVector(str, ',');
110   for (const auto &key_value : key_values) {
111     auto tmp = SplitStringToVector(key_value, ':');
112     if (tmp.size() != 2) {
113       MS_LOG(ERROR) << "vector need size = 2, size is " << tmp.size();
114       return RET_INPUT_PARAM_INVALID;
115     }
116     auto data_path = RealPath(tmp.at(1).c_str());
117     if (data_path.empty()) {
118       MS_LOG(ERROR) << "path is invalid.";
119       return RET_INPUT_PARAM_INVALID;
120     }
121     (*value)[tmp.at(0)] = data_path;
122   }
123   return RET_OK;
124 }
125 
ParseImagePreProcess(const DataPreProcessString & data_pre_process_str,preprocess::ImagePreProcessParam * image_pre_process)126 int PreprocessParser::ParseImagePreProcess(const DataPreProcessString &data_pre_process_str,
127                                            preprocess::ImagePreProcessParam *image_pre_process) {
128   auto ret = ParseImageNormalize(data_pre_process_str, image_pre_process);
129   if (ret != RET_OK) {
130     MS_LOG(ERROR) << "Parse image normalize failed.";
131     return ret;
132   }
133   ret = ParseImageCenterCrop(data_pre_process_str, image_pre_process);
134   if (ret != RET_OK) {
135     MS_LOG(ERROR) << "Parse image center crop failed.";
136     return ret;
137   }
138   ret = ParseImageResize(data_pre_process_str, image_pre_process);
139   if (ret != RET_OK) {
140     MS_LOG(ERROR) << "Parse image resize failed.";
141     return ret;
142   }
143   return RET_OK;
144 }
145 
ParseImageToFormat(const std::string & image_to_format_str,preprocess::ImageToFormat * image_to_format)146 int PreprocessParser::ParseImageToFormat(const std::string &image_to_format_str,
147                                          preprocess::ImageToFormat *image_to_format) {
148   if (image_to_format_str == "RGB") {
149     (*image_to_format) = preprocess::RGB;
150   } else if (image_to_format_str == "GRAY") {
151     (*image_to_format) = preprocess::GRAY;
152   } else if (image_to_format_str == "BGR") {
153     (*image_to_format) = preprocess::BGR;
154   } else {
155     (*image_to_format) = preprocess::IMAGE_TO_FORMAT_MAX;
156     MS_LOG(ERROR) << "INPUT ILLEGAL: image_to_format must be RGB|GRAY|BGR.";
157     return RET_INPUT_PARAM_INVALID;
158   }
159   return RET_OK;
160 }
161 
CollectCalibInputs(const std::map<std::string,std::string> & calibrate_data_path,size_t limited_count,std::map<std::string,std::vector<std::string>> * inputs)162 int PreprocessParser::CollectCalibInputs(const std::map<std::string, std::string> &calibrate_data_path,
163                                          size_t limited_count,
164                                          std::map<std::string, std::vector<std::string>> *inputs) {
165   if (inputs == nullptr) {
166     MS_LOG(ERROR) << "inputs is null";
167     return RET_ERROR;
168   }
169 
170   auto AddImage = [&inputs](const std::string &file, const std::string &input_name) {
171     struct stat buf {};
172     if (stat(file.c_str(), &buf) == 0) {
173       (*inputs)[input_name].push_back(file);
174     } else {
175       MS_LOG(WARNING) << "invalid image file path: " << file;
176     }
177   };
178 
179   for (const auto &image_path : calibrate_data_path) {
180     DIR *root = opendir(image_path.second.c_str());
181     if (root == nullptr) {
182       MS_LOG(ERROR) << "invalid data path: " << image_path;
183       return RET_PARAM_INVALID;
184     }
185     struct dirent *image_dir = readdir(root);
186     size_t count = 0;
187     while (image_dir != nullptr && count < limited_count) {
188       std::string file_name(image_dir->d_name);
189       if (file_name != "." && file_name != "..") {
190         const std::string file_path = image_path.second + "/" + file_name;
191         AddImage(file_path, image_path.first);
192         count++;
193       }
194       image_dir = readdir(root);
195     }
196     auto ret = closedir(root);
197     if (ret != 0) {
198       MS_LOG(ERROR) << " close dir failed.";
199       return RET_ERROR;
200     }
201     auto &cur_inputs = inputs->at(image_path.first);
202     std::sort(cur_inputs.begin(), cur_inputs.end());
203     if (count != limited_count) {
204       MS_LOG(ERROR) << " data path: " << image_path.second << " data count:" << count
205                     << " < limited_count:" << limited_count;
206       return RET_ERROR;
207     }
208   }
209   return RET_OK;
210 }
ParseImageNormalize(const DataPreProcessString & data_pre_process_str,preprocess::ImagePreProcessParam * image_pre_process)211 int PreprocessParser::ParseImageNormalize(const DataPreProcessString &data_pre_process_str,
212                                           preprocess::ImagePreProcessParam *image_pre_process) {
213   if (!data_pre_process_str.normalize_mean.empty() &&
214       !ConvertDoubleVector(data_pre_process_str.normalize_mean, &image_pre_process->normalize_mean)) {
215     MS_LOG(ERROR) << "Convert normalize_mean failed.";
216     return RET_INPUT_PARAM_INVALID;
217   }
218 
219   if (!data_pre_process_str.normalize_std.empty() &&
220       !ConvertDoubleVector(data_pre_process_str.normalize_std, &image_pre_process->normalize_std)) {
221     MS_LOG(ERROR) << "Convert normalize_std failed.";
222     return RET_INPUT_PARAM_INVALID;
223   }
224 
225   return RET_OK;
226 }
ParseImageResize(const DataPreProcessString & data_pre_process_str,preprocess::ImagePreProcessParam * image_pre_process)227 int PreprocessParser::ParseImageResize(const DataPreProcessString &data_pre_process_str,
228                                        preprocess::ImagePreProcessParam *image_pre_process) {
229   if (!data_pre_process_str.resize_width.empty()) {
230     if (!ConvertIntNum(data_pre_process_str.resize_width, &image_pre_process->resize_width)) {
231       MS_LOG(ERROR) << "resize_width should be a valid number.";
232       return RET_INPUT_PARAM_INVALID;
233     }
234     if (image_pre_process->resize_width <= kMinSize || image_pre_process->resize_width > kMaxSize) {
235       MS_LOG(ERROR) << "resize_width must be in [1, 65535].";
236       return RET_INPUT_PARAM_INVALID;
237     }
238   }
239   if (!data_pre_process_str.resize_height.empty()) {
240     if (!ConvertIntNum(data_pre_process_str.resize_height, &image_pre_process->resize_height)) {
241       MS_LOG(ERROR) << "resize_width should be a valid number.";
242       return RET_INPUT_PARAM_INVALID;
243     }
244     if (image_pre_process->resize_height <= kMinSize || image_pre_process->resize_height > kMaxSize) {
245       MS_LOG(ERROR) << "resize_height must be in [1, 65535].";
246       return RET_INPUT_PARAM_INVALID;
247     }
248   }
249 
250   if (!data_pre_process_str.resize_method.empty()) {
251     image_pre_process->resize_method = preprocess::ConvertResizeMethod(data_pre_process_str.resize_method);
252     if (image_pre_process->resize_method == cv::INTER_MAX) {
253       MS_LOG(ERROR) << "INPUT ILLEGAL: resize_method must be NEAREST|LINEAR|CUBIC.";
254       return RET_INPUT_PARAM_INVALID;
255     }
256   }
257   return RET_OK;
258 }
ParseImageCenterCrop(const DataPreProcessString & data_pre_process_str,preprocess::ImagePreProcessParam * image_pre_process)259 int PreprocessParser::ParseImageCenterCrop(const DataPreProcessString &data_pre_process_str,
260                                            preprocess::ImagePreProcessParam *image_pre_process) {
261   if (!data_pre_process_str.center_crop_width.empty()) {
262     if (!ConvertIntNum(data_pre_process_str.center_crop_width, &image_pre_process->center_crop_width)) {
263       MS_LOG(ERROR) << "center_crop_width should be a valid number.";
264       return RET_INPUT_PARAM_INVALID;
265     }
266     if (image_pre_process->center_crop_width <= kMinSize || image_pre_process->center_crop_width > kMaxSize) {
267       MS_LOG(ERROR) << "center_crop_width must be in [1, 65535].";
268       return RET_INPUT_PARAM_INVALID;
269     }
270   }
271   if (!data_pre_process_str.center_crop_height.empty()) {
272     if (!ConvertIntNum(data_pre_process_str.center_crop_height, &image_pre_process->center_crop_height)) {
273       MS_LOG(ERROR) << "center_crop_height should be a valid number.";
274       return RET_INPUT_PARAM_INVALID;
275     }
276     if (image_pre_process->center_crop_height <= kMinSize || image_pre_process->center_crop_height > kMaxSize) {
277       MS_LOG(ERROR) << "center_crop_height must be in [1, 65535].";
278       return RET_INPUT_PARAM_INVALID;
279     }
280   }
281   return RET_OK;
282 }
283 }  // namespace lite
284 }  // namespace mindspore
285