4 Star 8 Fork 2

樊智慧/faceHttpd

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
face_container.cpp 8.97 KB
一键复制 编辑 原始数据 按行查看 历史
樊智慧 提交于 2019-07-19 11:39 +08:00 . 局部优化
/*************************************************************************
> File Name: face_container.cpp
> Author: fanzhihui
> Mail: 953106194@qq.com
> Created Time: Fri 14 Jun 2019 05:45:33 PM CST
************************************************************************/
#include "face_container.h"
#include<iostream>
#include "face_api_helper.h"
#include "config.h"
#include <future>
using namespace std;
bool KownFaceList::add(const string& key, const kown_face_info_t& face)
{
bool ret = true;
shared_ptr<kown_face_node_> node(new kown_face_node_());
node->info = face;
auto it = mapKownFace.find(key);
if( it == mapKownFace.end() ) {
mapKownFace[key] = node;
if(!head) {
head = node;
tail = node;
}else {
tail->next = node;
node->pre = tail;
tail = node;
}
} else {
ret = false;
}
return ret;
}
bool KownFaceList::find(const string& key,kown_face_info_t& out)
{
bool ret = true;
auto it = mapKownFace.find(key);
if( it == mapKownFace.end() ) {
ret = false;
}else{
out.features = it->second->info.features;
out.face_key = it->second->info.face_key;
out.face_id = it->second->info.face_id;
}
return ret;
}
bool KownFaceList::remove(const string& key,kown_face_info_t& del_face)
{
bool ret = true;
auto it = mapKownFace.find(key);
if( it == mapKownFace.end() ){
ret = false;
}else{
auto del = it->second;
if(head == del) {
head.reset();
tail.reset();
}else if( tail = del) {
tail = del->pre;
tail->next.reset();
}
del_face = it->second->info;
mapKownFace.erase(it);
}
return ret;
}
bool KownFaceList::update(const string& key,const kown_face_info_t & in)
{
bool ret = true;
auto it = mapKownFace.find(key);
if( it == mapKownFace.end() ){
ret = false;
}else{
it->second->info = in;
}
return ret;
}
void KownFaceList::clear()
{
for( auto it = mapKownFace.begin(); it != mapKownFace.end(); ++it ) {
it->second.reset();
}
for(auto ptr = head; !ptr; ) {
if( ptr.get() != NULL && !ptr->next ){
ptr->next->pre.reset();
auto cur = ptr;
ptr = ptr->next;
cur->next.reset();
}else{
break;
}
}
mapKownFace.clear();
head.reset();
tail.reset();
}
void KownFaceList::allFace(std::vector<kown_face_info_t>& all)
{
for(auto it = mapKownFace.begin(); it != mapKownFace.end(); ++it ) {
kown_face_info_t info = it->second->info;
all.push_back(it->second->info);
}
}
FaceContainer::FaceContainer()
{
}
FaceContainer::FaceContainer(const FaceContainer&)
{
}
FaceContainer& FaceContainer::operator=(const FaceContainer&)
{
}
void FaceContainer::Init(shared_ptr<FaceSerializeIf> serialize)
{
faceSerial = serialize;
vector<face_serial_info_t> serials;
faceSerial->UnSerialize(serials);
std::lock_guard<std::mutex> lock(locker);
for(uint32_t i = 0; i < serials.size(); i++) {
kown_face_info_t face = serials[i].face;
int op_flag = serials[i].op_flag;
string key = Key(face.face_id,face.face_key);
if( op_flag == SERIAL_ADD_FACE ){
kownFaces.add(key,face);
auto it = id2Keys.find(face.face_id);
if( it == id2Keys.end() ){
set<string> keys;
keys.insert(face.face_key);
id2Keys[face.face_id] = keys;
} else{
it->second.insert(face.face_key);
}
} else {
kown_face_info_t del;
kownFaces.remove(key,del);
auto it = id2Keys.find(face.face_id);
if( it != id2Keys.end() ){
it->second.erase(face.face_key);
}
}
}
std::cout <<"FaceContainer init kown face db size:" << kownFaces.size() << std::endl;
}
string FaceContainer::Key(const string& face_id,const string& face_key)
{
return face_id + face_key;
}
void FaceContainer::AddFace(const string& face_id, const string& face_key, const std::string& img_base64,bool overrid)
{
std::vector<float> features;
FaceApiHelper::getInstance()->get_face_feature_by_base64(img_base64,features);
if(features.size() != 512){
throw FaceContainerException("img have no features");
}
std::lock_guard<std::mutex> lock(locker);
kown_face_info_t info(face_id,face_key,features);
string key = Key(face_id,face_key);
if( !kownFaces.add(key,info) ) {
//
if( overrid ) {
if(!kownFaces.update(key,info)) {
throw FaceContainerException("add face exception");
}
} else {
throw FaceContainerException("repeat add face");
}
}
auto it = id2Keys.find(face_id);
if( it == id2Keys.end() ){
set<string> keys;
keys.insert(face_key);
id2Keys[face_id] = keys;
} else{
it->second.insert(face_key);
}
std::cout << "all faces num:" << kownFaces.size() << std::endl;
face_serial_info_t serial;
serial.face = info;
serial.op_flag = SERIAL_ADD_FACE;
faceSerial->Serialize(serial);
}
void FaceContainer::RemoveFace(const string& face_id)
{
vector<kown_face_info_t> delFaces;
std::lock_guard<std::mutex> lock(locker);
auto it = id2Keys.find(face_id);
if( it == id2Keys.end() ){
throw FaceContainerException("not found face id");
} else {
for( auto kit = it->second.begin(); kit != it->second.end(); ++kit ) {
string key = Key(face_id,*kit);
kown_face_info_t del;
if( !kownFaces.remove(key,del)) {
throw FaceContainerException("not found face key");
}
delFaces.push_back(del);
}
}
for( uint32_t i = 0; i < delFaces.size(); i++) {
face_serial_info_t serial;
serial.face = delFaces[i];
serial.op_flag = SERIAL_DELETE_FACE;
faceSerial->Serialize(serial);
}
}
typedef struct score_info_{
string face_id;
string face_key;
float score;
}score_info_t;
score_info_t max(const vector<score_info_t>& ss)
{
score_info_t ret;
float max_score = 0.000;
float cur_score = max_score;
for( uint32_t i = 0; i < ss.size(); i++){
cur_score = ss[i].score;
if(cur_score > max_score){
max_score = cur_score;
ret = ss[i];
}
}
return ret;
}
score_info_t find_max_score_face(const std::vector<kown_face_info_t>& all_face,vector<float>& features,uint32_t from,uint32_t to)
{
auto p1 = std::chrono::high_resolution_clock::now();
score_info_t ret;
float max_score = 0.000;
float cur_score = max_score;
for( uint32_t i = from; i < to; i++ ) {
cur_score = FaceApiHelper::getInstance()->compare_feature(features,all_face[i].features);
if( cur_score > max_score ) {
max_score = cur_score;
ret.face_id = all_face[i].face_id;
ret.face_key = all_face[i].face_key;
}
}
ret.score = max_score;
auto p2 = std::chrono::high_resolution_clock::now();
std::cout <<"find_max_score_face clock time:" <<
(float)std::chrono::duration_cast<std::chrono::microseconds>(p2 - p1).count() / 1000 << std::endl;
return ret;
}
//匹配人脸,返回score
void FaceContainer::FindFace(const std::string& image, string& face_id,string& face_key,float& score)
{
auto p1 = std::chrono::high_resolution_clock::now();
std::vector<float> features;
FaceApiHelper::getInstance()->get_face_feature_by_base64(image,features);
if(features.size() != 512){
throw FaceContainerException("img have no features");
}
auto p2 = std::chrono::high_resolution_clock::now();
std::cout <<"get feature clock time:" <<
(float)std::chrono::duration_cast<std::chrono::microseconds>(p2 - p1).count() / 1000 << std::endl;
locker.lock();
std::vector<kown_face_info_t> all_face;
kownFaces.allFace(all_face);
locker.unlock();
auto p3 = std::chrono::high_resolution_clock::now();
std::cout <<"get all face clock time:" <<
(float)std::chrono::duration_cast<std::chrono::microseconds>(p3 - p2).count() / 1000 << std::endl;
vector<std::future<score_info_t>> futures;
uint32_t faces_per_task = Config::faces_per_async_task;
uint32_t async_task_num = all_face.size() / faces_per_task;
for( uint32_t i = 0; i < async_task_num; i++) {
futures.push_back(std::async(std::launch::deferred,[&all_face,&features](uint32_t from, uint32_t to){
return find_max_score_face(all_face,features,from,to);
},
i*faces_per_task,
(i+1)*faces_per_task));
}
if( all_face.size() % faces_per_task != 0 ){
futures.push_back(std::async(std::launch::deferred,[&all_face,&features](uint32_t from, uint32_t to){
return find_max_score_face(all_face,features,from,to);
},
async_task_num*faces_per_task,
all_face.size()));
}
auto p3_1 = std::chrono::high_resolution_clock::now();
std::cout <<"create async clock time:" <<
(float)std::chrono::duration_cast<std::chrono::microseconds>(p3_1 - p3).count() / 1000 << std::endl;
vector<score_info_t> ss;
for( uint32_t i = 0; i < futures.size(); i++){
ss.push_back(futures[i].get());
}
auto p3_2 = std::chrono::high_resolution_clock::now();
std::cout <<"wait async clock time:" <<
(float)std::chrono::duration_cast<std::chrono::microseconds>(p3_2 - p3_1).count() / 1000 << std::endl;
auto ms = max(ss);
face_id = ms.face_id;
face_key = ms.face_key;
score = ms.score;
auto p4 = std::chrono::high_resolution_clock::now();
std::cout <<"compare all feature clock time:" <<
(float)std::chrono::duration_cast<std::chrono::microseconds>(p4 - p3).count() / 1000 << std::endl;
}
void FaceContainer::ClearFace()
{
std::lock_guard<std::mutex> lock(locker);
faceSerial->Clear();
id2Keys.clear();
kownFaces.clear();
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/wisefan/faceHttpd.git
git@gitee.com:wisefan/faceHttpd.git
wisefan
faceHttpd
faceHttpd
20190718

搜索帮助