Skip to content

Commit e8c9717

Browse files
add facial-landmarks-98-detection model to gaze_estimation_demo (#2981)
* add 98 model to gaze_estimation_demo * delete mistakes * comment new model * solved bias * solve mistakes * style and fix crash when no eyes or only one eye visible/open Co-authored-by: Vladimir Dudnik <[email protected]>
1 parent 33ef3e6 commit e8c9717

16 files changed

+253
-108
lines changed

demos/gaze_estimation_demo/cpp/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The demo also relies on the following auxiliary networks:
88

99
* `face-detection-retail-0004` or `face-detection-adas-0001` detection networks for finding faces
1010
* `head-pose-estimation-adas-0001`, which estimates head pose in Tait-Bryan angles, serving as an input for gaze estimation model
11-
* `facial-landmarks-35-adas-0002`, which estimates coordinates of facial landmarks for detected faces. The keypoints at the corners of eyes are used to locate eyes regions required for the gaze estimation model
11+
* `facial-landmarks-35-adas-0002` or `facial-landmarks-98-detection-0001`, which estimates coordinates of facial landmarks for detected faces. The keypoints at the corners of eyes are used to locate eyes regions required for the gaze estimation model
1212
* `open-closed-eye-0001`, which estimates eyes state of detected faces.
1313

1414
Other demo objectives are:
@@ -47,6 +47,7 @@ omz_converter --list models.lst
4747
### Supported Models
4848

4949
* facial-landmarks-35-adas-0002
50+
* facial-landmarks-98-detection-0001
5051
* face-detection-adas-0001
5152
* face-detection-retail-0004
5253
* face-detection-retail-0005

demos/gaze_estimation_demo/cpp/gaze_estimation_demo.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77

88
#include <string>
99
#include <vector>
10-
#include <gflags/gflags.h>
1110
#include <iostream>
1211

13-
#include <utils/default_flags.hpp>
12+
#include "gflags/gflags.h"
13+
#include "utils/default_flags.hpp"
1414

1515
DEFINE_INPUT_FLAGS
1616
DEFINE_OUTPUT_FLAGS

demos/gaze_estimation_demo/cpp/include/face_inference_results.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
#include <vector>
88
#include <opencv2/core/core.hpp>
9-
#include <utils/slog.hpp>
9+
#include "utils/slog.hpp"
1010

1111
namespace gaze_estimation {
1212
struct FaceInferenceResults {
@@ -25,6 +25,8 @@ struct FaceInferenceResults {
2525

2626
cv::Point3f gazeVector;
2727

28+
std::vector<cv::Point2f> getEyeLandmarks();
29+
2830
friend slog::LogStream& operator<<(slog::LogStream& os, const FaceInferenceResults& faceInferenceResults);
2931
};
3032

demos/gaze_estimation_demo/cpp/include/ie_wrapper.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66

77
#include <cstdio>
88
#include <string>
9-
109
#include <map>
1110
#include <vector>
1211

13-
#include <utils/common.hpp>
14-
#include <utils/ocv_common.hpp>
15-
#include <utils/slog.hpp>
12+
#include "utils/common.hpp"
13+
#include "utils/ocv_common.hpp"
14+
#include "utils/slog.hpp"
1615

1716
namespace gaze_estimation {
1817
class IEWrapper {

demos/gaze_estimation_demo/cpp/include/landmarks_estimator.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,15 @@ class LandmarksEstimator: public BaseEstimator {
2727
private:
2828
IEWrapper ieWrapper;
2929
std::string inputBlobName, outputBlobName;
30+
size_t numberLandmarks;
31+
std::vector<cv::Point2i> simplePostprocess(cv::Rect faceBoundingBox, cv::Mat faceCrop);
32+
std::vector<cv::Point2i> heatMapPostprocess(cv::Rect faceBoundingBox, cv::Mat faceCrop);
33+
std::vector<cv::Mat> split(std::vector<float>& data, const std::vector<unsigned long>& shape);
34+
std::vector<cv::Point2f> getMaxPreds(std::vector<cv::Mat> heatMaps);
35+
int sign(float number);
36+
cv::Mat affineTransform(cv::Point2f center, cv::Point2f scale,
37+
float rot, size_t dst_w, size_t dst_h, cv::Point2f shift, bool inv);
38+
cv::Point2f rotatePoint(cv::Point2f pt, float angle_rad);
39+
cv::Point2f get3rdPoint(cv::Point2f a, cv::Point2f b);
3040
};
3141
} // namespace gaze_estimation

demos/gaze_estimation_demo/cpp/include/utils.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@
66

77
#include <cstdio>
88
#include <string>
9-
109
#include <utility>
1110
#include <map>
1211
#include <vector>
1312

1413
#include <inference_engine.hpp>
1514

16-
#include <utils/ocv_common.hpp>
17-
#include <utils/slog.hpp>
15+
#include "utils/ocv_common.hpp"
16+
#include "utils/slog.hpp"
1817

1918
namespace gaze_estimation {
2019
void gazeVectorToGazeAngles(const cv::Point3f& gazeVector, cv::Point2f& gazeAngles);

demos/gaze_estimation_demo/cpp/main.cpp

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

@@ -7,7 +7,6 @@
77
* \file gaze_estimation_demo/main.cpp
88
* \example gaze_estimation_demo/main.cpp
99
*/
10-
#include <gflags/gflags.h>
1110
#include <functional>
1211
#include <iostream>
1312
#include <fstream>
@@ -27,33 +26,30 @@
2726

2827
#include <inference_engine.hpp>
2928

29+
#include <gflags/gflags.h>
3030
#include <monitors/presenter.h>
3131
#include <utils/args_helper.hpp>
3232
#include <utils/images_capture.h>
3333
#include <utils/ocv_common.hpp>
3434
#include <utils/performance_metrics.hpp>
3535
#include <utils/slog.hpp>
3636

37-
#include "gaze_estimation_demo.hpp"
38-
3937
#include "face_inference_results.hpp"
40-
4138
#include "face_detector.hpp"
42-
4339
#include "base_estimator.hpp"
4440
#include "head_pose_estimator.hpp"
4541
#include "landmarks_estimator.hpp"
4642
#include "eye_state_estimator.hpp"
4743
#include "gaze_estimator.hpp"
48-
4944
#include "results_marker.hpp"
50-
5145
#include "utils.hpp"
5246

47+
#include "gaze_estimation_demo.hpp"
48+
5349
using namespace gaze_estimation;
5450

55-
bool ParseAndCheckCommandLine(int argc, char *argv[]) {
56-
// ---------------------------Parsing and validating input arguments--------------------------------------
51+
bool ParseAndCheckCommandLine(int argc, char* argv[]) {
52+
// Parsing and validating input arguments
5753
gflags::ParseCommandLineNonHelpFlags(&argc, &argv, true);
5854
if (FLAGS_h) {
5955
showUsage();
@@ -78,11 +74,11 @@ bool ParseAndCheckCommandLine(int argc, char *argv[]) {
7874
}
7975

8076

81-
int main(int argc, char *argv[]) {
77+
int main(int argc, char* argv[]) {
8278
try {
8379
PerformanceMetrics metrics;
8480

85-
// ------------------------------ Parsing and validating of input arguments --------------------------
81+
// Parsing and validating of input arguments
8682
if (!ParseAndCheckCommandLine(argc, argv)) {
8783
return 0;
8884
}
@@ -108,8 +104,8 @@ int main(int argc, char *argv[]) {
108104
int delay = 1;
109105
std::string windowName = "Gaze estimation demo";
110106

111-
std::unique_ptr<ImagesCapture> cap = openImagesCapture(FLAGS_i, FLAGS_loop, 0,
112-
std::numeric_limits<size_t>::max(), stringToSize(FLAGS_res));
107+
std::unique_ptr<ImagesCapture> cap = openImagesCapture(
108+
FLAGS_i, FLAGS_loop, 0, std::numeric_limits<size_t>::max(), stringToSize(FLAGS_res));
113109

114110
auto startTime = std::chrono::steady_clock::now();
115111
cv::Mat frame = cap->read();
@@ -118,8 +114,9 @@ int main(int argc, char *argv[]) {
118114
}
119115

120116
cv::VideoWriter videoWriter;
121-
if (!FLAGS_o.empty() && !videoWriter.open(FLAGS_o, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'),
122-
cap->fps(), frame.size())) {
117+
if (!FLAGS_o.empty() &&
118+
!videoWriter.open(FLAGS_o, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), cap->fps(), frame.size()))
119+
{
123120
throw std::runtime_error("Can't open video writer");
124121
}
125122
uint32_t framesProcessed = 0;

demos/gaze_estimation_demo/cpp/models.lst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# This file can be used with the --list option of the model downloader.
2+
#facial-landmarks-98-detection-????
23
facial-landmarks-35-adas-????
34
face-detection-adas-????
45
face-detection-retail-????

demos/gaze_estimation_demo/cpp/src/eye_state_estimator.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,17 @@
99

1010
namespace gaze_estimation {
1111

12-
EyeStateEstimator::EyeStateEstimator(InferenceEngine::Core& ie,
13-
const std::string& modelPath,
14-
const std::string& deviceName):
15-
ieWrapper(ie, modelPath, modelType, deviceName) {
12+
EyeStateEstimator::EyeStateEstimator(
13+
InferenceEngine::Core& ie, const std::string& modelPath, const std::string& deviceName) :
14+
ieWrapper(ie, modelPath, modelType, deviceName)
15+
{
1616
inputBlobName = ieWrapper.expectSingleInput();
1717
ieWrapper.expectImageInput(inputBlobName);
1818
outputBlobName = ieWrapper.expectSingleOutput();
1919
}
2020

21-
cv::Rect EyeStateEstimator::createEyeBoundingBox(const cv::Point2i& p1,
22-
const cv::Point2i& p2,
23-
float scale) const {
21+
cv::Rect EyeStateEstimator::createEyeBoundingBox(
22+
const cv::Point2i& p1, const cv::Point2i& p2, float scale) const {
2423
cv::Rect result;
2524
float size = static_cast<float>(cv::norm(p1 - p2));
2625

@@ -35,9 +34,8 @@ cv::Rect EyeStateEstimator::createEyeBoundingBox(const cv::Point2i& p1,
3534
return result;
3635
}
3736

38-
void EyeStateEstimator::rotateImageAroundCenter(const cv::Mat& srcImage,
39-
cv::Mat& dstImage,
40-
float angle) const {
37+
void EyeStateEstimator::rotateImageAroundCenter(
38+
const cv::Mat& srcImage, cv::Mat& dstImage, float angle) const {
4139
auto w = srcImage.cols;
4240
auto h = srcImage.rows;
4341

@@ -49,11 +47,13 @@ void EyeStateEstimator::rotateImageAroundCenter(const cv::Mat& srcImage,
4947
cv::warpAffine(srcImage, dstImage, rotMatrix, size, 1, cv::BORDER_REPLICATE);
5048
}
5149

52-
void EyeStateEstimator::estimate(const cv::Mat& image, FaceInferenceResults& outputResults) {
50+
void EyeStateEstimator::estimate(
51+
const cv::Mat& image, FaceInferenceResults& outputResults) {
5352
auto roll = outputResults.headPoseAngles.z;
53+
std::vector<cv::Point2f> eyeLandmarks = outputResults.getEyeLandmarks();
5454

55-
outputResults.leftEyeMidpoint = (outputResults.faceLandmarks[0] + outputResults.faceLandmarks[1]) / 2;
56-
auto leftEyeBoundingBox = createEyeBoundingBox(outputResults.faceLandmarks[0], outputResults.faceLandmarks[1]);
55+
outputResults.leftEyeMidpoint = (eyeLandmarks[0] + eyeLandmarks[1]) / 2;
56+
auto leftEyeBoundingBox = createEyeBoundingBox(eyeLandmarks[0], eyeLandmarks[1]);
5757
outputResults.leftEyeBoundingBox = leftEyeBoundingBox;
5858
if (leftEyeBoundingBox.area()) {
5959
auto leftEyeImage(cv::Mat(image, leftEyeBoundingBox));
@@ -70,8 +70,8 @@ void EyeStateEstimator::estimate(const cv::Mat& image, FaceInferenceResults& out
7070
outputResults.leftEyeState = false;
7171
}
7272

73-
outputResults.rightEyeMidpoint = (outputResults.faceLandmarks[2] + outputResults.faceLandmarks[3]) / 2;
74-
auto rightEyeBoundingBox = createEyeBoundingBox(outputResults.faceLandmarks[2], outputResults.faceLandmarks[3]);
73+
outputResults.rightEyeMidpoint = (eyeLandmarks[2] + eyeLandmarks[3]) / 2;
74+
auto rightEyeBoundingBox = createEyeBoundingBox(eyeLandmarks[2], eyeLandmarks[3]);
7575
outputResults.rightEyeBoundingBox = rightEyeBoundingBox;
7676
if (rightEyeBoundingBox.area()) {
7777
auto rightEyeImage(cv::Mat(image, rightEyeBoundingBox));

demos/gaze_estimation_demo/cpp/src/face_detector.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,20 @@
44

55
#include <cstdio>
66
#include <string>
7-
87
#include <vector>
98
#include <map>
109

1110
#include "face_detector.hpp"
1211

1312
namespace gaze_estimation {
14-
FaceDetector::FaceDetector(InferenceEngine::Core& ie,
15-
const std::string& modelPath,
16-
const std::string& deviceName,
17-
double detectionConfidenceThreshold,
18-
bool enableReshape):
19-
ieWrapper(ie, modelPath, modelType, deviceName),
20-
detectionThreshold(detectionConfidenceThreshold),
21-
enableReshape(enableReshape) {
13+
14+
FaceDetector::FaceDetector(
15+
InferenceEngine::Core& ie, const std::string& modelPath, const std::string& deviceName,
16+
double detectionConfidenceThreshold, bool enableReshape) :
17+
ieWrapper(ie, modelPath, modelType, deviceName),
18+
detectionThreshold(detectionConfidenceThreshold),
19+
enableReshape(enableReshape)
20+
{
2221
const auto& inputInfo = ieWrapper.getInputBlobDimsInfo();
2322

2423
inputBlobName = ieWrapper.expectSingleInput();

0 commit comments

Comments
 (0)