356 lines
9.4 KiB
C++
356 lines
9.4 KiB
C++
#include "Inc/DeepCamFaceApi.h"
|
|
#include "Inc/CenterFaceMnn.h"
|
|
#include "Inc/MobileFaceFeatureMnn.h"
|
|
#include "Inc/LivenessRGB.h"
|
|
#include "Inc/LivenessIRMnn.h"
|
|
#include "Inc/FaceQuality.h"
|
|
#include "Inc/Landmark68.h"
|
|
#include "Inc/FaceDbMgr.h"
|
|
|
|
class FaceCache {
|
|
public:
|
|
static FaceCache* GetInstance();
|
|
int GetFaceRect(int index, float* face_rect);
|
|
int GetFaceLandmark(int index, float* landmark);
|
|
void LoadFaceInfo(cv::Mat& frame, std::vector<FaceInfo>& face_infos);
|
|
void ResetFaceInfo();
|
|
cv::Mat GetFrame();
|
|
private:
|
|
FaceCache() {};
|
|
|
|
private:
|
|
static FaceCache* m_instance;
|
|
std::mutex m_mt;
|
|
std::vector<FaceInfo> m_face_infos;
|
|
cv::Mat m_frame;
|
|
};
|
|
|
|
FaceCache* FaceCache::m_instance = nullptr;
|
|
|
|
FaceCache* FaceCache::GetInstance()
|
|
{
|
|
if (m_instance == nullptr)
|
|
{
|
|
m_instance = new FaceCache;
|
|
}
|
|
return m_instance;
|
|
}
|
|
|
|
void FaceCache::LoadFaceInfo(cv::Mat& frame, std::vector<FaceInfo>& face_infos)
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_mt);
|
|
m_face_infos.clear();
|
|
|
|
for (auto& obj : face_infos)
|
|
{
|
|
m_face_infos.push_back(std::move(obj));
|
|
//m_face_info.x1 = obj.x1;
|
|
//m_face_info.x2 = obj.x1;
|
|
//m_face_info.y1 = obj.y1;
|
|
//m_face_info.y2 = obj.y2;
|
|
//m_face_info.score = 0.f;
|
|
//memcpy(m_face_info.landmarks, face_info.landmarks, 10 * sizeof(float));
|
|
}
|
|
m_frame = frame.clone();
|
|
}
|
|
|
|
void FaceCache::ResetFaceInfo()
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_mt);
|
|
m_face_infos.clear();
|
|
m_frame = cv::Mat().clone();
|
|
}
|
|
|
|
int FaceCache::GetFaceRect(int index, float* face_rect)
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_mt);
|
|
if (index < m_face_infos.size())
|
|
{
|
|
face_rect[0] = m_face_infos[index].x1;
|
|
face_rect[1] = m_face_infos[index].y1;
|
|
face_rect[2] = m_face_infos[index].x2;
|
|
face_rect[3] = m_face_infos[index].y2;
|
|
return ERR_OK;
|
|
}
|
|
else
|
|
{
|
|
memset(face_rect, 0.f, 4 * sizeof(float));
|
|
return ERR_INDEX_INVALID;
|
|
}
|
|
|
|
}
|
|
|
|
int FaceCache::GetFaceLandmark(int index, float* landmark)
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_mt);
|
|
if (index < m_face_infos.size())
|
|
{
|
|
memcpy(landmark, m_face_infos[index].landmarks, 10 * sizeof(float));
|
|
return ERR_OK;
|
|
}
|
|
else
|
|
{
|
|
return ERR_INDEX_INVALID;
|
|
}
|
|
}
|
|
|
|
cv::Mat FaceCache::GetFrame()
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_mt);
|
|
return m_frame;
|
|
}
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamFaceDetect(IN const cv::Mat& frame, OUT std::vector<FaceInfo>& faceList)
|
|
{
|
|
if (frame.empty())
|
|
{
|
|
return ERR_IMG;
|
|
}
|
|
return CenterFaceMnn::GetInstance()->Detect(frame, faceList);
|
|
}
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamGetFaceFeature(IN const cv::Mat& frame, IN const float* landmarks, OUT float* feature)
|
|
{
|
|
if (frame.empty())
|
|
{
|
|
return ERR_IMG;
|
|
}
|
|
if (landmarks == nullptr)
|
|
{
|
|
return ERR_LANDMARK;
|
|
}
|
|
return MobileFaceFeatureMnn::GetInstance()->GetFaceFeature(frame, landmarks, feature);
|
|
}
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamFaceFeatureCompare(IN const float* feature1, IN const float* feature2, OUT float & fSimilarity)
|
|
{
|
|
fSimilarity = 0.f;
|
|
|
|
if (feature1 == nullptr || feature2 == nullptr)
|
|
{
|
|
return ERR_FEATURE;
|
|
}
|
|
|
|
float tmp0 = 0, tmp1 = 0, tmp2 = 0;
|
|
for (int i = 0; i < 512; i++)
|
|
{
|
|
tmp0 += feature1[i] * feature2[i];
|
|
tmp1 += feature1[i] * feature1[i];
|
|
tmp2 += feature2[i] * feature2[i];
|
|
}
|
|
|
|
float score = (float(tmp0 / (sqrt(tmp1)* sqrt(tmp2))));
|
|
|
|
//拉高分数
|
|
float max_score = log10f(1.01);
|
|
float min_score = log10f(0.02);
|
|
float ret, temp;
|
|
if (score <= 0)
|
|
{
|
|
temp = fabs(score);
|
|
if (temp > 0.3)
|
|
{
|
|
ret = 0.0001;
|
|
}
|
|
else
|
|
{
|
|
ret = temp;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
temp = log10f(score + 0.01);
|
|
fSimilarity = fabsf(temp - min_score) / (max_score - min_score);
|
|
}
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamFaceLivenessRgb(IN const cv::Mat& frame, IN const float* landmarks, OUT float& livenessScore)
|
|
{
|
|
if (frame.empty())
|
|
{
|
|
return ERR_IMG;
|
|
}
|
|
if (landmarks == nullptr)
|
|
{
|
|
return ERR_LANDMARK;
|
|
}
|
|
livenessScore = LivenessRGB::GetInstance()->LivenessDetect(frame, landmarks);
|
|
return ERR_OK;
|
|
}
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamFaceLivenesIr(IN const cv::Mat& frame, IN float face_x1, IN float face_y1, IN float face_x2, IN float face_y2, IN const float* landmarks, OUT float& livenessScore)
|
|
{
|
|
livenessScore = 0.f;
|
|
if (frame.empty())
|
|
{
|
|
return ERR_IMG;
|
|
}
|
|
if (landmarks == nullptr)
|
|
{
|
|
return ERR_LANDMARK;
|
|
}
|
|
return LivenessIRMnn::GetInstance()->LivenessDetect(frame, face_x1, face_y1, face_x2, face_y2, landmarks, livenessScore, true);
|
|
}
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamGetFaceQuality(IN const cv::Mat& frame, IN float face_x1, IN float face_y1, IN float face_x2, IN float face_y2, OUT float& score)
|
|
{
|
|
if (frame.empty())
|
|
{
|
|
return ERR_IMG;
|
|
}
|
|
score = FaceQuality::GetInstance()->DetectQuality(frame, cv::Rect(face_x1, face_y1, face_x2 - face_x1, face_y2 - face_y1));
|
|
return ERR_OK;
|
|
}
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamGetFaceLandmarks68(IN const cv::Mat& frame, IN float face_x1, IN float face_y1, IN float face_x2, IN float face_y2, OUT float* landmark68)
|
|
{
|
|
std::vector<float> pose;
|
|
std::vector<float> landmark;
|
|
int ret = Landmark68::GetInstance()->Detect(frame, face_x1, face_y1, face_x2, face_y2, pose, landmark);
|
|
if (ret != ERR_OK || landmark.size() != 136)
|
|
{
|
|
memset(landmark68, 0, 136 * sizeof(float));
|
|
return ret;
|
|
}
|
|
memcpy(landmark68, landmark.data(), sizeof(float) * 136);
|
|
return ERR_OK;
|
|
}
|
|
|
|
|
|
/**********************************人脸通用接口************************************/
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamFaceDetectStd(IN unsigned char * data, IN int width, IN int height, IN int pixelType)
|
|
{
|
|
if (data == NULL || width < 1 || height < 1 || (pixelType != PIXEL_BGR &&pixelType != PIXEL_RGB))
|
|
{
|
|
return ERR_IMG;
|
|
}
|
|
|
|
cv::Mat tempMat(height, width, CV_8UC(3), (void *)data);
|
|
if (tempMat.empty() || !tempMat.data)
|
|
{
|
|
return ERR_IMG;
|
|
}
|
|
|
|
std::vector<FaceInfo> face_infos;
|
|
int ret = DeepCamFaceDetect(tempMat, face_infos);
|
|
if (face_infos.size() > 0)
|
|
{
|
|
FaceCache::GetInstance()->LoadFaceInfo(tempMat, face_infos);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamGetFaceRectStd(IN int index, OUT float* face_rect)
|
|
{
|
|
return FaceCache::GetInstance()->GetFaceRect(index, face_rect);
|
|
}
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamGetFaceLandmarkStd(IN int index, OUT float* landmark)
|
|
{
|
|
return FaceCache::GetInstance()->GetFaceLandmark(index, landmark);
|
|
}
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamGetFaceQualityStd(IN int index, OUT float& score)
|
|
{
|
|
float face_rect[4] = { 0.f };
|
|
int ret = FaceCache::GetInstance()->GetFaceRect(index, face_rect);
|
|
if (ret != ERR_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
return DeepCamGetFaceQuality(FaceCache::GetInstance()->GetFrame(), face_rect[0], face_rect[1], face_rect[2], face_rect[3], score);
|
|
}
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamGetFaceFeatureStd(IN int index, OUT float* feature)
|
|
{
|
|
float landmark[10] = { 0 };
|
|
int ret = FaceCache::GetInstance()->GetFaceLandmark(index, landmark);
|
|
if (ret != ERR_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
return DeepCamGetFaceFeature(FaceCache::GetInstance()->GetFrame(), landmark, feature);
|
|
}
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamFaceFeatureCompareStd(const float* feature1, const float* feature2, float & fSimilarity)
|
|
{
|
|
return DeepCamFaceFeatureCompare(feature1, feature2, fSimilarity);
|
|
}
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamFaceLivenessRgbStd(IN int index, OUT float& score)
|
|
{
|
|
float landmark[10] = { 0 };
|
|
int ret = FaceCache::GetInstance()->GetFaceLandmark(index, landmark);
|
|
if (ret != ERR_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
return DeepCamFaceLivenessRgb(FaceCache::GetInstance()->GetFrame(), landmark, score);
|
|
}
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamFaceLivenesIrStd(IN int index, OUT float& score)
|
|
{
|
|
float landmark[10] = { 0 };
|
|
float face_rect[4] = { 0 };
|
|
int ret = FaceCache::GetInstance()->GetFaceLandmark(index, landmark);
|
|
if (ret != ERR_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
ret = FaceCache::GetInstance()->GetFaceRect(index, face_rect);
|
|
if (ret != ERR_OK)
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
return DeepCamFaceLivenesIr(FaceCache::GetInstance()->GetFrame(), face_rect[0], face_rect[1],
|
|
face_rect[2], face_rect[3],landmark, score);
|
|
}
|
|
|
|
DEEPCAM_API_EXPORT int DeepCamGetFaceLandmark68Std(IN int index, OUT float* landmark68)
|
|
{
|
|
float face_rect[4] = { 0 };
|
|
int ret = FaceCache::GetInstance()->GetFaceRect(index, face_rect);
|
|
if (ret != ERR_OK)
|
|
{
|
|
memset(landmark68, 0, sizeof(float) * 136);
|
|
return ret;
|
|
}
|
|
return DeepCamGetFaceLandmarks68(FaceCache::GetInstance()->GetFrame(), face_rect[0], face_rect[1], face_rect[2], face_rect[3], landmark68);
|
|
}
|
|
|
|
|
|
/**********************************人脸库管理接口************************************/
|
|
DEEPCAM_API_EXPORT int DeepCamEnterFace(IN const char* name, IN const char* vid, IN const char* group_name,
|
|
IN const float* feature, IN const unsigned char* img_data, IN int img_data_len)
|
|
{
|
|
std::vector<float> _feature(feature, feature + 512);
|
|
std::vector<unsigned char> _img_data(img_data, img_data + img_data_len);
|
|
return FaceDbMgr::GetInstance()->EnterFace(_feature, std::string(name), std::string(vid), std::string(group_name), _img_data);
|
|
}
|
|
|
|
//DEEPCAM_API_EXPORT int DeepCamFaceSearch(IN const float* feature, IN const char* group_name, OUT char* name, OUT char* vid,
|
|
// OUT const uint8_t* img_data, OUT float& fSimilarity, float fThreshold = 0.8)
|
|
//{
|
|
|
|
//}
|
|
|
|
//DEEPCAM_API_EXPORT int DeepCamDeleteFaceByName(IN const char* name, IN const char* group_name);
|
|
|
|
//DEEPCAM_API_EXPORT int DeepCamDeleteAllFace(IN const char* group_name);
|
|
|
|
//DEEPCAM_API_EXPORT int DeepCamAddFaceGroup(IN const char* group_name, IN const char* remarks);
|
|
|
|
//DEEPCAM_API_EXPORT int DeepCamDeleteFaceGroup(IN const char* group_name);
|
|
|
|
#ifdef __cplusplus
|
|
} //end extern "C"
|
|
#endif |