1 /**
2 * Copyright 2020-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 <algorithm>
18 #include "minddata/dataset/kernels/ir/vision/ascend_vision_ir.h"
19
20 #include "minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.h"
21 #include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.h"
22 #include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h"
23 #include "minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.h"
24 #include "minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.h"
25 #include "minddata/dataset/kernels/image/dvpp/dvpp_normalize_op.h"
26 #include "minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.h"
27
28 namespace mindspore {
29 namespace dataset {
30
31 // Transform operations for computer vision
32 namespace vision {
33 /* ####################################### Derived TensorOperation classes ################################# */
34
35 // DvppCropOperation
DvppCropJpegOperation(const std::vector<uint32_t> & crop)36 DvppCropJpegOperation::DvppCropJpegOperation(const std::vector<uint32_t> &crop) : crop_(crop) {}
37
ValidateParams()38 Status DvppCropJpegOperation::ValidateParams() {
39 // size
40 if (crop_.empty() || crop_.size() > 2) {
41 std::string err_msg =
42 "DvppCropJpeg: Crop resolution must be a vector of one or two elements, got: " + std::to_string(crop_.size());
43 MS_LOG(ERROR) << err_msg;
44 RETURN_STATUS_SYNTAX_ERROR(err_msg);
45 }
46 if (*min_element(crop_.begin(), crop_.end()) < 32 || *max_element(crop_.begin(), crop_.end()) > 2048) {
47 std::string err_msg = "Dvpp module supports crop image with resolution in range [32, 2048], got crop Parameters: ";
48 if (crop_.size() == 2) {
49 MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[1] << "]";
50 } else {
51 MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[0] << "]";
52 }
53 RETURN_STATUS_SYNTAX_ERROR(err_msg);
54 }
55 return Status::OK();
56 }
57
Build()58 std::shared_ptr<TensorOp> DvppCropJpegOperation::Build() {
59 // If size is a single value, the smaller edge of the image will be
60 // resized to this value with the same image aspect ratio.
61 uint32_t cropHeight, cropWidth;
62 // User specified the width value.
63 if (crop_.size() == 1) {
64 cropHeight = crop_[0];
65 cropWidth = crop_[0];
66 } else {
67 cropHeight = crop_[0];
68 cropWidth = crop_[1];
69 }
70 std::shared_ptr<DvppCropJpegOp> tensor_op = std::make_shared<DvppCropJpegOp>(cropHeight, cropWidth);
71 return tensor_op;
72 }
73
to_json(nlohmann::json * out_json)74 Status DvppCropJpegOperation::to_json(nlohmann::json *out_json) {
75 nlohmann::json args;
76 args["size"] = crop_;
77 *out_json = args;
78 return Status::OK();
79 }
80
from_json(nlohmann::json op_params,std::shared_ptr<TensorOperation> * operation)81 Status DvppCropJpegOperation::from_json(nlohmann::json op_params, std::shared_ptr<TensorOperation> *operation) {
82 CHECK_FAIL_RETURN_UNEXPECTED(op_params.find("size") != op_params.end(), "Fail to find size");
83 std::vector<uint32_t> resize = op_params["size"];
84 *operation = std::make_shared<vision::DvppCropJpegOperation>(resize);
85 return Status::OK();
86 }
87
88 // DvppDecodeResizeOperation
DvppDecodeResizeOperation(const std::vector<uint32_t> & resize)89 DvppDecodeResizeOperation::DvppDecodeResizeOperation(const std::vector<uint32_t> &resize) : resize_(resize) {}
90
ValidateParams()91 Status DvppDecodeResizeOperation::ValidateParams() {
92 // size
93 if (resize_.empty() || resize_.size() > 2) {
94 std::string err_msg = "DvppDecodeResizeJpeg: resize resolution must be a vector of one or two elements, got: " +
95 std::to_string(resize_.size());
96 MS_LOG(ERROR) << err_msg;
97 RETURN_STATUS_SYNTAX_ERROR(err_msg);
98 }
99 if (*min_element(resize_.begin(), resize_.end()) < 32 || *max_element(resize_.begin(), resize_.end()) > 2048) {
100 std::string err_msg =
101 "Dvpp module supports resize image with resolution in range [32, 2048], got resize Parameters: ";
102 if (resize_.size() == 2) {
103 MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[1] << "]";
104 } else {
105 MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[0] << "]";
106 }
107 RETURN_STATUS_SYNTAX_ERROR(err_msg);
108 }
109 return Status::OK();
110 }
111
Build()112 std::shared_ptr<TensorOp> DvppDecodeResizeOperation::Build() {
113 // If size is a single value, the smaller edge of the image will be
114 // resized to this value with the same image aspect ratio.
115 uint32_t resizeHeight, resizeWidth;
116 // User specified the width value.
117 if (resize_.size() == 1) {
118 resizeHeight = resize_[0];
119 resizeWidth = 0;
120 } else {
121 resizeHeight = resize_[0];
122 resizeWidth = resize_[1];
123 }
124 std::shared_ptr<DvppDecodeResizeJpegOp> tensor_op =
125 std::make_shared<DvppDecodeResizeJpegOp>(resizeHeight, resizeWidth);
126 return tensor_op;
127 }
128
to_json(nlohmann::json * out_json)129 Status DvppDecodeResizeOperation::to_json(nlohmann::json *out_json) {
130 nlohmann::json args;
131 args["size"] = resize_;
132 *out_json = args;
133 return Status::OK();
134 }
135
from_json(nlohmann::json op_params,std::shared_ptr<TensorOperation> * operation)136 Status DvppDecodeResizeOperation::from_json(nlohmann::json op_params, std::shared_ptr<TensorOperation> *operation) {
137 CHECK_FAIL_RETURN_UNEXPECTED(op_params.find("size") != op_params.end(), "Fail to find size");
138 std::vector<uint32_t> resize = op_params["size"];
139 *operation = std::make_shared<vision::DvppDecodeResizeOperation>(resize);
140 return Status::OK();
141 }
142
143 // DvppDecodeResizeCropOperation
DvppDecodeResizeCropOperation(const std::vector<uint32_t> & crop,const std::vector<uint32_t> & resize)144 DvppDecodeResizeCropOperation::DvppDecodeResizeCropOperation(const std::vector<uint32_t> &crop,
145 const std::vector<uint32_t> &resize)
146 : crop_(crop), resize_(resize) {}
147
ValidateParams()148 Status DvppDecodeResizeCropOperation::ValidateParams() {
149 // size
150 if (crop_.empty() || crop_.size() > 2) {
151 std::string err_msg = "DvppDecodeResizeCropJpeg: crop resolution must be a vector of one or two elements, got: " +
152 std::to_string(crop_.size());
153 MS_LOG(ERROR) << err_msg;
154 RETURN_STATUS_SYNTAX_ERROR(err_msg);
155 }
156 if (resize_.empty() || resize_.size() > 2) {
157 std::string err_msg = "DvppDecodeResizeCropJpeg: resize resolution must be a vector of one or two elements, got: " +
158 std::to_string(resize_.size());
159 MS_LOG(ERROR) << err_msg;
160 RETURN_STATUS_SYNTAX_ERROR(err_msg);
161 }
162 if (*min_element(crop_.begin(), crop_.end()) < 32 || *max_element(crop_.begin(), crop_.end()) > 2048) {
163 std::string err_msg = "Dvpp module supports crop image with resolution in range [32, 2048], got Crop Parameters: ";
164 if (crop_.size() == 2) {
165 MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[1] << "]";
166 } else {
167 MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[0] << "]";
168 }
169 RETURN_STATUS_SYNTAX_ERROR(err_msg);
170 }
171 if (*min_element(resize_.begin(), resize_.end()) < 32 || *max_element(resize_.begin(), resize_.end()) > 2048) {
172 std::string err_msg =
173 "Dvpp module supports resize image with resolution in range [32, 2048], got Crop Parameters: ";
174 if (resize_.size() == 2) {
175 MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[1] << "]";
176 } else {
177 MS_LOG(ERROR) << err_msg << "[" << resize_[0] << "]";
178 }
179 RETURN_STATUS_SYNTAX_ERROR(err_msg);
180 }
181 if (crop_.size() < resize_.size()) {
182 if (crop_[0] > MIN(resize_[0], resize_[1])) {
183 std::string err_msg =
184 "Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= "
185 "y[0], and x[1] <= y[1], please verify your input parameters.";
186 MS_LOG(ERROR) << err_msg;
187 RETURN_STATUS_SYNTAX_ERROR(err_msg);
188 }
189 }
190 if (crop_.size() > resize_.size()) {
191 if (MAX(crop_[0], crop_[1]) > resize_[0]) {
192 std::string err_msg =
193 "Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= "
194 "y[0], and x[1] <= y[1], please verify your input parameters.";
195 MS_LOG(ERROR) << err_msg;
196 RETURN_STATUS_SYNTAX_ERROR(err_msg);
197 }
198 }
199 if (crop_.size() == resize_.size()) {
200 for (int32_t i = 0; i < crop_.size(); ++i) {
201 if (crop_[i] > resize_[i]) {
202 std::string err_msg =
203 "Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= "
204 "y[0], and x[1] <= y[1], please verify your input parameters.";
205 MS_LOG(ERROR) << err_msg;
206 RETURN_STATUS_SYNTAX_ERROR(err_msg);
207 }
208 }
209 }
210 return Status::OK();
211 }
212
Build()213 std::shared_ptr<TensorOp> DvppDecodeResizeCropOperation::Build() {
214 // If size is a single value, the smaller edge of the image will be
215 // resized to this value with the same image aspect ratio.
216 uint32_t cropHeight, cropWidth, resizeHeight, resizeWidth;
217 if (crop_.size() == 1) {
218 cropHeight = crop_[0];
219 cropWidth = crop_[0];
220 } else {
221 cropHeight = crop_[0];
222 cropWidth = crop_[1];
223 }
224 // User specified the width value.
225 if (resize_.size() == 1) {
226 resizeHeight = resize_[0];
227 resizeWidth = 0;
228 } else {
229 resizeHeight = resize_[0];
230 resizeWidth = resize_[1];
231 }
232 std::shared_ptr<DvppDecodeResizeCropJpegOp> tensor_op =
233 std::make_shared<DvppDecodeResizeCropJpegOp>(cropHeight, cropWidth, resizeHeight, resizeWidth);
234 return tensor_op;
235 }
236
to_json(nlohmann::json * out_json)237 Status DvppDecodeResizeCropOperation::to_json(nlohmann::json *out_json) {
238 nlohmann::json args;
239 args["crop_size"] = crop_;
240 args["resize_size"] = resize_;
241 *out_json = args;
242 return Status::OK();
243 }
244
from_json(nlohmann::json op_params,std::shared_ptr<TensorOperation> * operation)245 Status DvppDecodeResizeCropOperation::from_json(nlohmann::json op_params, std::shared_ptr<TensorOperation> *operation) {
246 CHECK_FAIL_RETURN_UNEXPECTED(op_params.find("crop_size") != op_params.end(), "Fail to find crop_size");
247 CHECK_FAIL_RETURN_UNEXPECTED(op_params.find("resize_size") != op_params.end(), "Fail to find resize_size");
248 std::vector<uint32_t> crop = op_params["crop_size"];
249 std::vector<uint32_t> resize = op_params["resize_size"];
250 *operation = std::make_shared<vision::DvppDecodeResizeCropOperation>(crop, resize);
251 return Status::OK();
252 }
253
254 // DvppDecodeJPEG
ValidateParams()255 Status DvppDecodeJpegOperation::ValidateParams() { return Status::OK(); }
256
Build()257 std::shared_ptr<TensorOp> DvppDecodeJpegOperation::Build() { return std::make_shared<DvppDecodeJpegOp>(); }
258
259 // DvppDecodePNG
ValidateParams()260 Status DvppDecodePngOperation::ValidateParams() { return Status::OK(); }
261
Build()262 std::shared_ptr<TensorOp> DvppDecodePngOperation::Build() { return std::make_shared<DvppDecodePngOp>(); }
263
264 // DvppNormalize
DvppNormalizeOperation(const std::vector<float> & mean,const std::vector<float> & std)265 DvppNormalizeOperation::DvppNormalizeOperation(const std::vector<float> &mean, const std::vector<float> &std)
266 : mean_(mean), std_(std) {}
267
ValidateParams()268 Status DvppNormalizeOperation::ValidateParams() {
269 if (mean_.size() != 3) {
270 std::string err_msg = "DvppNormalization:: mean expecting size 3, got size: " + std::to_string(mean_.size());
271 MS_LOG(ERROR) << err_msg;
272 RETURN_STATUS_SYNTAX_ERROR(err_msg);
273 }
274 if (std_.size() != 3) {
275 std::string err_msg = "DvppNormalization: std expecting size 3, got size: " + std::to_string(std_.size());
276 MS_LOG(ERROR) << err_msg;
277 RETURN_STATUS_SYNTAX_ERROR(err_msg);
278 }
279 if (*min_element(mean_.begin(), mean_.end()) < 0 || *max_element(mean_.begin(), mean_.end()) > 256) {
280 std::string err_msg =
281 "Normalization can take parameters in range [0, 256] according to math theory of mean and sigma, got mean "
282 "vector" +
283 std::to_string(std_.size());
284 MS_LOG(ERROR) << err_msg;
285 RETURN_STATUS_SYNTAX_ERROR(err_msg);
286 }
287 if (*min_element(std_.begin(), std_.end()) < 0 || *max_element(std_.begin(), std_.end()) > 256) {
288 std::string err_msg =
289 "Normalization can take parameters in range [0, 256] according to math theory of mean and sigma, got mean "
290 "vector" +
291 std::to_string(std_.size());
292 MS_LOG(ERROR) << err_msg;
293 RETURN_STATUS_SYNTAX_ERROR(err_msg);
294 }
295 return Status::OK();
296 }
297
Build()298 std::shared_ptr<TensorOp> DvppNormalizeOperation::Build() {
299 std::shared_ptr<DvppNormalizeOp> tensor_op = std::make_shared<DvppNormalizeOp>(mean_, std_);
300 return tensor_op;
301 }
302
to_json(nlohmann::json * out_json)303 Status DvppNormalizeOperation::to_json(nlohmann::json *out_json) {
304 nlohmann::json args;
305 std::vector<uint32_t> enlarge_mean_;
306 std::vector<uint32_t> enlarge_std_;
307 std::transform(mean_.begin(), mean_.end(), std::back_inserter(enlarge_mean_),
308 [](float i) -> uint32_t { return static_cast<uint32_t>(10000 * i); });
309 std::transform(std_.begin(), std_.end(), std::back_inserter(enlarge_std_),
310 [](float j) -> uint32_t { return static_cast<uint32_t>(10000 * j); });
311 args["mean"] = enlarge_mean_;
312 args["std"] = enlarge_std_;
313 *out_json = args;
314 return Status::OK();
315 }
316
from_json(nlohmann::json op_params,std::shared_ptr<TensorOperation> * operation)317 Status DvppNormalizeOperation::from_json(nlohmann::json op_params, std::shared_ptr<TensorOperation> *operation) {
318 CHECK_FAIL_RETURN_UNEXPECTED(op_params.find("mean") != op_params.end(), "Fail to find mean");
319 CHECK_FAIL_RETURN_UNEXPECTED(op_params.find("std") != op_params.end(), "Fail to find std");
320 std::vector<float> mean = op_params["mean"];
321 std::vector<float> std = op_params["std"];
322 *operation = std::make_shared<vision::DvppNormalizeOperation>(mean, std);
323 return Status::OK();
324 }
325
326 // DvppResizeOperation
DvppResizeJpegOperation(const std::vector<uint32_t> & resize)327 DvppResizeJpegOperation::DvppResizeJpegOperation(const std::vector<uint32_t> &resize) : resize_(resize) {}
328
ValidateParams()329 Status DvppResizeJpegOperation::ValidateParams() {
330 // size
331 if (resize_.empty() || resize_.size() > 2) {
332 std::string err_msg = "DvppResizeJpeg: resize resolution must be a vector of one or two elements, got: " +
333 std::to_string(resize_.size());
334 MS_LOG(ERROR) << err_msg;
335 RETURN_STATUS_SYNTAX_ERROR(err_msg);
336 }
337 if (*min_element(resize_.begin(), resize_.end()) < 32 || *max_element(resize_.begin(), resize_.end()) > 2048) {
338 std::string err_msg =
339 "Dvpp module supports resize image with resolution in range [32, 2048], got resize Parameters: ";
340 if (resize_.size() == 2) {
341 MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[1] << "]";
342 } else {
343 MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[0] << "]";
344 }
345 RETURN_STATUS_SYNTAX_ERROR(err_msg);
346 }
347 return Status::OK();
348 }
349
Build()350 std::shared_ptr<TensorOp> DvppResizeJpegOperation::Build() {
351 // If size is a single value, the smaller edge of the image will be
352 // resized to this value with the same image aspect ratio.
353 uint32_t resizeHeight, resizeWidth;
354 // User specified the width value.
355 if (resize_.size() == 1) {
356 resizeHeight = resize_[0];
357 resizeWidth = 0;
358 } else {
359 resizeHeight = resize_[0];
360 resizeWidth = resize_[1];
361 }
362 std::shared_ptr<DvppResizeJpegOp> tensor_op = std::make_shared<DvppResizeJpegOp>(resizeHeight, resizeWidth);
363 return tensor_op;
364 }
365
to_json(nlohmann::json * out_json)366 Status DvppResizeJpegOperation::to_json(nlohmann::json *out_json) {
367 nlohmann::json args;
368 args["size"] = resize_;
369 *out_json = args;
370 return Status::OK();
371 }
372
from_json(nlohmann::json op_params,std::shared_ptr<TensorOperation> * operation)373 Status DvppResizeJpegOperation::from_json(nlohmann::json op_params, std::shared_ptr<TensorOperation> *operation) {
374 CHECK_FAIL_RETURN_UNEXPECTED(op_params.find("size") != op_params.end(), "Fail to find size");
375 std::vector<uint32_t> resize = op_params["size"];
376 *operation = std::make_shared<vision::DvppResizeJpegOperation>(resize);
377 return Status::OK();
378 }
379 } // namespace vision
380 } // namespace dataset
381 } // namespace mindspore
382