279 lines
13 KiB
C++
279 lines
13 KiB
C++
#include "ANSOVFBFaceDetector.h"
|
|
#include <models/detection_model_faceboxes.h>
|
|
#include <pipelines/metadata.h>
|
|
#include <models/input_data.h>
|
|
#include <models/results.h>
|
|
#include "Utility.h"
|
|
namespace ANSCENTER {
|
|
bool ANSOVFBFD::Initialize(std::string licenseKey, ModelConfig modelConfig, const std::string& modelZipFilePath, const std::string& modelZipPassword, std::string& labelMap) {
|
|
bool result = ANSFDBase::Initialize(licenseKey, modelConfig, modelZipFilePath, modelZipPassword, labelMap);
|
|
labelMap = "Face";
|
|
// We do not need to check for the license
|
|
_licenseValid = true;
|
|
if (!_licenseValid) return false;
|
|
try {
|
|
_modelConfig = modelConfig;
|
|
_modelConfig.modelType = ModelType::FACEDETECT;
|
|
_modelConfig.detectionType = DetectionType::FACEDETECTOR;
|
|
|
|
// We need to get the modelfolder from here
|
|
std::string xmlfile = CreateFilePath(_modelFolder, "facebox.xml");
|
|
if (std::filesystem::exists(xmlfile)) {
|
|
_modelFilePath = xmlfile;
|
|
this->_logger.LogDebug("ANSOVFBFD::Initialize. Loading ansovfb weight", _modelFilePath, __FILE__, __LINE__);
|
|
}
|
|
else {
|
|
this->_logger.LogError("ANSOVFBFD::Initialize. Model ansovfb.xml file is not exist", _modelFilePath, __FILE__, __LINE__);
|
|
return false;
|
|
}
|
|
std::string landmarkModel = CreateFilePath(_modelFolder, "landmarks.xml");
|
|
if (std::filesystem::exists(landmarkModel)) {
|
|
_landmarkModelFilePath = landmarkModel;
|
|
this->_logger.LogDebug("ANSOVFBFD::Initialize. Loading landmarks weight", _landmarkModelFilePath, __FILE__, __LINE__);
|
|
ov::Core lmcore;
|
|
CnnConfig landmarks_config(_landmarkModelFilePath, "Facial Landmarks Regression");
|
|
landmarks_config.m_deviceName = "GPU";
|
|
landmarks_config.m_max_batch_size = 1;
|
|
landmarks_config.m_core = lmcore;
|
|
this->_faceLandmark = std::make_unique<VectorCNN>(landmarks_config);
|
|
if (_faceLandmark == nullptr) {
|
|
this->_logger.LogFatal("ANSOVFBFD::Initialize", "Failed to initialize face recognizer model", __FILE__, __LINE__);
|
|
}
|
|
}
|
|
else {
|
|
this->_logger.LogError("ANSOVFBFD::Initialize. Model landmarks.xml file is not exist", _landmarkModelFilePath, __FILE__, __LINE__);
|
|
}
|
|
|
|
std::vector<std::string> labels;
|
|
labels.push_back(labelMap);
|
|
std::unique_ptr<ModelBase> _faceDetector;
|
|
_faceDetector.reset(new ModelFaceBoxes(_modelFilePath,
|
|
static_cast<float>(0.5),
|
|
false,
|
|
static_cast<float>(0.5),
|
|
""));
|
|
_faceDetector->setInputsPreprocessing(false, "", "");
|
|
ov::Core core;
|
|
this->_faceDectectorPipeline = std::make_unique<AsyncPipeline>(std::move(_faceDetector), ConfigFactory::getUserConfig("GPU", 0, "", 0), core);
|
|
|
|
_isInitialized = true;
|
|
return true;
|
|
}
|
|
catch (std::exception& e) {
|
|
this->_logger.LogFatal("ANSOVFBFD::Initialize", e.what(), __FILE__, __LINE__);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool ANSOVFBFD::LoadModel(const std::string& modelZipFilePath, const std::string& modelZipPassword) {
|
|
try {
|
|
// We need to get the _modelFolder
|
|
bool result = ANSFDBase::LoadModel(modelZipFilePath, modelZipPassword);
|
|
if (!result) return false;
|
|
// We need to get the modelfolder from here
|
|
std::string xmlfile = CreateFilePath(_modelFolder, "ansovfb.xml");
|
|
if (std::filesystem::exists(xmlfile)) {
|
|
_modelFilePath = xmlfile;
|
|
this->_logger.LogDebug("ANSOVFBFD::LoadModel. Loading ansovfb weight", _modelFilePath, __FILE__, __LINE__);
|
|
}
|
|
else {
|
|
this->_logger.LogError("ANSOVFBFD::LoadModel. Model ansovfb.xml file is not exist", _modelFilePath, __FILE__, __LINE__);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
catch (std::exception& e) {
|
|
this->_logger.LogFatal("ANSOVFBFD::LoadModel", e.what(), __FILE__, __LINE__);
|
|
return false;
|
|
}
|
|
|
|
}
|
|
bool ANSOVFBFD::OptimizeModel(bool fp16, std::string& optimizedModelFolder) {
|
|
if (!FileExist(_modelFilePath)) {
|
|
optimizedModelFolder = "";
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
std::vector<Object> ANSOVFBFD::RunInference(const cv::Mat& input) {
|
|
std::vector<Object> output;
|
|
output.clear();
|
|
if (!_licenseValid) {
|
|
if (_modelLoading.load()) return {};
|
|
this->_logger.LogError("ANSOVFBFD::RunInference", "Invalid license", __FILE__, __LINE__);
|
|
return output;
|
|
}
|
|
if (!_isInitialized) {
|
|
this->_logger.LogError("ANSOVFBFD::RunInference", "Model is not initialized", __FILE__, __LINE__);
|
|
return output;
|
|
}
|
|
try {
|
|
bool croppedFace = false; // Check if the image is cropped face image
|
|
cv::Mat im = input.clone();
|
|
//std::cout << "Width x Height=" << input.size[0] << "x" << input.size[1] << std::endl;
|
|
// We know that the image sizes <=300 px, it is likely that image is cropped for face only
|
|
if ((input.size[0] <= 300) || (input.size[1] <= 300)) croppedFace = true;
|
|
if (croppedFace) cv::copyMakeBorder(input, im, 200, 200, 200, 200, cv::BORDER_REPLICATE);
|
|
|
|
;
|
|
auto startTime = std::chrono::steady_clock::now();
|
|
int64_t frameNum = _faceDectectorPipeline->submitData(ImageInputData(im), std::make_shared<ImageMetaData>(im, startTime));
|
|
_faceDectectorPipeline->waitForTotalCompletion();
|
|
std::unique_ptr<ResultBase> result = _faceDectectorPipeline->getResult();
|
|
|
|
auto outputImg = result->metaData->asRef<ImageMetaData>().img;
|
|
if (outputImg.empty()) {
|
|
throw std::invalid_argument("Renderer: image provided in metadata is empty");
|
|
}
|
|
for (auto& obj : result->asRef<DetectionResult>().objects) {
|
|
Object result;
|
|
std::vector<cv::Mat> face_rois;
|
|
std::vector<cv::Mat> landmarks;
|
|
|
|
float confidence = obj.confidence;
|
|
if (confidence >= _modelConfig.detectionScoreThreshold)
|
|
{
|
|
int x_min = obj.x;
|
|
int y_min = obj.y;
|
|
int x_max = obj.x + obj.width;
|
|
int y_max = obj.y + obj.height;
|
|
result.classId = obj.labelID;
|
|
result.className = obj.label;
|
|
result.confidence = confidence;
|
|
result.box.x = x_min;
|
|
result.box.y = y_min;
|
|
if (croppedFace) {
|
|
if (x_min <= 200) x_min = 200;
|
|
if (y_min <= 200) y_min = 200;
|
|
result.box.x = x_min - 200;
|
|
result.box.y = y_min - 200;
|
|
}
|
|
result.box.width = x_max - x_min;
|
|
result.box.height = y_max - y_min;
|
|
|
|
if (_faceLandmark != nullptr) {
|
|
landmarks.clear();
|
|
face_rois.clear();
|
|
cv::Mat face_roi = ANSUtilityHelper::GetCroppedFace(im, x_min, y_min, x_max, y_max);
|
|
face_rois.push_back(face_roi);
|
|
_faceLandmark->Compute(face_rois, &landmarks, cv::Size(2, 5));
|
|
ANSUtilityHelper::AlignFaces(&face_rois, &landmarks);
|
|
result.mask = face_rois[0];
|
|
face_roi.release();
|
|
}
|
|
else {
|
|
result.mask = ANSUtilityHelper::GetCroppedFace(im, x_min, y_min, x_max, y_max);
|
|
}
|
|
result.cameraId = "FBFaceCAM";
|
|
output.push_back(result);
|
|
}
|
|
}
|
|
im.release();
|
|
EnqueueDetection(output, "FBFaceCAM");
|
|
return output;
|
|
}
|
|
catch (std::exception& e) {
|
|
this->_logger.LogFatal("ANSOVFBFD::RunInference", e.what(), __FILE__, __LINE__);
|
|
return output;
|
|
}
|
|
}
|
|
std::vector<Object> ANSOVFBFD::RunInference(const cv::Mat& input, const std::string& camera_id) {
|
|
std::vector<Object> output;
|
|
output.clear();
|
|
if (!_licenseValid) {
|
|
if (_modelLoading.load()) return {};
|
|
this->_logger.LogError("ANSOVFBFD::RunInference", "Invalid license", __FILE__, __LINE__);
|
|
return output;
|
|
}
|
|
if (!_isInitialized) {
|
|
this->_logger.LogError("ANSOVFBFD::RunInference", "Model is not initialized", __FILE__, __LINE__);
|
|
return output;
|
|
}
|
|
try {
|
|
bool croppedFace = false; // Check if the image is cropped face image
|
|
cv::Mat im = input.clone();
|
|
//std::cout << "Width x Height=" << input.size[0] << "x" << input.size[1] << std::endl;
|
|
// We know that the image sizes <=300 px, it is likely that image is cropped for face only
|
|
if ((input.size[0] <= 300) || (input.size[1] <= 300)) croppedFace = true;
|
|
if (croppedFace) cv::copyMakeBorder(input, im, 200, 200, 200, 200, cv::BORDER_REPLICATE);
|
|
|
|
;
|
|
auto startTime = std::chrono::steady_clock::now();
|
|
int64_t frameNum = _faceDectectorPipeline->submitData(ImageInputData(im), std::make_shared<ImageMetaData>(im, startTime));
|
|
_faceDectectorPipeline->waitForTotalCompletion();
|
|
std::unique_ptr<ResultBase> result = _faceDectectorPipeline->getResult();
|
|
|
|
auto outputImg = result->metaData->asRef<ImageMetaData>().img;
|
|
if (outputImg.empty()) {
|
|
throw std::invalid_argument("Renderer: image provided in metadata is empty");
|
|
}
|
|
for (auto& obj : result->asRef<DetectionResult>().objects) {
|
|
Object result;
|
|
std::vector<cv::Mat> face_rois;
|
|
std::vector<cv::Mat> landmarks;
|
|
|
|
float confidence = obj.confidence;
|
|
if (confidence >= _modelConfig.detectionScoreThreshold)
|
|
{
|
|
int x_min = obj.x;
|
|
int y_min = obj.y;
|
|
int x_max = obj.x + obj.width;
|
|
int y_max = obj.y + obj.height;
|
|
result.classId = obj.labelID;
|
|
result.className = obj.label;
|
|
result.confidence = confidence;
|
|
result.box.x = x_min;
|
|
result.box.y = y_min;
|
|
if (croppedFace) {
|
|
if (x_min <= 200) x_min = 200;
|
|
if (y_min <= 200) y_min = 200;
|
|
result.box.x = x_min - 200;
|
|
result.box.y = y_min - 200;
|
|
}
|
|
result.box.width = x_max - x_min;
|
|
result.box.height = y_max - y_min;
|
|
|
|
if (_faceLandmark != nullptr) {
|
|
landmarks.clear();
|
|
face_rois.clear();
|
|
cv::Mat face_roi = ANSUtilityHelper::GetCroppedFace(im, x_min, y_min, x_max, y_max);
|
|
face_rois.push_back(face_roi);
|
|
_faceLandmark->Compute(face_rois, &landmarks, cv::Size(2, 5));
|
|
ANSUtilityHelper::AlignFaces(&face_rois, &landmarks);
|
|
result.mask = face_rois[0];
|
|
face_roi.release();
|
|
}
|
|
else {
|
|
result.mask = ANSUtilityHelper::GetCroppedFace(im, x_min, y_min, x_max, y_max);
|
|
}
|
|
result.cameraId = camera_id;
|
|
output.push_back(result);
|
|
}
|
|
}
|
|
im.release();
|
|
EnqueueDetection(output, camera_id);
|
|
return output;
|
|
}
|
|
catch (std::exception& e) {
|
|
this->_logger.LogFatal("ANSOVFBFD::RunInference", e.what(), __FILE__, __LINE__);
|
|
return output;
|
|
}
|
|
}
|
|
|
|
ANSOVFBFD::~ANSOVFBFD() {
|
|
try {
|
|
}
|
|
catch (std::exception& e) {
|
|
this->_logger.LogFatal("ANSOVFBFD::Destroy", e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
bool ANSOVFBFD::Destroy() {
|
|
try {
|
|
return true;
|
|
}
|
|
catch (std::exception& e) {
|
|
this->_logger.LogFatal("ANSOVFBFD::Destroy", e.what(), __FILE__, __LINE__);
|
|
return false;
|
|
}
|
|
}
|
|
} |