Files
ANSCORE/ANSODEngine/ANSOVFBFaceDetector.cpp

277 lines
12 KiB
C++
Raw Normal View History

2026-03-28 16:54:11 +11:00
#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) {
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) {
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;
}
}
}