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