summaryrefslogtreecommitdiff
path: root/inference-engine/include/inference_engine.hpp
blob: 08f043e377ab0b577948ae888e25f71455ebab07 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// Copyright (C) 2018 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//

/**
 * @brief A header file that provides a set of convenience utility functions and the main include file for all other .h files.
 * @file inference_engine.hpp
 */
#pragma once

#include <vector>
#include <numeric>
#include <algorithm>
#include <memory>

#include <ie_blob.h>
#include <ie_api.h>
#include <ie_error.hpp>
#include <ie_layers.h>
#include <ie_device.hpp>
#include <ie_plugin_dispatcher.hpp>
#include <ie_plugin_config.hpp>
#include <ie_icnn_network.hpp>
#include <ie_icnn_network_stats.hpp>
#include <cpp/ie_cnn_net_reader.h>
#include <cpp/ie_plugin_cpp.hpp>
#include <cpp/ie_executable_network.hpp>
#include <ie_version.hpp>

namespace InferenceEngine {
/**
 * @brief Gets the top n results from a tblob
 * @param n Top n count
 * @param input 1D tblob that contains probabilities
 * @param output Vector of indexes for the top n places
 */
template<class T>
inline void TopResults(unsigned int n, TBlob<T> &input, std::vector<unsigned> &output) {
    size_t input_rank = input.dims().size();
    if (!input_rank || !input.dims().at(input_rank - 1))
        THROW_IE_EXCEPTION << "Input blob has incorrect dimensions!";
    size_t batchSize = input.dims().at(input_rank - 1);
    std::vector<unsigned> indexes(input.size() / batchSize);

    n = static_cast<unsigned>(std::min<size_t>((size_t) n, input.size()));

    output.resize(n * batchSize);

    for (size_t i = 0; i < batchSize; i++) {
        size_t offset = i * (input.size() / batchSize);
        T *batchData = input.data();
        batchData += offset;

        std::iota(std::begin(indexes), std::end(indexes), 0);
        std::partial_sort(std::begin(indexes), std::begin(indexes) + n, std::end(indexes),
                          [&batchData](unsigned l, unsigned r) {
                              return batchData[l] > batchData[r];
                          });
        for (unsigned j = 0; j < n; j++) {
            output.at(i * n + j) = indexes.at(j);
        }
    }
}

#define TBLOB_TOP_RESULT(precision)\
    case InferenceEngine::Precision::precision  : {\
        using myBlobType = InferenceEngine::PrecisionTrait<Precision::precision>::value_type;\
        TBlob<myBlobType> &tblob = dynamic_cast<TBlob<myBlobType> &>(input);\
        TopResults(n, tblob, output);\
        break;\
    }

/**
 * @brief Gets the top n results from a blob
 * @param n Top n count
 * @param input 1D blob that contains probabilities
 * @param output Vector of indexes for the top n places
 */
inline void TopResults(unsigned int n, Blob &input, std::vector<unsigned> &output) {
    switch (input.precision()) {
        TBLOB_TOP_RESULT(FP32);
        TBLOB_TOP_RESULT(FP16);
        TBLOB_TOP_RESULT(Q78);
        TBLOB_TOP_RESULT(I16);
        TBLOB_TOP_RESULT(U8);
        TBLOB_TOP_RESULT(I8);
        TBLOB_TOP_RESULT(U16);
        TBLOB_TOP_RESULT(I32);
        default:
            THROW_IE_EXCEPTION << "cannot locate blob for precision: " << input.precision();
    }
}

#undef TBLOB_TOP_RESULT

/**
 * @brief Copies a 8-bit RGB image to the blob.
 * Throws an exception in case of dimensions or input size mismatch
 * @tparam data_t Type of the target blob
 * @param RGB8 8-bit RGB image
 * @param RGB8_size Size of the image
 * @param blob Target blob to write image to
 */
template<typename data_t>
void copyFromRGB8(uint8_t *RGB8, size_t RGB8_size, InferenceEngine::TBlob<data_t> *blob) {
    if (4 != blob->dims().size())
        THROW_IE_EXCEPTION << "Cannot write data to input blob! Blob has incorrect dimensions size "
                           << blob->dims().size();
    size_t num_channels = blob->dims()[2];  // because RGB
    size_t num_images = blob->dims()[3];
    size_t w = blob->dims()[0];
    size_t h = blob->dims()[1];
    size_t nPixels = w * h;

    if (RGB8_size != w * h * num_channels * num_images)
        THROW_IE_EXCEPTION << "input pixels mismatch, expecting " << w * h * num_channels * num_images
                           << " bytes, got: " << RGB8_size;

    std::vector<data_t *> dataArray;
    for (unsigned int n = 0; n < num_images; n++) {
        for (unsigned int i = 0; i < num_channels; i++) {
            if (!n && !i && dataArray.empty()) {
                dataArray.push_back(blob->data());
            } else {
                dataArray.push_back(dataArray.at(n * num_channels + i - 1) + nPixels);
            }
        }
    }
    for (size_t n = 0; n < num_images; n++) {
        size_t n_num_channels = n * num_channels;
        size_t n_num_channels_nPixels = n_num_channels * nPixels;
        for (size_t i = 0; i < nPixels; i++) {
            size_t i_num_channels = i * num_channels + n_num_channels_nPixels;
            for (size_t j = 0; j < num_channels; j++) {
                dataArray.at(n_num_channels + j)[i] = RGB8[i_num_channels + j];
            }
        }
    }
}

/**
 * @brief Splits the RGB channels to either I16 Blob or float blob.
 * The image buffer is assumed to be packed with no support for strides.
 * @param imgBufRGB8 Packed 24bit RGB image (3 bytes per pixel: R-G-B)
 * @param lengthbytesSize Size in bytes of the RGB image. It is equal to amount of pixels times 3 (number of channels)
 * @param input Blob to contain the split image (to 3 channels)
 */
inline void ConvertImageToInput(unsigned char *imgBufRGB8, size_t lengthbytesSize, Blob &input) {
    TBlob<float> *float_input = dynamic_cast<TBlob<float> *>(&input);
    if (float_input != nullptr) copyFromRGB8(imgBufRGB8, lengthbytesSize, float_input);

    TBlob<short> *short_input = dynamic_cast<TBlob<short> *>(&input);
    if (short_input != nullptr) copyFromRGB8(imgBufRGB8, lengthbytesSize, short_input);

    TBlob<uint8_t> *byte_input = dynamic_cast<TBlob<uint8_t> *>(&input);
    if (byte_input != nullptr) copyFromRGB8(imgBufRGB8, lengthbytesSize, byte_input);
}

/**
 * @brief Copies data from a certain precision to float
 * @param dst Pointer to an output float buffer, must be allocated before the call
 * @param src Source blob to take data from
 */
template<typename T>
void copyToFloat(float *dst, const InferenceEngine::Blob *src) {
    if (!dst) {
        return;
    }
    const InferenceEngine::TBlob<T> *t_blob = dynamic_cast<const InferenceEngine::TBlob<T> *>(src);
    if (t_blob == nullptr) {
        THROW_IE_EXCEPTION << "input type is " << src->precision() << " but input is not " << typeid(T).name();
    }

    const T *srcPtr = t_blob->readOnly();
    if (srcPtr == nullptr) {
        THROW_IE_EXCEPTION << "Input data was not allocated.";
    }
    for (size_t i = 0; i < t_blob->size(); i++) dst[i] = srcPtr[i];
}

}  // namespace InferenceEngine