Files
DeepCamFaceSDK2.0/Src/FaceDbMgr.cpp
2024-12-13 23:33:37 +08:00

843 lines
27 KiB
C++

//#include <ShlObj.h>
#include <omp.h>
#include <iostream>
#include <filesystem>
#include "Inc/FaceDbMgr.h"
#define SEARCH_FACE_THRESHOLD 0.8 //A similarity threshold for default match
#define SAME_FACE_THRESHOLD 0.7 //A similarity threshold for entering the same person
#define FEATURE_NAME_MAX_LEN 64 //Max lenght for entering name
//创建人脸数据表 ID Feature Name VID Image GroupID EnterTime
#define FS_DB_CREATE_TABLE "CREATE TABLE table_features(ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,Feature blob NOT NULL,Name VARCHAR(64) NOT NULL,VID VARCHAR(64),Image blob NOT NULL,GroupID INTEGER NOT NULL,EnterTime datetime default(datetime('now','localtime')));"
//检查人脸数据表是否存在
#define FS_DB_CHECK_TABLE_EXIST "select count(*) from sqlite_master where type='table' and name = 'table_features';"
//给人脸数据表 ID字段加上索引
#define FS_DB_CREATE_ID_INDEX "CREATE UNIQUE INDEX id_index ON table_features(ID);"
//检查人脸数据表 ID字段是否有索引
#define FS_DB_CHECK_ID_INDEX_EXIST "select count(*) from sqlite_master where type='index' and name = 'id_index';"
//给人脸数据表 NAME字段加上索引
#define FS_DB_CREATE_NAME_INDEX "CREATE INDEX name_index ON table_features(Name);"
//检查人脸数据表 NAME字段是否有索引
#define FS_DB_CHECK_NAME_INDEX_EXIST "select count(*) from sqlite_master where type='index' and name = 'name_index';"
//查询人数据表 人脸特征总数
#define FS_DB_QUERY_FEATURES_SIZE "select count(*) from table_features;"
//查询分组下面的人脸特征总数
#define FS_DB_QUERY_GROUP_FEATURES_SIZE "select count(*) from table_features where GroupID=?;"
//添加人脸数据
#define FS_DB_INSERT_FEATURE_DATA "insert into table_features(Feature,Name,VID,Image,GroupID) values(?,?,?,?,?)"
#define FS_DB_CLEAR_TABLE_SEQUENCE "UPDATE sqlite_sequence SET seq = 0 WHERE name='table_features';"
//通过名字删除人脸
#define FS_DB_DELETE_FEATURE_BY_NAME "delete from table_features where Name=? and GroupID=?;" //The '?' in string can't be quoted with '',or it can't not be parsed by 'sqlite3_prepare'
//删除分组下面的所有人脸数据
#define FS_DB_DELETE_FEATURE_BY_GROUP "delete from table_features where GroupID=?;"
//查询所有人脸数据
#define FS_DB_QUERY_FEATURES_INFO "SELECT * FROM table_features;"
//通过Group Id 查询人脸数据
#define FS_DB_QUERY_FEATURES_INFO_BY_GROPU "SELECT * FROM table_features WHERE GroupID=?;"
//通过名字查询人脸数据
#define FS_DB_QUERY_FEATURES_INFO_BY_NAME "SELECT * FROM table_features WHERE NAME=? AND GroupID=?;"
//通过名字和组ID查询图片
#define FS_DB_QUERY_IMG_BY_NAME "SELECT Image FROM table_features WHERE NAME=? AND GroupID=?;"
#define FACEFEATURES_DEFAULT_SIZE 2000 //A default increase size
//分组表sql
//创建人脸分组索引表
#define FS_DB_CREATE_GROUP_TABLE "CREATE TABLE table_group(ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,Name VARCHAR(64) NOT NULL, Remarks VARCHAR(512),EnterTime datetime default(datetime('now','localtime')));"
//检查分组表是否存在
#define FS_DB_CHECK_GROUP_TABLE_EXIST "select count(*) from sqlite_master where type='table' and name = 'table_group';"
//给分组表添加名称索引
#define FS_DB_GROUP_CREATE_ID_INDEX "CREATE UNIQUE INDEX group_name_index ON table_group(Name);"
//查询分组总数
#define FS_DB_QUERY_GROUP_SIZE "select count(*) from table_group;"
//通过名字查询分组ID
#define FS_DB_QUERY_GROUP_ID_BY_NAME "select ID from table_group where Name=?;"
//通过名字查询分组信息
#define FS_DB_QUERY_GROUP_BY_NAME "select * from table_group where Name=?;"
//通过ID查询分组信息
#define FS_DB_QUERY_GROUP_BY_ID "select * from table_group where ID=?;"
//查询分组数据
#define FS_DB_QUERY_GROUP_DATA "select * from table_group;"
//通过名字删除分组表
#define FS_DB_DELETE_GROUP_BY_NAME "delete from table_group where Name=?;"
//插入一条分组数据
#define FS_DB_INSTER_GROUP_DATA "insert into table_group(Name,Remarks) values(?,?)"
FaceDbMgr* FaceDbMgr::m_instance = nullptr;
std::vector<DB_GROUP_OBJ> FaceDbMgr::m_groups;
std::map<int, std::vector<DB_FACE_OBJ>> FaceDbMgr::m_GroupDb;
static int _callback_exec(void * notused, int argc, char ** argv, char ** aszColName)
{
return 0;
}
/******************************************************************/
float FaceDbMgr::FeatureCompare(const float* feature1, const float* feature2)
{
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))));
//return score;
//拉高分数
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);
ret = fabsf(temp - min_score) / (max_score - min_score);
}
return ret;
}
/******************************************************************/
FaceDbMgr* FaceDbMgr::GetInstance()
{
if (m_instance == nullptr)
{
m_instance = new FaceDbMgr();
}
return m_instance;
}
FaceDbMgr::FaceDbMgr(char * pcDbName)
{
/******************初始化错误映射表**********************/
//m_err_info[DB_ERR_SQL] = UnicodeToUtf8(L"数据库引擎内部SQL脚本错误");
//m_err_info[DB_ERR_BIND_SQL_DATA] = UnicodeToUtf8(L"数据库引擎内部绑定SQL参数错误");
//m_err_info[DB_ERR_SQL_EXE] = UnicodeToUtf8(L"数据库引擎内部执行SQL错误");
//m_err_info[DB_ERR_FEATURE_LEN] = UnicodeToUtf8(L"人脸特征长度错误");
//m_err_info[DB_ERR_NAME_FEATURE_EXIST] = UnicodeToUtf8(L"当前名字已经被注册");
//m_err_info[DB_ERR_GROUP_FEATURE_FULL] = UnicodeToUtf8(L"当前分组下的人脸注册数量已经达到上限");
//m_err_info[DB_ERR_GROUP_FULL] = UnicodeToUtf8(L"当前分组数量已经达到上限,无法创建新的分组");
//m_err_info[DB_ERR_ADD_FACE_FEATURE] = UnicodeToUtf8(L"录入人脸特征失败");
//m_err_info[DB_ERR_NON_GROUP] = UnicodeToUtf8(L"输入的分组名称不存在");
//m_err_info[DB_ERR_GROUP_REPEAT] = UnicodeToUtf8(L"当前分组名称已经被使用");
//m_err_info[DB_ERR_ADD_GROUP] = UnicodeToUtf8(L"添加分组失败");
//m_err_info[DB_ERR_NO_INIT] = UnicodeToUtf8(L"数据库引擎未初始化");
//m_err_info[DB_ERR_NO_DATA] = UnicodeToUtf8(L"未查询到数据");
//m_err_info[DB_ERR_OK] = UnicodeToUtf8(L"无错误");
/******************************************************/
m_bDbInit = false;
m_db = NULL;
std::string tempDbPath = std::string(std::experimental::filesystem::current_path().generic_string()) + std::string("/FaceDb/");
if (!std::experimental::filesystem::exists(std::experimental::filesystem::path(tempDbPath)))
{
std::experimental::filesystem::create_directory(std::experimental::filesystem::path(tempDbPath));
}
tempDbPath.append(pcDbName);
int res = 0;
res = sqlite3_open(tempDbPath.c_str(), &m_db);
if (res != SQLITE_OK)
{
std::cout << "Open DB " << tempDbPath.c_str() << "Failed. ErrCode is :" << res << std::endl;
return;
}
m_bDbInit = true;
//查询分组索引表是否存在
if (QueryTableSize(FS_DB_CHECK_GROUP_TABLE_EXIST) < 1)
{
//创建分组索引表
FeatureDBMgrExec(FS_DB_CREATE_GROUP_TABLE);
FeatureDBMgrExec(FS_DB_GROUP_CREATE_ID_INDEX);
}
if (QueryTableSize(FS_DB_CHECK_TABLE_EXIST) < 1)
{
//创建人脸数据表
FeatureDBMgrExec(FS_DB_CREATE_TABLE);
if (QueryTableSize(FS_DB_CHECK_NAME_INDEX_EXIST) < 1)
{//创建名字索引
res = FeatureDBMgrExec(FS_DB_CREATE_NAME_INDEX);
if (res != SQLITE_OK)
{
std::cout << "Create name_index Failed ...ErrCode:" << res << std::endl;
return;
}
res = FeatureDBMgrExec(FS_DB_CREATE_ID_INDEX);
if (res != SQLITE_OK)
{
std::cout << "Create id_index Failed ...ErrCode:" << res << std::endl;
return;
}
}
}
std::cout << "Face DB Init Ok! " << std::endl;
{//加载人脸数据到内存
int group_num = QueryTableSize(FS_DB_QUERY_GROUP_SIZE);
if (group_num < 1) return; //没有分组,数据库没有人脸数据
QueryGroupDatas(m_groups);
std::cout << "group num: "<< m_groups.size() << std::endl;
for (auto& obj: m_groups)
{
std::vector<DB_FACE_OBJ> face_objs;
QueryFeatrueByGroup(obj, face_objs);
m_GroupDb[obj.group_id] = face_objs;
std::cout << "load group " << obj.group_name << ",face num: " << face_objs.size() << std::endl;
}
std::cout << "load data ok!" << std::endl;
}
}
FaceDbMgr::~FaceDbMgr()
{
if (m_db)
{
int res = sqlite3_close(m_db);
if (res == SQLITE_OK)
{
m_db = NULL;
}
else
{
std::cout << "Close DB Failed. ErrCode is : " << res << std::endl;
}
}
}
bool FaceDbMgr::IsDbInit()
{
return m_bDbInit;
}
int FaceDbMgr::FeatureDBMgrExec(const char * strSql)
{
if (!m_bDbInit)
{
return -1;//DB must be initialized
}
char * pErrMsg = NULL;
int res = sqlite3_exec(m_db, strSql, _callback_exec, 0, &pErrMsg);
return res;
}
/***************************************************************/
/* 查询数据数量 */
int FaceDbMgr::QueryTableSize(const char * strSql)
{
if (!m_bDbInit || strSql == NULL) return DB_ERR_NO_INIT;
int ret;
sqlite3_stmt * pstmt = NULL;
ret = sqlite3_prepare_v2(m_db, strSql, strlen(strSql), &pstmt, 0);
if (ret != SQLITE_OK)
{
return 0;
}
AutoDeleteStmt ads(pstmt);//这里不清理干净会导致数据库关闭时返回错误码SQLITE_BUSY
ret = sqlite3_step(pstmt);
if (ret != SQLITE_ROW)
{
return 0;
}
int countNum = sqlite3_column_int(pstmt, 0);
return countNum;
}
/* 通过名字查询查询数据数量 */
int FaceDbMgr::QueryTableSizeByName(const char * strSql, const char * strPersonName)
{
if (!IsDbInit()) return DB_ERR_NO_INIT;
int ret;
sqlite3_stmt * pstmt = NULL;
ret = sqlite3_prepare_v2(m_db, strSql, strlen(strSql), &pstmt, 0);
if (ret != SQLITE_OK)
{
return DB_ERR_SQL;
}
AutoDeleteStmt ads(pstmt);//这里不清理干净会导致数据库关闭时返回错误码SQLITE_BUSY
ret = sqlite3_bind_text(pstmt, 1, strPersonName, strnlen_s(strPersonName, 64), NULL);
if (ret != SQLITE_OK)
{
return DB_ERR_BIND_SQL_DATA;
}
ret = sqlite3_step(pstmt);
if (ret != SQLITE_ROW)
{
return DB_ERR_SQL_EXE;
}
int countNum = sqlite3_column_int(pstmt, 0);
return countNum;
}
/* 查询所有的人脸特征数量*/
int FaceDbMgr::QueryAllFeatureSize()
{
if (!IsDbInit()) return DB_ERR_NO_INIT;
int ret;
sqlite3_stmt * pstmt = NULL;
ret = sqlite3_prepare_v2(m_db, FS_DB_QUERY_FEATURES_SIZE, strlen(FS_DB_QUERY_FEATURES_SIZE), &pstmt, 0);
if (ret != SQLITE_OK) return DB_ERR_SQL;
AutoDeleteStmt ads(pstmt);//这里不清理干净会导致数据库关闭时返回错误码SQLITE_BUSY
ret = sqlite3_step(pstmt);
if (ret != SQLITE_ROW) return DB_ERR_SQL_EXE;
return sqlite3_column_int(pstmt, 0);
}
/* 查询分组内所有的人脸特征数量 */
int FaceDbMgr::QueryGroupAllFeatureSize(int group_id)
{
if (!IsDbInit()) return DB_ERR_NO_INIT;
int ret;
sqlite3_stmt * pstmt = NULL;
ret = sqlite3_prepare_v2(m_db, FS_DB_QUERY_GROUP_FEATURES_SIZE,
strlen(FS_DB_QUERY_GROUP_FEATURES_SIZE), &pstmt, 0);
if (ret != SQLITE_OK) return DB_ERR_SQL;
ret = sqlite3_bind_int(pstmt, 1, group_id);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
AutoDeleteStmt ads(pstmt);//这里不清理干净会导致数据库关闭时返回错误码SQLITE_BUSY
ret = sqlite3_step(pstmt);
if (ret != SQLITE_ROW)
{
if (ret != SQLITE_DONE)
{
return DB_ERR_SQL_EXE;
}
return DB_ERR_NO_DATA;
}
int num = sqlite3_column_int(pstmt, 0);
return num;
}
//通过组名查询组内注册人脸特征数量
int FaceDbMgr::QueryNameFeatureInGroupSize(std::string groupName, std::string faceName)
{
if (!IsDbInit()) return DB_ERR_NO_INIT;
int ret;
sqlite3_stmt * pstmt = NULL;
ret = sqlite3_prepare_v2(m_db, FS_DB_QUERY_GROUP_FEATURES_SIZE,
strlen(FS_DB_QUERY_GROUP_FEATURES_SIZE), &pstmt, 0);
if (ret != SQLITE_OK) return DB_ERR_SQL;
ret = sqlite3_bind_text(pstmt, 1, groupName.c_str(), groupName.length(), NULL);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_bind_text(pstmt, 2, faceName.c_str(), faceName.length(), NULL);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
AutoDeleteStmt ads(pstmt);//这里不清理干净会导致数据库关闭时返回错误码SQLITE_BUSY
ret = sqlite3_step(pstmt);
if (ret != SQLITE_ROW)
{
if (ret == SQLITE_DONE)
{
return DB_ERR_NO_DATA;
}
return DB_ERR_SQL_EXE;
}
int feature_num = sqlite3_column_int(pstmt, 0);
return feature_num;
}
//查询所有分组数量
int FaceDbMgr::QueryAllGroupSize()
{
if (!IsDbInit()) return DB_ERR_NO_INIT;
int ret;
sqlite3_stmt * pstmt = NULL;
ret = sqlite3_prepare_v2(m_db, FS_DB_QUERY_GROUP_SIZE, strlen(FS_DB_QUERY_GROUP_SIZE), &pstmt, 0);
if (ret != SQLITE_OK) return DB_ERR_SQL;
ret = sqlite3_step(pstmt);
AutoDeleteStmt ads(pstmt);//这里不清理干净会导致数据库关闭时返回错误码SQLITE_BUSY
if (ret != SQLITE_ROW)
{
if (ret == SQLITE_DONE)
{
return DB_ERR_NO_DATA;
}
return DB_ERR_SQL_EXE;
}
return sqlite3_column_int(pstmt, 0);
}
//通过组名字查询组ID
int FaceDbMgr::QueryGroupIdByName(std::string groupName)
{
if (!IsDbInit()) return DB_ERR_NO_INIT;
int ret;
sqlite3_stmt * pstmt = NULL;
ret = sqlite3_prepare_v2(m_db, FS_DB_QUERY_GROUP_ID_BY_NAME, strlen(FS_DB_QUERY_GROUP_ID_BY_NAME), &pstmt, 0);
if (ret != SQLITE_OK) return DB_ERR_SQL;
ret = sqlite3_bind_text(pstmt, 1, groupName.c_str(), groupName.length(), NULL);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_step(pstmt);
AutoDeleteStmt ads(pstmt);//这里不清理干净会导致数据库关闭时返回错误码SQLITE_BUSY
if (ret != SQLITE_ROW)
{
if (ret == SQLITE_DONE)
{
return DB_ERR_NO_DATA;
}
return DB_ERR_SQL_EXE;
}
int group_id = sqlite3_column_int(pstmt, 0);
return group_id;
}
int FaceDbMgr::QueryGroupByName(std::string groupName, std::vector<DB_GROUP_OBJ>& objs)
{
if (!IsDbInit()) return DB_ERR_NO_INIT;
int ret;
sqlite3_stmt * pstmt = NULL;
ret = sqlite3_prepare_v2(m_db, FS_DB_QUERY_GROUP_BY_NAME, strlen(FS_DB_QUERY_GROUP_BY_NAME), &pstmt, 0);
AutoDeleteStmt ads(pstmt);
if (ret != SQLITE_OK) return DB_ERR_SQL;
ret = sqlite3_bind_text(pstmt, 1, groupName.c_str(), groupName.length(), NULL);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
while (sqlite3_step(pstmt) == SQLITE_ROW)
{
DB_GROUP_OBJ obj;
obj.group_id = sqlite3_column_int(pstmt, 0);
obj.group_name = std::string((const char*)sqlite3_column_text(pstmt, 1), sqlite3_column_bytes(pstmt, 1));
obj.remarks = std::string((const char*)sqlite3_column_text(pstmt, 2), sqlite3_column_bytes(pstmt, 2));
obj.remarks = std::string((const char*)sqlite3_column_text(pstmt, 3), sqlite3_column_bytes(pstmt, 3));
objs.push_back(obj);
}
return objs.size();
}
int FaceDbMgr::QueryGroupByID(int group_id, std::vector<DB_GROUP_OBJ>& objs)
{
if (!IsDbInit()) return DB_ERR_NO_INIT;
int ret;
sqlite3_stmt * pstmt = NULL;
ret = sqlite3_prepare_v2(m_db, FS_DB_QUERY_GROUP_BY_NAME, strlen(FS_DB_QUERY_GROUP_BY_NAME), &pstmt, 0);
AutoDeleteStmt ads(pstmt);
if (ret != SQLITE_OK) return DB_ERR_SQL;
ret = sqlite3_bind_int(pstmt, 1, group_id);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
while (sqlite3_step(pstmt) == SQLITE_ROW)
{
DB_GROUP_OBJ obj;
obj.group_id = sqlite3_column_int(pstmt, 0);
obj.group_name = std::string((const char*)sqlite3_column_text(pstmt, 1), sqlite3_column_bytes(pstmt, 1));
obj.remarks = std::string((const char*)sqlite3_column_text(pstmt, 2), sqlite3_column_bytes(pstmt, 2));
obj.remarks = std::string((const char*)sqlite3_column_text(pstmt, 3), sqlite3_column_bytes(pstmt, 3));
objs.push_back(obj);
}
return objs.size();
}
/* 查询所有的组数据 */
DB_ERR_CODE FaceDbMgr::QueryGroupDatas(std::vector<DB_GROUP_OBJ>& objs)
{
if (!IsDbInit()) return DB_ERR_NO_INIT;
sqlite3_stmt * stat = NULL;
int res = sqlite3_prepare(m_db, FS_DB_QUERY_GROUP_DATA, -1, &stat, 0);
if (res != SQLITE_OK) return DB_ERR_SQL;
AutoDeleteStmt ads(stat);
while (sqlite3_step(stat) == SQLITE_ROW)
{
DB_GROUP_OBJ obj;
obj.group_id = sqlite3_column_int(stat, 0);
obj.group_name = std::string((const char*)sqlite3_column_text(stat, 1), sqlite3_column_bytes(stat,1));
obj.remarks = std::string((const char*)sqlite3_column_text(stat, 2), sqlite3_column_bytes(stat, 2));
obj.create_time = std::string((const char*)sqlite3_column_text(stat, 3), sqlite3_column_bytes(stat, 3));
objs.push_back(obj);
}
return DB_ERR_OK;
}
/*根据组ID查询人脸数据*/
int FaceDbMgr::QueryFeatrueByGroup(DB_GROUP_OBJ& group, std::vector<DB_FACE_OBJ>& face_db)
{
if (!IsDbInit()) return DB_ERR_NO_INIT;
sqlite3_stmt * stat = NULL;
int res = sqlite3_prepare(m_db, FS_DB_QUERY_FEATURES_INFO_BY_GROPU, -1, &stat, 0);
AutoDeleteStmt ads(stat);
if (res != SQLITE_OK) return DB_ERR_SQL;
res = sqlite3_bind_int(stat, 1, group.group_id);
if (res != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
while (sqlite3_step(stat) == SQLITE_ROW)
{
DB_FACE_OBJ obj;
const void* pFeatureBytes = sqlite3_column_blob(stat, 1);
int featureLen = sqlite3_column_bytes(stat, 1);
if (featureLen != MOBILE_FACE_FEATURE_BYTE_LEN)
{
std::cout << "feature length error..." << std::endl;
continue;
}
memcpy_s(obj.byteFeature, featureLen, pFeatureBytes, featureLen);
obj.name = std::string((const char*)sqlite3_column_text(stat, 2), sqlite3_column_bytes(stat, 2));
obj.vip_id = std::string((const char*)sqlite3_column_text(stat, 3), sqlite3_column_bytes(stat, 3));
obj.group = group;
obj.enter_time = std::string((const char*)sqlite3_column_text(stat, 6), sqlite3_column_bytes(stat, 6));
face_db.push_back(obj);
}
return face_db.size();
}
/*通过姓名查询人脸特征库*/
int FaceDbMgr::QueryFeatureByName(std::string face_name, std::string group_name, std::vector<DB_FACE_OBJ>& face_db)
{
face_db.clear();
std::vector<DB_GROUP_OBJ> group_objs;
QueryGroupByName(group_name, group_objs);
if (group_objs.size() < 1) return DB_ERR_NON_GROUP;
sqlite3_stmt * stat = NULL;
int res = sqlite3_prepare(m_db, FS_DB_QUERY_FEATURES_INFO_BY_NAME, -1, &stat, 0);
AutoDeleteStmt ads(stat);
if (res != SQLITE_OK) return DB_ERR_SQL;
res = sqlite3_bind_text(stat, 1, face_name.c_str(), face_name.length(), NULL);
if (res != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
res = sqlite3_bind_int(stat, 2, group_objs[0].group_id);
if (res != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
while (sqlite3_step(stat) == SQLITE_ROW)
{
DB_FACE_OBJ obj;
const void* pFeatureBytes = sqlite3_column_blob(stat, 1);
int featureLen = sqlite3_column_bytes(stat, 1);
if (featureLen != MOBILE_FACE_FEATURE_BYTE_LEN)
{
std::cout << "feature length error..." << std::endl;
continue;
}
memcpy_s(obj.byteFeature, featureLen, pFeatureBytes, featureLen);
obj.name = std::string((const char*)sqlite3_column_text(stat, 2), sqlite3_column_bytes(stat, 2));
obj.vip_id = std::string((const char*)sqlite3_column_text(stat, 3), sqlite3_column_bytes(stat, 3));
obj.group = group_objs[0];
obj.enter_time = std::string((const char*)sqlite3_column_text(stat, 6), sqlite3_column_bytes(stat, 6));
face_db.push_back(obj);
}
return face_db.size();
}
/*通过姓名查询人脸图片*/
//FS_DB_QUERY_IMG_BY_NAME
int FaceDbMgr::QueryImageByName(std::string face_name, int group_id, std::vector<uint8_t>& img_data)
{
if (!IsDbInit()) return DB_ERR_NO_INIT;
int ret;
sqlite3_stmt * pstmt = NULL;
ret = sqlite3_prepare_v2(m_db, FS_DB_QUERY_IMG_BY_NAME, strlen(FS_DB_QUERY_IMG_BY_NAME), &pstmt, 0);
if (ret != SQLITE_OK)
{
return DB_ERR_SQL;
}
AutoDeleteStmt ads(pstmt);//这里不清理干净会导致数据库关闭时返回错误码SQLITE_BUSY
ret = sqlite3_bind_text(pstmt, 1, face_name.c_str(), face_name.length(), NULL);
if (ret != SQLITE_OK)return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_bind_int(pstmt, 2, group_id);
if (ret != SQLITE_OK)return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_step(pstmt);
if (ret != SQLITE_ROW) return DB_ERR_SQL_EXE;
const void* tmp_data = sqlite3_column_blob(pstmt, 0);
int data_len = sqlite3_column_bytes(pstmt, 0);
img_data.resize(data_len);
memcpy_s(img_data.data(), data_len, tmp_data, data_len);
return DB_ERR_OK;
}
/*********************** FaceDB API *****************************/
std::string FaceDbMgr::GetErrInfo(DB_ERR_CODE err_code)
{
std::string err_info = m_err_info[err_code];
if (err_info.empty())
{
return "unknow error";
//return UnicodeToUtf8(L"未知错误...");
}
return err_info;
}
DB_ERR_CODE FaceDbMgr::EnterFace(const std::vector<float>& feature, std::string face_name, std::string vid, std::string group_name, std::vector<unsigned char> & imgData)
{
/*
1.判断特征长度
2.判断分组是否存在
3.判断分组数据是否存满
4.判断人脸特征是否已注册
*/
std::lock_guard<std::mutex> lock(m_db_lock);
if (!m_bDbInit) return DB_ERR_NO_INIT;
if (feature.size() != MOBILE_FACE_FEATURE_FLOAT_LEN) return DB_ERR_FEATURE_LEN;//特征长度不对
int group_id = QueryGroupIdByName(group_name);
if (group_id < 0) return DB_ERR_NON_GROUP; //分组不存在
if (QueryGroupAllFeatureSize(group_id) >= MAX_FEATURE_FOR_GROUP) return DB_ERR_GROUP_FEATURE_FULL;
std::vector<DB_FACE_OBJ> face_objs;
if (QueryFeatureByName(face_name, group_name, face_objs) > 0)
{
return DB_ERR_NAME_FEATURE_EXIST;
}
/* 插入人脸数据 */
sqlite3_stmt * stat;
int ret = sqlite3_prepare_v2(m_db, FS_DB_INSERT_FEATURE_DATA, -1, &stat, 0);
AutoDeleteStmt ads(stat);
if (ret != SQLITE_OK) return DB_ERR_SQL;
ret = sqlite3_bind_blob(stat, 1, (unsigned char *)feature.data(), feature.size()*sizeof(float), NULL);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_bind_text(stat, 2, face_name.c_str(), face_name.length(), NULL);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_bind_text(stat, 3, vid.c_str(), vid.length(), NULL);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_bind_blob(stat, 4, imgData.data(), imgData.size(), NULL);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_bind_int64(stat, 5, group_id);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_step(stat);
if (ret != SQLITE_DONE) return DB_ERR_ADD_FACE_FEATURE;
//同步到内存
if (QueryFeatureByName(face_name, group_name, face_objs) < 1)
{
return DB_ERR_ADD_FACE_FEATURE;
}
m_GroupDb[group_id].push_back(face_objs[0]);
return DB_ERR_OK;
}
DB_ERR_CODE FaceDbMgr::FaceSearch(const std::vector<float> & feature, const std::string group_name, DB_FACE_OBJ& face_obj, std::vector<uint8_t>& img_data, float & fSimilarity, float fThreshold)
{
/*
1.查询组ID
2.在对应分组人脸库比对特征
*/
std::lock_guard<std::mutex> lock(m_db_lock);
fSimilarity = 0.f;
//if (feature.size() != MOBILE_FACE_FEATURE_FLOAT_LEN) return 0;
auto iter = find_if(m_groups.begin(), m_groups.end(), [&group_name](const DB_GROUP_OBJ& tmp_obj) {
if (tmp_obj.group_name.compare(group_name) == 0)
{
return true;
}
return false;
});
if (iter == m_groups.end())
{
//没找到分组
return DB_ERR_NON_GROUP;
}
auto& face_db = m_GroupDb[iter->group_id];
if (face_db.size() == 0)
{
return DB_ERR_NO_DATA; //分组内没有人脸数据
}
std::vector<SEARCH_FACE_RESULT> results;
results.resize(face_db.size());
{
omp_set_num_threads(omp_get_num_procs() - 1);
#pragma omp parallel for
for (int i = 0; i < face_db.size(); i++)
{
results[i].score = FeatureCompare(feature.data(), (float*)face_db[i].byteFeature);
results[i].face_obj = face_db[i];
}
}
sort(results.begin(), results.end(), [&results](const SEARCH_FACE_RESULT& v1, const SEARCH_FACE_RESULT& v2) {
return v1.score > v2.score;
});
for (int j = 0; j < results.size(); j++)
{
if (results[j].score > fThreshold)
{
face_obj = results[j].face_obj;
fSimilarity = results[j].score;
QueryImageByName(face_obj.name, face_obj.group.group_id, img_data);
//FILE* fp;
//errno_t err = fopen_s(&fp,"E:/out1.jpg", "wb+");
//fwrite(img_data.data(), 1, img_data.size(), fp);
//fclose(fp);
}
break;
}
return DB_ERR_OK;
}
DB_ERR_CODE FaceDbMgr::DeleteFaceByName(std::string face_name, std::string group_name)
{
/*
1.通过分组名查询分组ID
2.通过名字和分组ID从数据库中删除数据
3.从内存中删除数据
*/
std::lock_guard<std::mutex> lock(m_db_lock);
if (!m_bDbInit) return DB_ERR_NO_INIT;
int group_id = QueryGroupIdByName(group_name);
if (group_id < 0) return DB_ERR_NON_GROUP; //分组不存在
sqlite3_stmt * stat;
int ret = sqlite3_prepare_v2(m_db, FS_DB_DELETE_FEATURE_BY_NAME, -1, &stat, 0);
if (ret != SQLITE_OK) return DB_ERR_SQL;
AutoDeleteStmt ads(stat);
ret = sqlite3_bind_text(stat, 1, face_name.c_str(), face_name.length(), NULL);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_bind_int(stat, 2, group_id);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_step(stat);
if (ret != SQLITE_DONE)
{//删除人脸失败
return DB_ERR_SQL_EXE;
}
//从内存中删除
m_GroupDb[group_id].erase(remove_if(m_GroupDb[group_id].begin(), m_GroupDb[group_id].end(),
[&face_name](DB_FACE_OBJ& face_obj) {
return face_obj.name.compare(face_name) == 0 ? true : false;
}), m_GroupDb[group_id].end());
return DB_ERR_OK;
}
DB_ERR_CODE FaceDbMgr::DeleteAllFace(std::string group_name)
{
std::lock_guard<std::mutex> lock(m_db_lock);
if (!m_bDbInit) return DB_ERR_NO_INIT;
int group_id = QueryGroupIdByName(group_name);
if (group_id < 0) return DB_ERR_NON_GROUP; //分组不存在
sqlite3_stmt * stat;
int ret = sqlite3_prepare_v2(m_db, FS_DB_DELETE_FEATURE_BY_NAME, -1, &stat, 0);
AutoDeleteStmt ads(stat);
if (ret != SQLITE_OK) return DB_ERR_SQL;
ret = sqlite3_bind_int(stat, 1, group_id);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_step(stat);
if (ret != SQLITE_DONE) return DB_ERR_SQL_EXE;
//从内存中删除
m_GroupDb[group_id].clear();
return DB_ERR_OK;
}
DB_ERR_CODE FaceDbMgr::AddGroup(std::string group_name, std::string remarks)
{
std::lock_guard<std::mutex> lock(m_db_lock);
if (!m_bDbInit) return DB_ERR_NO_INIT;
int group_id = QueryGroupIdByName(group_name);
if (group_id >= 0) return DB_ERR_GROUP_REPEAT;
sqlite3_stmt * stat;
int ret = sqlite3_prepare_v2(m_db, FS_DB_INSTER_GROUP_DATA, -1, &stat, 0);
if (ret != SQLITE_OK) return DB_ERR_SQL;
AutoDeleteStmt ads(stat);
ret = sqlite3_bind_text(stat, 1, group_name.c_str(), group_name.length(), NULL);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_bind_text(stat, 2, remarks.c_str(), remarks.length(), NULL);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_step(stat);
if (ret != SQLITE_DONE) return DB_ERR_ADD_GROUP;
std::vector<DB_GROUP_OBJ> groups;
QueryGroupByName(group_name, groups);
if (groups.size() < 1) return DB_ERR_ADD_GROUP;
m_groups.push_back(groups[0]);
return DB_ERR_OK;
}
DB_ERR_CODE FaceDbMgr::DeleteGroup(std::string group_name)
{
std::lock_guard<std::mutex> lock(m_db_lock);
if (!m_bDbInit) return DB_ERR_NO_INIT;
int group_id = QueryGroupIdByName(group_name);
if (group_id < 0) return DB_ERR_NON_GROUP;
auto err_code = DeleteAllFace(group_name);
if (err_code != DB_ERR_OK) return err_code;
sqlite3_stmt * stat;
int ret = sqlite3_prepare_v2(m_db, FS_DB_DELETE_GROUP_BY_NAME, -1, &stat, 0);
AutoDeleteStmt ads(stat);
if (ret != SQLITE_OK) return DB_ERR_SQL;
ret = sqlite3_bind_text(stat, 1, group_name.c_str(), group_name.length(), NULL);
if (ret != SQLITE_OK) return DB_ERR_BIND_SQL_DATA;
ret = sqlite3_step(stat);
if (ret != SQLITE_DONE) return DB_ERR_ADD_GROUP;
//从内存中删除
m_groups.erase(remove_if(m_groups.begin(), m_groups.end(), [&group_name](DB_GROUP_OBJ& group_obj) {
return (group_obj.group_name.compare(group_name) == 0) ? true : false;
}));
for (auto it = m_GroupDb.begin(); it != m_GroupDb.end();)
{
if (it->first == group_id)
m_GroupDb.erase(it);
}
return DB_ERR_OK;
}