Skip to content

Commit c70b055

Browse files
OV2.0 API C++ gaze estimation demo (#3085)
* add 98 model to gaze_estimation_demo * comment new model * OV2.0 API C++ gaze_estimation_demo * change year * change common.hpp * logmModel in demo * remove unnecessary changes, suppress warnings, unify basic model info logging * little changes * update ie_wrapper.cpp and landmarks_estimator.cpp * Update ie_wrapper.cpp Co-authored-by: Vladimir Dudnik <[email protected]>
1 parent 53a5e98 commit c70b055

15 files changed

+296
-237
lines changed

demos/common/cpp/utils/include/utils/common.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#endif
3737

3838
template <typename T, std::size_t N>
39-
constexpr std::size_t arraySize(const T (&)[N]) noexcept {
39+
constexpr std::size_t arraySize(const T(&)[N]) noexcept {
4040
return N;
4141
}
4242

@@ -221,7 +221,7 @@ inline void showAvailableDevices() {
221221
std::cout << std::endl;
222222
}
223223

224-
inline std::string fileNameNoExt(const std::string &filepath) {
224+
inline std::string fileNameNoExt(const std::string& filepath) {
225225
auto pos = filepath.rfind('.');
226226
if (pos == std::string::npos) return filepath;
227227
return filepath.substr(0, pos);

demos/common/cpp/utils/include/utils/ocv_common.hpp

Lines changed: 87 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414
#include "utils/common.hpp"
1515
#include "utils/shared_blob_allocator.h"
1616

17+
#include "openvino/openvino.hpp"
1718

18-
/**
19-
* @brief Get cv::Mat value in the correct format.
20-
*/
19+
20+
/**
21+
* @brief Get cv::Mat value in the correct format.
22+
*/
2123
template <typename T>
2224
static const T getMatValue(const cv::Mat& mat, size_t h, size_t w, size_t c) {
2325
switch (mat.type()) {
@@ -48,9 +50,11 @@ static UNUSED void matToBlob(const cv::Mat& mat, const InferenceEngine::Blob::Pt
4850
}
4951
int batchOffset = batchIndex * width * height * channels;
5052

51-
cv::Mat resizedMat(mat);
53+
cv::Mat resizedMat;
5254
if (static_cast<int>(width) != mat.size().width || static_cast<int>(height) != mat.size().height) {
5355
cv::resize(mat, resizedMat, cv::Size(width, height));
56+
} else {
57+
resizedMat = mat;
5458
}
5559

5660
InferenceEngine::LockedMemory<void> blobMapped = InferenceEngine::as<InferenceEngine::MemoryBlob>(blob)->wmap();
@@ -61,10 +65,9 @@ static UNUSED void matToBlob(const cv::Mat& mat, const InferenceEngine::Blob::Pt
6165
for (size_t w = 0; w < width; w++)
6266
blobData[batchOffset + c * width * height + h * width + w] =
6367
getMatValue<float_t>(resizedMat, h, w, c);
64-
}
65-
else {
68+
} else {
6669
uint8_t* blobData = blobMapped.as<uint8_t*>();
67-
if ((resizedMat.type() & CV_MAT_DEPTH_MASK) == CV_32F) {
70+
if (resizedMat.depth() == CV_32F) {
6871
throw std::runtime_error("Conversion of cv::Mat from float_t to uint8_t is forbidden");
6972
}
7073
for (size_t c = 0; c < channels; c++)
@@ -75,14 +78,62 @@ static UNUSED void matToBlob(const cv::Mat& mat, const InferenceEngine::Blob::Pt
7578
}
7679
}
7780

81+
/**
82+
* @brief Resize and copy image data from cv::Mat object to a given Tensor object.
83+
* @param mat - given cv::Mat object with an image data.
84+
* @param tensor - Tensor object which to be filled by an image data.
85+
* @param batchIndex - batch index of an image inside of the blob.
86+
*/
87+
static UNUSED void matToTensor(const cv::Mat& mat, const ov::runtime::Tensor& tensor, int batchIndex = 0) {
88+
ov::Shape tensorShape = tensor.get_shape();
89+
ov::Layout layout("NCHW");
90+
const size_t width = tensorShape[ov::layout::width_idx(layout)];
91+
const size_t height = tensorShape[ov::layout::height_idx(layout)];
92+
const size_t channels = tensorShape[ov::layout::channels_idx(layout)];
93+
if (static_cast<size_t>(mat.channels()) != channels) {
94+
throw std::runtime_error("The number of channels for net input and image must match");
95+
}
96+
if (channels != 1 && channels != 3) {
97+
throw std::runtime_error("Unsupported number of channels");
98+
}
99+
int batchOffset = batchIndex * width * height * channels;
100+
101+
cv::Mat resizedMat;
102+
if (static_cast<int>(width) != mat.size().width || static_cast<int>(height) != mat.size().height) {
103+
cv::resize(mat, resizedMat, cv::Size(width, height));
104+
} else {
105+
resizedMat = mat;
106+
}
107+
108+
if (tensor.get_element_type() == ov::element::f32) {
109+
float_t* tensorData = tensor.data<float_t>();
110+
for (size_t c = 0; c < channels; c++)
111+
for (size_t h = 0; h < height; h++)
112+
for (size_t w = 0; w < width; w++)
113+
tensorData[batchOffset + c * width * height + h * width + w] =
114+
getMatValue<float_t>(resizedMat, h, w, c);
115+
}
116+
else {
117+
uint8_t* tensorData = tensor.data<uint8_t>();
118+
if (resizedMat.depth() == CV_32F) {
119+
throw std::runtime_error("Conversion of cv::Mat from float_t to uint8_t is forbidden");
120+
}
121+
for (size_t c = 0; c < channels; c++)
122+
for (size_t h = 0; h < height; h++)
123+
for (size_t w = 0; w < width; w++)
124+
tensorData[batchOffset + c * width * height + h * width + w] =
125+
getMatValue<uint8_t>(resizedMat, h, w, c);
126+
}
127+
}
128+
78129
/**
79130
* @brief Wraps data stored inside of a passed cv::Mat object by new Blob pointer.
80131
* @note: No memory allocation is happened. The blob just points to already existing
81132
* cv::Mat data.
82133
* @param mat - given cv::Mat object with an image data.
83134
* @return resulting Blob pointer.
84135
*/
85-
static UNUSED InferenceEngine::Blob::Ptr wrapMat2Blob(const cv::Mat &mat) {
136+
static UNUSED InferenceEngine::Blob::Ptr wrapMat2Blob(const cv::Mat& mat) {
86137
auto matType = mat.type() & CV_MAT_DEPTH_MASK;
87138
if (matType != CV_8U && matType != CV_32F) {
88139
throw std::runtime_error("Unsupported mat type for wrapping");
@@ -104,21 +155,34 @@ static UNUSED InferenceEngine::Blob::Ptr wrapMat2Blob(const cv::Mat &mat) {
104155
InferenceEngine::Precision precision = isMatFloat ?
105156
InferenceEngine::Precision::FP32 : InferenceEngine::Precision::U8;
106157
InferenceEngine::TensorDesc tDesc(precision,
107-
{1, channels, height, width},
108-
InferenceEngine::Layout::NHWC);
158+
{ 1, channels, height, width },
159+
InferenceEngine::Layout::NHWC);
109160

110161
InferenceEngine::Blob::Ptr blob;
111162
if (isMatFloat) {
112163
blob = InferenceEngine::make_shared_blob<float>(tDesc, std::make_shared<SharedBlobAllocator>(mat));
113-
}
114-
else {
164+
} else {
115165
blob = InferenceEngine::make_shared_blob<uint8_t>(tDesc, std::make_shared<SharedBlobAllocator>(mat));
116166
}
117167

118168
blob->allocate();
119169
return blob;
120170
}
121171

172+
static UNUSED ov::runtime::Tensor wrapMat2Tensor(const cv::Mat& mat) {
173+
const size_t channels = mat.channels();
174+
const size_t height = mat.size().height;
175+
const size_t width = mat.size().width;
176+
177+
const size_t strideH = mat.step.buf[0];
178+
const size_t strideW = mat.step.buf[1];
179+
180+
const bool is_dense = strideW == channels && strideH == channels * width;
181+
OPENVINO_ASSERT(is_dense, "Doesn't support conversion from not dense cv::Mat");
182+
183+
return ov::runtime::Tensor(ov::element::u8, ov::Shape{ 1, height, width, channels }, mat.data);
184+
}
185+
122186
/**
123187
* @brief Puts text message on the frame, highlights the text with a white border to make it distinguishable from
124188
* the background.
@@ -131,12 +195,12 @@ static UNUSED InferenceEngine::Blob::Ptr wrapMat2Blob(const cv::Mat &mat) {
131195
* @param thickness - thickness of the lines used to draw a text.
132196
*/
133197
inline void putHighlightedText(const cv::Mat& frame,
134-
const std::string& message,
135-
cv::Point position,
136-
int fontFace,
137-
double fontScale,
138-
cv::Scalar color,
139-
int thickness) {
198+
const std::string& message,
199+
cv::Point position,
200+
int fontFace,
201+
double fontScale,
202+
cv::Scalar color,
203+
int thickness) {
140204
cv::putText(frame, message, position, fontFace, fontScale, cv::Scalar(255, 255, 255), thickness + 1);
141205
cv::putText(frame, message, position, fontFace, fontScale, color, thickness);
142206
}
@@ -153,7 +217,7 @@ class OutputTransform {
153217
float inputWidth = static_cast<float>(inputSize.width);
154218
float inputHeight = static_cast<float>(inputSize.height);
155219
scaleFactor = std::min(outputResolution.height / inputHeight, outputResolution.width / inputWidth);
156-
newResolution = cv::Size{static_cast<int>(inputWidth * scaleFactor), static_cast<int>(inputHeight * scaleFactor)};
220+
newResolution = cv::Size{ static_cast<int>(inputWidth * scaleFactor), static_cast<int>(inputHeight * scaleFactor) };
157221
return newResolution;
158222
}
159223

@@ -197,20 +261,21 @@ class InputTransform {
197261
public:
198262
InputTransform() : reverseInputChannels(false), isTrivial(true) {}
199263

200-
InputTransform(bool reverseInputChannels, const std::string &meanValues, const std::string &scaleValues) :
264+
InputTransform(bool reverseInputChannels, const std::string& meanValues, const std::string& scaleValues) :
201265
reverseInputChannels(reverseInputChannels),
202266
isTrivial(!reverseInputChannels && meanValues.empty() && scaleValues.empty()),
203267
means(meanValues.empty() ? cv::Scalar(0.0, 0.0, 0.0) : string2Vec(meanValues)),
204268
stdScales(scaleValues.empty() ? cv::Scalar(1.0, 1.0, 1.0) : string2Vec(scaleValues)) {
205269
}
206270

207-
cv::Scalar string2Vec(const std::string &string) {
271+
cv::Scalar string2Vec(const std::string& string) {
208272
const auto& strValues = split(string, ' ');
209273
std::vector<float> values;
210274
try {
211275
for (auto& str : strValues)
212276
values.push_back(std::stof(str));
213-
} catch (const std::invalid_argument&) {
277+
}
278+
catch (const std::invalid_argument&) {
214279
throw std::runtime_error("Invalid parameter --mean_values or --scale_values is provided.");
215280
}
216281
if (values.size() != 3) {

demos/gaze_estimation_demo/cpp/include/eye_state_estimator.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2018 Intel Corporation
1+
// Copyright (C) 2018-2022 Intel Corporation
22
// SPDX-License-Identifier: Apache-2.0
33
//
44

@@ -15,7 +15,7 @@
1515
namespace gaze_estimation {
1616
class EyeStateEstimator: public BaseEstimator {
1717
public:
18-
EyeStateEstimator(InferenceEngine::Core& ie,
18+
EyeStateEstimator(ov::runtime::Core& ie,
1919
const std::string& modelPath,
2020
const std::string& deviceName);
2121
void estimate(const cv::Mat& image, FaceInferenceResults& outputResults) override;
@@ -28,6 +28,6 @@ class EyeStateEstimator: public BaseEstimator {
2828
void rotateImageAroundCenter(const cv::Mat& srcImage, cv::Mat& dstImage, float angle) const;
2929

3030
IEWrapper ieWrapper;
31-
std::string inputBlobName, outputBlobName;
31+
std::string inputTensorName, outputTensorName;
3232
};
3333
} // namespace gaze_estimation

demos/gaze_estimation_demo/cpp/include/face_detector.hpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2018 Intel Corporation
1+
// Copyright (C) 2018-2022 Intel Corporation
22
// SPDX-License-Identifier: Apache-2.0
33
//
44

@@ -8,7 +8,6 @@
88
#include <vector>
99
#include <map>
1010

11-
#include <inference_engine.hpp>
1211
#include <opencv2/core/core.hpp>
1312

1413
#include "face_inference_results.hpp"
@@ -17,7 +16,7 @@
1716
namespace gaze_estimation {
1817
class FaceDetector {
1918
public:
20-
FaceDetector(InferenceEngine::Core& ie,
19+
FaceDetector(ov::runtime::Core& ie,
2120
const std::string& modelPath,
2221
const std::string& deviceName,
2322
double detectionConfidenceThreshold,
@@ -29,9 +28,9 @@ class FaceDetector {
2928

3029
private:
3130
IEWrapper ieWrapper;
32-
std::string inputBlobName;
33-
std::vector<unsigned long> inputBlobDims;
34-
std::string outputBlobName;
31+
std::string inputTensorName;
32+
ov::Shape inputTensorDims;
33+
std::string outputTensorName;
3534
std::size_t numTotalDetections;
3635

3736
double detectionThreshold;

demos/gaze_estimation_demo/cpp/include/gaze_estimator.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2018 Intel Corporation
1+
// Copyright (C) 2018-2022 Intel Corporation
22
// SPDX-License-Identifier: Apache-2.0
33
//
44

@@ -15,7 +15,7 @@
1515
namespace gaze_estimation {
1616
class GazeEstimator: public BaseEstimator {
1717
public:
18-
GazeEstimator(InferenceEngine::Core& ie,
18+
GazeEstimator(ov::runtime::Core& ie,
1919
const std::string& modelPath,
2020
const std::string& deviceName,
2121
bool doRollAlign = true);
@@ -27,7 +27,7 @@ class GazeEstimator: public BaseEstimator {
2727

2828
private:
2929
IEWrapper ieWrapper;
30-
std::string outputBlobName;
30+
std::string outputTensorName;
3131
bool rollAlign;
3232

3333
void rotateImageAroundCenter(const cv::Mat& srcImage, cv::Mat& dstImage, float angle) const;

demos/gaze_estimation_demo/cpp/include/head_pose_estimator.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2018 Intel Corporation
1+
// Copyright (C) 2018-2022 Intel Corporation
22
// SPDX-License-Identifier: Apache-2.0
33
//
44

@@ -15,7 +15,7 @@
1515
namespace gaze_estimation {
1616
class HeadPoseEstimator: public BaseEstimator {
1717
public:
18-
HeadPoseEstimator(InferenceEngine::Core& ie,
18+
HeadPoseEstimator(ov::runtime::Core& ie,
1919
const std::string& modelPath,
2020
const std::string& deviceName);
2121
void estimate(const cv::Mat& image,
@@ -26,6 +26,6 @@ class HeadPoseEstimator: public BaseEstimator {
2626

2727
private:
2828
IEWrapper ieWrapper;
29-
std::string inputBlobName;
29+
std::string inputTensorName;
3030
};
3131
} // namespace gaze_estimation

demos/gaze_estimation_demo/cpp/include/ie_wrapper.hpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2018 Intel Corporation
1+
// Copyright (C) 2018-2022 Intel Corporation
22
// SPDX-License-Identifier: Apache-2.0
33
//
44

@@ -16,40 +16,40 @@
1616
namespace gaze_estimation {
1717
class IEWrapper {
1818
public:
19-
IEWrapper(InferenceEngine::Core& ie,
19+
IEWrapper(ov::runtime::Core& core,
2020
const std::string& modelPath,
2121
const std::string& modelType,
2222
const std::string& deviceName);
23-
// For setting input blobs containing images
24-
void setInputBlob(const std::string& blobName, const cv::Mat& image);
25-
// For setting input blobs containing vectors of data
26-
void setInputBlob(const std::string& blobName, const std::vector<float>& data);
23+
// For setting input tensors containing images
24+
void setInputTensor(const std::string& tensorName, const cv::Mat& image);
25+
// For setting input tensors containing vectors of data
26+
void setInputTensor(const std::string& tensorName, const std::vector<float>& data);
2727

28-
// Get output blob content as a vector given its name
29-
void getOutputBlob(const std::string& blobName, std::vector<float>& output);
28+
// Get output tensor content as a vector given its name
29+
void getOutputTensor(const std::string& tensorName, std::vector<float>& output);
3030

31-
const std::map<std::string, std::vector<unsigned long>>& getInputBlobDimsInfo() const;
32-
const std::map<std::string, std::vector<unsigned long>>& getOutputBlobDimsInfo() const;
31+
const std::map<std::string, ov::Shape>& getInputTensorDimsInfo() const;
32+
const std::map<std::string, ov::Shape>& getOutputTensorDimsInfo() const;
3333

3434
std::string expectSingleInput() const;
3535
std::string expectSingleOutput() const;
3636

37-
void expectImageInput(const std::string& blobName) const;
37+
void expectImageInput(const std::string& tensorName) const;
3838

39-
void reshape(const std::map<std::string, std::vector<unsigned long>>& newBlobsDimsInfo);
39+
void reshape(const std::map<std::string, ov::Shape>& newTensorsDimsInfo);
4040

4141
void infer();
4242

4343
private:
4444
std::string modelPath;
4545
std::string modelType;
4646
std::string deviceName;
47-
InferenceEngine::Core& ie;
48-
InferenceEngine::CNNNetwork network;
49-
InferenceEngine::ExecutableNetwork executableNetwork;
50-
InferenceEngine::InferRequest request;
51-
std::map<std::string, std::vector<unsigned long>> inputBlobsDimsInfo;
52-
std::map<std::string, std::vector<unsigned long>> outputBlobsDimsInfo;
47+
ov::runtime::Core core;
48+
std::shared_ptr<ov::Model> model;
49+
ov::runtime::CompiledModel compiled_model;
50+
ov::runtime::InferRequest infer_request;
51+
std::map<std::string, ov::Shape> input_tensors_dims_info;
52+
std::map<std::string, ov::Shape> output_tensors_dims_info;
5353

5454
void setExecPart();
5555
};

0 commit comments

Comments
 (0)