//
|
// Created by pans on 4/27/18.
|
//
|
|
#include <iostream>
|
|
#include "jsoncpp/json/json.h"
|
|
#include <basic/debug/Debug.h>
|
#include <basic/util/app/AppPreference.hpp>
|
#include "FaceFeatureSearchServerI.h"
|
|
using namespace std;
|
|
static std::string t_cNodeName = "FaceSearch";
|
|
void erlangCallBackFunc(std::string) {
|
DBG("erlangCallBackFunc");
|
pthread_cond_signal(&(func_cond));
|
pthread_mutex_unlock(&(func_cond_mutex));
|
}
|
|
FaceFeatureSearchServerI::FaceFeatureSearchServerI()
|
: m_erlangDbTool(appConfig.getStringProperty("erlPath"), appConfig.getStringProperty("erlNode"),
|
appConfig.getStringProperty("erlCookie"), t_cNodeName), m_retUpdatePthread(true),
|
pManagerEsDB(appPref.getStringData("ipAdd"), appPref.getIntData("ipPort")), m_sqliteFaceEncap("LocalDataDB") {
|
|
auto erlFatherNode = appConfig.getStringProperty("erlFatherNode");
|
if (m_erlangDbTool.initErlang() == 1) {
|
m_erlangDbTool.startNodeDb(erlFatherNode);
|
}
|
|
m_erlangDbTool.test(&func_cond, &func_cond_mutex);
|
|
loadFeatureData(this);
|
}
|
|
FaceFeatureSearchServerI::FaceFeatureSearchServerI(Ice::CommunicatorPtr &ich, string nodeName, string cookie)
|
: m_erlangDbTool(nodeName, cookie, t_cNodeName), m_retUpdatePthread(true),
|
pManagerEsDB(appPref.getStringData("ipAdd"), appPref.getIntData("ipPort")),
|
m_sqliteFaceEncap("LocalDataDB") {
|
|
// try {
|
// std::string identity2 = ich->getProperties()->getProperty("user.FaceData");
|
// DBG(identity2);
|
// base_FaceMemoryData = ich->stringToProxy(appPref.getStringData("user.FaceData"));
|
// } catch (std::exception ex) {
|
// ERR("base_FaceMemoryData connceticon fail" << ex.what());
|
// };
|
|
loadFeatureData(this);
|
}
|
|
FaceFeatureSearchServerI::~FaceFeatureSearchServerI() {
|
t_live_ret = false;
|
}
|
|
//#todo 优化
|
::FaceSearch::FaceResults
|
FaceFeatureSearchServerI::faceSearchMax(const ::FaceSearch::Data &feature, const ::std::string &info_json,
|
const ::Ice::Current &) {
|
thread::id key = std::this_thread::get_id();
|
ClockTimer clockTimer("faceSearchMax");
|
::FaceSearch::FaceResults results;
|
FaceResults t_TableCompareResult;
|
AlarmData featureData;
|
featureData.num = 1;
|
featureData.feature.resize(feature.size());
|
memcpy(featureData.feature.data(), feature.data(), feature.size());
|
|
for (auto &it : m_faceFCMAP) {
|
auto &t_FaceFC = it.second;
|
auto t_tableInfo = m_tableType[it.first];
|
bool ret = getRet(t_tableInfo.startTime, t_tableInfo.endTime);
|
if (ret) {
|
bool alarmRet = atoi(t_tableInfo.bwType.c_str());
|
//#todo 非同步库是否需要比较?
|
t_FaceFC->compare(key, &featureData, 1);
|
auto t_results = t_FaceFC->getTopResult(key);
|
for (auto &t_item : t_results) {
|
t_item.tableName = it.first;
|
//#todo baojing zhuangtai ?
|
t_item.alarmRet = ret;
|
t_TableCompareResult.push_back(t_item);
|
}
|
}
|
}
|
|
// DBG("t_TableCompareResult size" << t_TableCompareResult.size());
|
for (auto itor = t_TableCompareResult.begin(); itor != t_TableCompareResult.end(); ++itor) {
|
float new_confidence = itor->confidence;
|
auto rtTR = results.rbegin();
|
if (!results.empty()) {
|
auto temp = rtTR->confidence;
|
while (new_confidence > temp) {
|
++rtTR;
|
if (rtTR == (results.rend() + 1)) {
|
rtTR--;
|
break;
|
} else {
|
// DBG(" sc is "<< new_confidence << " > " << temp);
|
}
|
temp = rtTR->confidence;
|
}
|
} else {
|
// INFO("topResult is null");
|
}
|
auto itTR(rtTR.base());
|
::FaceSearch::FaceResult t_faceCR;
|
t_faceCR.id = itor->id;
|
t_faceCR.uuid = itor->uuid;
|
t_faceCR.tableName = itor->tableName;
|
t_faceCR.confidence = itor->confidence;
|
DBG("compare results tablename is " << t_faceCR.tableName << " id is " << t_faceCR.uuid << " sc is"
|
<< t_faceCR.confidence);
|
results.insert(itTR, t_faceCR);
|
}
|
|
|
//#todo send message
|
|
return results;
|
}
|
|
//#todo 优化
|
::FaceSearch::FaceResults
|
FaceFeatureSearchServerI::faceSearchTopN(const ::FaceSearch::Data &feature, const ::std::string &info_json,
|
::Ice::Int topN, ::Ice::Float score, const ::Ice::Current &) {
|
ClockTimer clockTimer("faceSearchTopN " + to_string(score) + " :");
|
INFO("faceSearchTopN start");
|
thread::id key = std::this_thread::get_id();
|
::FaceSearch::FaceResults results;
|
FaceResults t_TableCompareResult;
|
AlarmData featureData;
|
featureData.num = topN;
|
featureData.feature.resize(feature.size());
|
memcpy(featureData.feature.data(), feature.data(), feature.size());
|
|
Json::Reader reader;
|
Json::Value value;
|
|
if (reader.parse(info_json, value)) {
|
//#todo
|
m_rwLock.rdlock();
|
std::string feature_base64;
|
feature_base64 = base64.Encode(feature.data(), feature.size());
|
value["FaceFeature"] = feature_base64;
|
DBG("auto &it : m_faceFCMAP start " << m_faceFCMAP.size());
|
//#todo lock
|
for (auto &it : m_faceFCMAP) {
|
auto &t_FaceFC = it.second;
|
auto t_tableInfo = m_tableType[it.first];
|
bool ret = getRet(t_tableInfo.startTime, t_tableInfo.endTime);
|
if (ret) {
|
string t_alarmRet = t_tableInfo.bwType;
|
// bool alarmRet = atoi(t_tableInfo.bwType.c_str());
|
//#todo 非同步库是否需要比较?
|
|
DBG("m_faceFCMAP compare start " << it.first);
|
t_FaceFC->compare(key, &featureData, topN);
|
DBG("m_faceFCMAP compare end " << it.first);
|
|
auto t_results = t_FaceFC->getTopResult(key);
|
for (auto &t_item : t_results) {
|
t_item.tableName = it.first;
|
t_item.alarmRet = t_alarmRet;
|
t_TableCompareResult.push_back(t_item);
|
// DBG("t_results item : uuid is " << t_item.uuid << " confidence " << t_item.confidence << it.first);
|
}
|
} else {
|
INFO("m_faceFCMAP ret is false " << it.first);
|
}
|
}
|
m_rwLock.unlock();
|
DBG("auto &it : m_faceFCMAP end");
|
|
DBG("t_TableCompareResult size" << t_TableCompareResult.size());
|
//sort_all_results
|
for (auto itor = t_TableCompareResult.begin(); itor != t_TableCompareResult.end(); ++itor) {
|
float new_confidence = itor->confidence;
|
auto rtTR = results.rbegin();
|
if (!results.empty()) {
|
auto temp = rtTR->confidence;
|
while (new_confidence > temp) {
|
++rtTR;
|
if (rtTR == (results.rend() + 1)) {
|
rtTR--;
|
break;
|
} else {
|
}
|
temp = rtTR->confidence;
|
}
|
} else {
|
ERR("topResult is null");
|
}
|
auto itTR(rtTR.base());
|
::FaceSearch::FaceResult t_faceCR;
|
t_faceCR.id = itor->id;
|
t_faceCR.uuid = itor->uuid;
|
t_faceCR.tableName = itor->tableName;
|
t_faceCR.confidence = itor->confidence;
|
//#todo url idcard
|
t_faceCR.imgUrl = itor->face_img_url;
|
t_faceCR.idcard = itor->idCard;
|
t_faceCR.alarmRet = itor->alarmRet;
|
DBG("compare results tablename is " << t_faceCR.tableName << " id is " << t_faceCR.uuid << " pic n "
|
<< t_faceCR.idcard << " sc is" << t_faceCR.confidence);
|
results.insert(itTR, t_faceCR);
|
}
|
bool retface = true;
|
// cout << __FUNCTION__ << " -> " << __LINE__ << " -> " << results.size() << endl;
|
//#todo send message
|
if (results.size() > 0) {
|
for (auto &item : results) {
|
//#todo 得分比较,应该在compare中进行
|
if (item.confidence < score) {
|
//#todo test
|
auto str_uuid = value["Id"].asString();
|
value["personIsHub"] = "4";
|
value["likePer"] = 0.0;
|
// DBG(value.toStyledString());
|
cout << __FUNCTION__ << " -> " << __LINE__ << " -> " << "value.toStyledString() "
|
<< value.toStyledString() << endl;
|
retface = pManagerEsDB.insertData("videopersons", "perVideoPicture", value.toStyledString(),
|
str_uuid);
|
break;
|
}
|
value["personId"] = item.uuid.size() > 0 ? item.uuid : "";//关联底库人员id,人脸id
|
|
// string tmp_tableName = item.tableName;
|
// if (tmp_tableName.find("lt_") == 0) {
|
// tmp_tableName = tmp_tableName.insert(tmp_tableName.find("lt_") + 3, "::");
|
// value["BaseName"] = tmp_tableName;//关联底库表名
|
// } else {
|
// value["BaseName"] = item.tableName.size() > 0 ? item.tableName : "";//关联底库表名
|
// }
|
|
value["BaseName"] = item.tableName.size() > 0 ? item.tableName : "";//关联底库表名
|
|
value["likePer"] = item.confidence > 0 ? item.confidence : 0.0;
|
value["personPicUrl"] = item.imgUrl.size() > 0 ? item.imgUrl : "";//diku tupian
|
value["idcard"] = item.idcard.size() > 0 ? item.idcard : "";//diku tupian
|
//如果 alarmRet 不为空把 他的值 放入 personIsHub,否则为4
|
value["personIsHub"] = item.alarmRet.size() > 0 ? item.alarmRet : "4";
|
|
auto str_uuid = value["Id"].asString();
|
// DBG(value.toStyledString());
|
|
cout << __FUNCTION__ << " -> " << __LINE__ << " -> " << "value.toStyledString() "
|
<< value.toStyledString() << "\n score " << score << endl;
|
// DBG("score " << score);
|
retface = pManagerEsDB.insertData("videopersons", "perVideoPicture", value.toStyledString(),
|
str_uuid);
|
break;
|
}
|
} else {
|
auto str_uuid = value["Id"].asString();
|
value["personIsHub"] = "4";
|
value["likePer"] = 0.0;
|
DBG(value.toStyledString());
|
// cout << __FUNCTION__ << " -> " << __LINE__ << " -> " << "value.toStyledString() "
|
// << value.toStyledString() << endl;
|
retface = pManagerEsDB.insertData("videopersons", "perVideoPicture", value.toStyledString(),
|
str_uuid);
|
}
|
if (!retface) {
|
ERR("insert error");
|
} else {
|
cout << __FUNCTION__ << " -> " << __LINE__ << " -> " << "retface " << retface << endl;
|
};
|
} else {
|
ERR("json is error" << info_json);
|
}
|
|
|
|
|
// for (auto &item : t_tables) {
|
// DBG(item);
|
// }
|
return results;
|
}
|
|
bool FaceFeatureSearchServerI::loadFeatureData(FaceFeatureSearchServerI *faceFea) {
|
ErlangTool::map_TabDataCache dataBaseCache = faceFea->m_erlangDbTool.findAllDatabase();
|
if (dataBaseCache.size() < 0 && faceFea->m_retUpdatePthread) {
|
faceFea->m_retUpdatePthread = false;
|
std::thread thd(dataUpdate, faceFea);
|
thd.detach();
|
}
|
auto typeInfoCache = faceFea->m_erlangDbTool.findAllTypeInfo();
|
faceFea->m_tableType.clear();
|
string str_config = faceFea->m_erlangDbTool.getConfigJsonString();
|
|
|
Json::Value t_json;
|
Json::FastWriter writer;
|
Json::Reader reader;
|
|
faceFea->m_rwLock.wrlock();
|
if (reader.parse(str_config, t_json)) {
|
for (auto &item : dataBaseCache) {
|
TableInfo tabInfo;
|
tabInfo.tableName = item.first;
|
tabInfo.startTime = item.second.startTime;
|
tabInfo.endTime = item.second.endTime;
|
// tabInfo.bwType = item.second.bwType = typeInfoCache.find(item.first)->second.bwType;
|
tabInfo.bwType = item.second.bwType;//= typeInfoCache.find(item.first)->second.bwType;
|
tabInfo.createBy = item.second.create_by;
|
|
if ((tabInfo.tableName.find("lt_") == 0) && (tabInfo.createBy != appConfig.getStringProperty("erlNode"))) {
|
continue;
|
}
|
string &tableName = item.second.tableName;
|
faceFea->m_tableType[tableName] = tabInfo;
|
appPref.setIntData(tableName, 0);
|
if (faceFea->m_faceFCMAP.find(tableName) == faceFea->m_faceFCMAP.end()) {
|
faceFea->m_faceFCMAP[tableName] = new FaceDBCompareServer(&(faceFea->m_erlangDbTool));
|
// usleep(1000);
|
}
|
t_json["\"tableName\""] = "\"" + tableName + "\"";
|
std::string str_json = writer.write(t_json);
|
|
str_json.substr(0, str_json.length() - 1);
|
// sleep(1);
|
usleep(1500 * 1000);
|
faceFea->m_faceFCMAP[tableName]->initDB(str_json);
|
DBG("initDB tableName " << tableName);
|
}
|
} else {
|
ERR("json format error :: " << str_config);
|
}
|
|
//#todo get data from sqlite3
|
{
|
//#查询人脸底库列表
|
auto res = faceFea->m_sqliteFaceEncap.getTableInfos();
|
for (auto &item : res) {
|
if (item.tableType == "person") {
|
std::cout << "tableName is " << item.tableName << std::endl;
|
|
{
|
std::string tableName = item.tableName;
|
faceFea->m_tableType[tableName] = item;
|
appPref.setIntData(tableName, 0);
|
if (faceFea->m_faceFCMAP.find(tableName) == faceFea->m_faceFCMAP.end()) {
|
faceFea->m_faceFCMAP[tableName] = new FaceDBCompareServer(&(faceFea->m_sqliteFaceEncap));
|
}
|
|
Json::Value t_json2;
|
t_json2.clear();
|
|
t_json2["\"syncTpye\""] = "local";
|
t_json2["tableName"] = tableName;
|
std::string str_json = writer.write(t_json2);
|
|
str_json.substr(0, str_json.length() - 1);
|
faceFea->m_faceFCMAP[tableName]->initDB(str_json);
|
DBG("initDB tableName " << tableName);
|
}
|
|
}
|
}
|
}
|
faceFea->m_rwLock.unlock();
|
|
INFO("get time");
|
faceFea->m_inTime = getTimeLong();
|
if (faceFea->m_retUpdatePthread) {
|
faceFea->m_retUpdatePthread = false;
|
std::thread thd(dataUpdate, faceFea);
|
|
// faceFea->m_erlangDbTool.test(faceFea, erlangCallBackFunc);
|
INFO("start thread");
|
thd.detach();
|
} else {
|
ERR("m_retUpdatePthread is false ");
|
}
|
|
return false;
|
}
|
|
void FaceFeatureSearchServerI::waitTables(FaceFeatureSearchServerI *faceFea, int loop) {
|
DBG("waitTales");
|
while (t_live_ret) {
|
faceFea->m_rwLock.rdlock();
|
if (faceFea->m_faceFCMAP.size() == 0) {
|
ERR("table size is 0");
|
faceFea->m_rwLock.unlock();
|
return;
|
}
|
bool tmp = true;
|
for (auto &t_face : faceFea->m_faceFCMAP) {
|
auto t_ret = appPref.getIntData(t_face.first);
|
tmp = t_ret & tmp;
|
}
|
if (tmp && faceFea->m_faceFCMAP.size() > 0) {
|
INFO("waitTables ok");
|
faceFea->m_rwLock.unlock();
|
return;
|
} else {
|
ERR("tmp is " << tmp << " faceFea->m_faceFCMAP.size() is " << faceFea->m_faceFCMAP.size());
|
faceFea->m_rwLock.unlock();
|
usleep(1000);
|
// if (loop != -1 && loop-- < 1) {
|
// ERR("return " << loop);
|
// return;
|
// }
|
}
|
}
|
return;
|
}
|
|
|
//void FaceFeatureSearchServerI::erlangCallBackFunc(std::string) {
|
// DBG("erlangCallBackFunc");
|
// pthread_cond_signal(&(func_cond));
|
// pthread_mutex_unlock(&(func_cond_mutex));
|
//}
|
|
void FaceFeatureSearchServerI::dataUpdate(FaceFeatureSearchServerI *faceFea) {
|
long inTime = faceFea->m_inTime;
|
// modify all db ready start update, <10s
|
faceFea->waitTables(faceFea, 100);
|
int loop = 0;
|
long outTime;
|
//update
|
while (t_live_ret) {
|
DBG(" wait lock?");
|
pthread_mutex_lock(&(func_cond_mutex));
|
DBG(" get lock?");
|
pthread_cond_wait(&(func_cond), &(func_cond_mutex));
|
try {
|
// faceFea->m_rwLock.rdlock();
|
// if (faceFea->m_faceFCMAP.size() > 0) {
|
// faceFea->m_rwLock.unlock();
|
// } else {
|
// faceFea->m_rwLock.unlock();
|
// }
|
DBG("update data sleep before ");
|
int sleepTime = appConfig.getIntProperty("FaceSeachSleepTime");
|
sleepTime = sleepTime > 30 ? sleepTime : 30;
|
DBG("sleepTime is " << sleepTime);
|
sleep(30);
|
inTime = outTime;
|
outTime = 0;
|
cout << " loop is " << loop++ << endl;
|
faceFea->loadFeatureData(faceFea);
|
faceFea->waitTables(faceFea, 100000);
|
pthread_mutex_unlock(&func_cond_mutex);
|
} catch (std::exception ex) {
|
ERR(ex.what());
|
}
|
}
|
}
|
|
|
bool FaceFeatureSearchServerI::initErlang(std::string nodeName, std::string cookie) {
|
//#todo
|
// m_erlangDbTool = ErlangTool::ErlangDbTool(nodeName, cookie);
|
return false;
|
}
|