public:
MvInferenceFaceService(std::vector<inference::TaskType> &tasks);
virtual ~MvInferenceFaceService() {};
- void configure() override;
+ void configure(const std::vector<int> &landmarkIndices) override;
void prepare() override;
void invoke(BaseDataType &input) override;
FaceResult &result() override;
}
}
-void MvInferenceFaceService::configure()
+void MvInferenceFaceService::configure(const vector<int> &landmarkIndices)
{
}
};
}
}
-#endif
\ No newline at end of file
+#endif
\ No newline at end of file
public:
PrivateInferenceFaceService(std::vector<inference::TaskType> &tasks);
virtual ~PrivateInferenceFaceService();
- void configure() override;
+ void configure(const std::vector<int> &landmarkIndices) override;
void prepare() override;
void invoke(BaseDataType &input) override;
FaceResult &result() override;
ret = mv_facial_landmark_prepare(_handle);
if (ret != MEDIA_VISION_ERROR_NONE)
throw runtime_error("Fail to prepare face landmark detection.");
-
- _landmarkMappingIndex.resize(13);
- // nose ridge
- _landmarkMappingIndex[0] = 27;
- _landmarkMappingIndex[1] = 28;
- _landmarkMappingIndex[2] = 29;
- _landmarkMappingIndex[3] = 30;
-
- // nose base
- _landmarkMappingIndex[4] = 31;
- _landmarkMappingIndex[5] = 32;
- _landmarkMappingIndex[6] = 33;
- _landmarkMappingIndex[7] = 34;
- _landmarkMappingIndex[8] = 35;
-
- // left eye
- _landmarkMappingIndex[9] = 36;
- _landmarkMappingIndex[10] = 39;
-
- // right eye
- _landmarkMappingIndex[11] = 42;
- _landmarkMappingIndex[12] = 45;
-
- _filterLandmarks.resize(13);
- for (auto &filt : _filterLandmarks)
- filt = make_unique<Kalman2D>();
}
break;
default:
}
}
-void PrivateInferenceFaceService::configure()
+void PrivateInferenceFaceService::configure(const vector<int> &landmarkIndices)
{
-
+ if (!landmarkIndices.empty() && isLandmarkDetectTask) {
+ for (auto &idx : landmarkIndices) {
+ _landmarkMappingIndex.push_back(idx);
+ _filterLandmarks.push_back(make_unique<Kalman2D>());
+ }
+ }
}
void PrivateInferenceFaceService::prepare()
--- /dev/null
+/**
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+#ifndef __FACE_SHAPE_COMPONENTS_H__
+#define __FACE_SHAPE_COMPONENTS_H__
+
+namespace singleo
+{
+namespace inference
+{
+enum class FACE_COMPONENTS {
+ NOSE_RIDGE,
+ NOSE_BASE,
+ LEFT_EYE_CORNERS,
+ RIGHT_EYE_CORNERS,
+};
+} // inference
+} // singleo
+
+#endif
\ No newline at end of file
#include "FaceResult.h"
#include "SingleoInferenceTypes.h"
+#include "FaceShapeComponents.h"
namespace singleo
{
public:
virtual ~IInferenceFaceService() {};
- virtual void configure() = 0;
+ virtual void configure(const std::vector<int> &landmarkIndices) = 0;
virtual void prepare() = 0;
virtual void invoke(BaseDataType &input) = 0;
virtual FaceResult &result() = 0;
#include <memory>
#include <vector>
-#include <PoseVector.h>
-
+#include <map>
+#include "PoseVector.h"
+#include "FaceShapeComponents.h"
namespace singleo
{
namespace services
void loadModelFromFile(const std::string &model_path);
template <typename T>
T ToNumber(const std::string &text);
+ std::map<singleo::inference::FACE_COMPONENTS, std::vector<int>> _faceShapeIndices;
public:
FaceShapeModelManager(const std::string &model_path);
~FaceShapeModelManager();
const std::vector<Point3f> &getFaceShape();
+ const std::vector<int>& getFaceShapeIndices(singleo::inference::FACE_COMPONENTS component);
};
} // smartpointer
} // services
std::unique_ptr<HeadPoseEstimator> _head_pose_estimator;
std::vector<inference::TaskType> _tasks { inference::TaskType::FACE_DETECTION, inference::TaskType::FACE_LANDMARK_DETECTION };
+ const std::vector<singleo::inference::FACE_COMPONENTS> _faceComponents { singleo::inference::FACE_COMPONENTS::NOSE_RIDGE,
+ singleo::inference::FACE_COMPONENTS::NOSE_BASE,
+ singleo::inference::FACE_COMPONENTS::LEFT_EYE_CORNERS,
+ singleo::inference::FACE_COMPONENTS::RIGHT_EYE_CORNERS };
PoseVector _headPose;
public:
explicit GazeEstimator(input::InputConfigBase &config);
#include <opencv2/calib3d.hpp>
#include "PoseVector.h"
#include "SingleoCommonTypes.h"
+#include "FaceShapeComponents.h"
namespace singleo
{
private:
std::vector<cv::Point2f> _landmarks_2d;
std::vector<cv::Point3f> _landmarks_3d;
+ std::vector<int> _faceComponentIndices;
cv::Mat _camera_matrix;
cv::Mat _camera_dist_coeff;
std::vector<cv::Point3f> _pose_axes_3d;
std::vector<singleo::services::smartpointer::Point2f> _pose_axes;
- bool _isInit;
-
public:
- HeadPoseEstimator();
+ HeadPoseEstimator(const std::vector<singleo::inference::FACE_COMPONENTS> &components);
~HeadPoseEstimator();
PoseVector estimate(const std::vector<singleo::Point> &landmark2d);
std::vector<singleo::services::smartpointer::Point2f> &getPoseAxes();
+ std::vector<int> &getFaceComponentsIndieces();
};
} // smartpointer
} // services
#include "SingleoLog.h"
using namespace std;
+using namespace singleo::inference;
namespace singleo
{
throw std::invalid_argument("Invalid face shape model path");
loadModelFromFile(model_path);
+ _faceShapeIndices.insert(make_pair<FACE_COMPONENTS, vector<int>>(FACE_COMPONENTS::NOSE_RIDGE, vector<int>{27, 28, 29, 30}));
+ _faceShapeIndices.insert(make_pair<FACE_COMPONENTS, vector<int>>(FACE_COMPONENTS::NOSE_BASE, vector<int>{31, 32, 33, 34, 35}));
+ _faceShapeIndices.insert(make_pair<FACE_COMPONENTS, vector<int>>(FACE_COMPONENTS::LEFT_EYE_CORNERS, vector<int>{36, 39}));
+ _faceShapeIndices.insert(make_pair<FACE_COMPONENTS, vector<int>>(FACE_COMPONENTS::RIGHT_EYE_CORNERS, vector<int>{42, 45}));
}
FaceShapeModelManager::~FaceShapeModelManager()
return _faceShape;
}
+const vector<int> &FaceShapeModelManager::getFaceShapeIndices(FACE_COMPONENTS component)
+{
+ auto indices = _faceShapeIndices.find(component);
+ return indices->second;
+}
+
template float FaceShapeModelManager::ToNumber(const string &text);
} // smartpointer
} // services
{
GazeEstimator::GazeEstimator(InputConfigBase& config)
{
+ _head_pose_estimator = make_unique<HeadPoseEstimator>(_faceComponents);
+ _headPose.reset();
+
+
// MvInferenceServiceFactory factory;
PrivateInferenceServiceFactory factory;
_face_estimator = factory.createInferenceFaceService(_tasks);
- _face_estimator->configure();
+ _face_estimator->configure(_head_pose_estimator->getFaceComponentsIndieces());
_face_estimator->prepare();
- _head_pose_estimator = make_unique<HeadPoseEstimator>();
- _headPose.reset();
+
}
GazeEstimator::~GazeEstimator()
using namespace std;
using namespace cv;
+using namespace singleo::inference;
namespace singleo
{
{
namespace smartpointer
{
-HeadPoseEstimator::HeadPoseEstimator()
+HeadPoseEstimator::HeadPoseEstimator(const vector<FACE_COMPONENTS> &components)
{
FaceShapeModelManager faceShapeModelmgr("/usr/share/singleo/pdm.txt");
const vector<Point3f> faceShape = faceShapeModelmgr.getFaceShape();
- // for (auto &point : faceShape)
- // _landmarks_3d.push_back(cv::Point3f(point.x, point.y, point.z));
- vector<int> landmarkMappingIndex = {27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 39, 42, 45};
- for (auto &idx : landmarkMappingIndex) {
- _landmarks_3d.push_back(cv::Point3f(faceShape[idx].x, faceShape[idx].y, faceShape[idx].z));
+ // std::vector
+ for (auto &component : components){
+ for (auto &index : faceShapeModelmgr.getFaceShapeIndices(component))
+ {
+ _landmarks_3d.push_back(cv::Point3f(faceShape[index].x, faceShape[index].y, faceShape[index].z));
+ _faceComponentIndices.push_back(index);
+ }
}
- // 2nd landmark is the nose's tip
- _pose_axes_3d.push_back(_landmarks_3d[6]);
- _pose_axes_3d.push_back(cv::Point3f(_landmarks_3d[6].x - 50, _landmarks_3d[6].y, _landmarks_3d[6].z));
- _pose_axes_3d.push_back(cv::Point3f(_landmarks_3d[6].x, _landmarks_3d[6].y - 50, _landmarks_3d[6].z));
- _pose_axes_3d.push_back(cv::Point3f(_landmarks_3d[6].x, _landmarks_3d[6].y, _landmarks_3d[6].z -50));
+ // Nose base landmarks are 31, 32, 33, 34, 35 and 33 is the nose tip
+ int noseTipIndex = faceShapeModelmgr.getFaceShapeIndices(FACE_COMPONENTS::NOSE_BASE)[2];
+ _pose_axes_3d.push_back(cv::Point3f(faceShape[noseTipIndex].x, faceShape[noseTipIndex].y, faceShape[noseTipIndex].z));
+ _pose_axes_3d.push_back(cv::Point3f(faceShape[noseTipIndex].x - 50, faceShape[noseTipIndex].y, faceShape[noseTipIndex].z));
+ _pose_axes_3d.push_back(cv::Point3f(faceShape[noseTipIndex].x, faceShape[noseTipIndex].y - 50, faceShape[noseTipIndex].z));
+ _pose_axes_3d.push_back(cv::Point3f(faceShape[noseTipIndex].x, faceShape[noseTipIndex].y, faceShape[noseTipIndex].z -50));
_pose_axes.resize(_pose_axes_3d.size());
_landmarks_2d.resize(_landmarks_3d.size());
SINGLEO_LOGI("%.3f", _camera_dist_coeff.at<float>(r, c));
}
}
-
- _isInit = false;
}
HeadPoseEstimator::~HeadPoseEstimator()
}
SINGLEO_LOGI("Get 2d landmark takes %d ms", timer.check_ms());
- if (true/*!_isInit*/) {
- timer.reset();
- // init
- cv::solvePnPRansac(_landmarks_3d, _landmarks_2d,
- _camera_matrix, _camera_dist_coeff,
- _rotation_vector, _translation_vector, false, 100, 8.0F, 0.99, cv::noArray(), cv::SOLVEPNP_EPNP);
- SINGLEO_LOGI("1st solvePnP takes %d ms", timer.check_ms());
- _isInit = true;
- }
+ timer.reset();
+ cv::solvePnPRansac(_landmarks_3d, _landmarks_2d,
+ _camera_matrix, _camera_dist_coeff,
+ _rotation_vector, _translation_vector, false, 100, 8.0F, 0.99, cv::noArray(), cv::SOLVEPNP_EPNP);
+ SINGLEO_LOGI("1st solvePnP takes %d ms", timer.check_ms());
timer.reset();
// estimate pose
return _pose_axes;
}
+std::vector<int> &HeadPoseEstimator::getFaceComponentsIndieces()
+{
+ return _faceComponentIndices;
+}
+
} // smartpointer
} // services
} // singleo