Publishing R3
[platform/upstream/dldt.git] / inference-engine / samples / validation_app / image_decoder.cpp
1 /*
2 // Copyright (c) 2018 Intel Corporation
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 <utility>
18
19 #include "image_decoder.hpp"
20 #include "details/ie_exception.hpp"
21 #include <vector>
22 #include <string>
23 #include <map>
24 #include <iostream>
25 #include <opencv2/core/core.hpp>
26 #include <opencv2/highgui/highgui.hpp>
27 #include <opencv2/imgproc/imgproc.hpp>
28
29 using namespace cv;
30
31 int getLoadModeForChannels(int channels, int base) {
32     switch (channels) {
33     case 1:
34         return base | CV_LOAD_IMAGE_GRAYSCALE;
35     case 3:
36         return base | CV_LOAD_IMAGE_COLOR;
37     }
38     return base | CV_LOAD_IMAGE_UNCHANGED;
39 }
40
41 template <class T>
42 cv::Size addToBlob(std::string name, int batch_pos, Blob& blob, PreprocessingOptions preprocessingOptions) {
43     SizeVector blobSize = blob.dims();
44     int width = static_cast<int>(blobSize[0]);
45     int height = static_cast<int>(blobSize[1]);
46     int channels = static_cast<int>(blobSize[2]);
47     T* blob_data = static_cast<T*>(blob.buffer());
48     Mat orig_image, result_image;
49     int loadMode = getLoadModeForChannels(channels, 0);
50
51     std::string tryName = name;
52
53     // TODO This is a dirty hack to support VOC2007 (where no file extension is put into annotation).
54     //      Rewrite.
55     if (name.find('.') == -1) tryName = name + ".JPEG";
56
57     orig_image = imread(tryName, loadMode);
58
59     if (orig_image.empty()) {
60         THROW_IE_EXCEPTION << "Cannot open image file: " << tryName;
61     }
62
63     // Preprocessing the image
64     Size res = orig_image.size();
65
66     if (preprocessingOptions.resizeCropPolicy == ResizeCropPolicy::Resize) {
67         cv::resize(orig_image, result_image, Size(width, height));
68     } else if (preprocessingOptions.resizeCropPolicy == ResizeCropPolicy::ResizeThenCrop) {
69         Mat resized_image;
70
71         cv::resize(orig_image, resized_image, Size(preprocessingOptions.resizeBeforeCropX, preprocessingOptions.resizeBeforeCropY));
72
73         size_t cx = preprocessingOptions.resizeBeforeCropX / 2;
74         size_t cy = preprocessingOptions.resizeBeforeCropY / 2;
75
76         cv::Rect cropRect(cx - width / 2, cy - height / 2, width, height);
77         result_image = resized_image(cropRect);
78     } else if (preprocessingOptions.resizeCropPolicy == ResizeCropPolicy::DoNothing) {
79         // No image preprocessing to be done here
80         result_image = orig_image;
81     } else {
82         THROW_IE_EXCEPTION << "Unsupported ResizeCropPolicy value";
83     }
84
85     float scaleFactor = preprocessingOptions.scaleValuesTo01 ? 255.0 : 1.0;
86
87     for (int c = 0; c < channels; c++) {
88         for (int h = 0; h < height; h++) {
89             for (int w = 0; w < width; w++) {
90                 blob_data[batch_pos * channels * width * height + c * width * height + h * width + w] =
91                     static_cast<T>(result_image.at<cv::Vec3b>(h, w)[c] / scaleFactor);
92             }
93         }
94     }
95
96     return res;
97 }
98
99 std::map<std::string, cv::Size> convertToBlob(std::vector<std::string> names, int batch_pos, Blob& blob, PreprocessingOptions preprocessingOptions) {
100     if (blob.buffer() == nullptr) {
101         THROW_IE_EXCEPTION << "Blob was not allocated";
102     }
103
104     std::function<cv::Size(std::string, int, Blob&, PreprocessingOptions)> add_func;
105
106     switch (blob.precision()) {
107     case Precision::FP32:
108         add_func = &addToBlob<float>;
109         break;
110     case Precision::FP16:
111     case Precision::Q78:
112     case Precision::I16:
113     case Precision::U16:
114         add_func = &addToBlob<short>;
115         break;
116     default:
117         add_func = &addToBlob<uint8_t>;
118     }
119
120     std::map<std::string, Size> res;
121     for (int b = 0; b < names.size(); b++) {
122         std::string name = names[b];
123         Size orig_size = add_func(name, batch_pos + b, blob, preprocessingOptions);
124         res.insert(std::pair<std::string, Size>(name, orig_size));
125     }
126
127     return res;
128 }
129
130 Size ImageDecoder::loadToBlob(std::string name, Blob& blob, PreprocessingOptions preprocessingOptions) {
131     std::vector<std::string> names = { name };
132     return loadToBlob(names, blob, preprocessingOptions).at(name);
133 }
134
135 std::map<std::string, cv::Size> ImageDecoder::loadToBlob(std::vector<std::string> names, Blob& blob, PreprocessingOptions preprocessingOptions) {
136     return convertToBlob(names, 0, blob, preprocessingOptions);
137 }
138
139 Size ImageDecoder::insertIntoBlob(std::string name, int batch_pos, Blob& blob, PreprocessingOptions preprocessingOptions) {
140     return convertToBlob({ name }, batch_pos, blob, preprocessingOptions).at(name);
141 }