#include "FaceExtractElement.h"
|
#include <basic/util/app/AppPreference.hpp>
|
#include <QtCore/QSharedMemory>
|
#include <QtCore/QString>
|
#include <basic/util/app/AppUtil.h>
|
#include <basic/util/opencv/CvUtil.h>
|
#include <basic/util/app/AppPreference.hpp>
|
//diao用对应es数据封装的类
|
//#include <basic/db/ES/es/ManagerEsDB.h>
|
#include <basic/db/Elasticsearch/EsDBTool.h>
|
#include <QtCore/QJsonDocument>
|
#include <QtCore/QJsonObject>
|
#include <uuid/uuid.h>
|
#include <jsoncpp/json/json.h>
|
#include <basic/util/app/AppConfig.h>
|
|
#define state "state"
|
|
void StringReplace(string &strBase, string strSrc, string strDes) {
|
string::size_type pos = 0;
|
string::size_type srcLen = strSrc.size();
|
string::size_type desLen = strDes.size();
|
pos = strBase.find(strSrc, pos);
|
while ((pos != string::npos)) {
|
strBase.replace(pos, srcLen, strDes);
|
pos = strBase.find(strSrc, (pos + desLen));
|
}
|
}
|
|
FaceExtractElement::FaceExtractElement(std::string shareMemoryName, const SdkRule &rule) :
|
TimerElement(1000), sharedMemory(nullptr), fdfsClient(nullptr),
|
//#todo appPref.setStringData
|
faceExtractRpcClient(appPref.getStringData("faceExte.proxy"), appPref.getStringData("faceExte.ip"),
|
appPref.getIntData("faceExte.port"), "tcp"),
|
// faceExtractRpcClient(/*appPref.getStringData("face.extract.proxy")*/
|
// "faceExtractServer", "", 10008, "tcp"),//人脸特征提取 修改成点对点通讯
|
faceSearchRpcClient(appPref.getStringData("faceSear.proxy"), appPref.getStringData("faceSear.ip"),
|
appPref.getIntData("faceSear.port"), "tcp"),
|
// faceSearchRpcClient("faceCmServer", "", 10004, "tcp")
|
m_sdkRule(rule),
|
m_rpcClient("RtspAnalysServer", "127.0.0.1", appPref.getIntData("RpcVTIMPort"), "tcp") {
|
sharedMemory = new QSharedMemory(QString(shareMemoryName.c_str()));
|
if (!sharedMemory->create(4608 * 2592 * 4)) {
|
sharedMemory->attach();
|
}
|
}
|
|
FaceExtractElement::~FaceExtractElement() {
|
if (sharedMemory) {
|
delete sharedMemory;
|
}
|
}
|
|
void FaceExtractElement::submitFaceExtract(FaceToExtract faceToExtract) {
|
std::lock_guard<std::mutex> lg(imageQueueMutex);
|
if (faceExtractQueue.size() >= VECTOR_MAX) {
|
ERR("FaceExtractElement::submitFaceExtract too fast, imageQueue.size()>=QUEUE_MAX")
|
return;
|
}
|
faceExtractQueue.push_back(faceToExtract);
|
}
|
|
void FaceExtractElement::timerFunc() {
|
// INFO("MYH Run Here");
|
std::vector<FaceToExtract> faceExtractQueueTmp;
|
{
|
std::lock_guard<std::mutex> lg(imageQueueMutex);
|
if (faceExtractQueue.empty()) {
|
ERR("faceExtractQueue.empty ");
|
return;
|
}
|
faceExtractQueueTmp.swap(faceExtractQueue);
|
faceExtractQueue.clear();
|
}
|
try {
|
|
string t_camIdex = getProperty("dev_id") + getProperty("ch_id");
|
float t_com_sc = m_sdkRule.nThreshold == 0 ? 75 : m_sdkRule.nThreshold;
|
|
|
// DBG(" TESTCODE getValue" << t_camIdex << " " << t_com_sc << " " << t_com_sc / 100);
|
|
t_com_sc = t_com_sc / 100;
|
|
for (int i = 0; i < faceExtractQueueTmp.size(); i++) {
|
auto extractServer = faceExtractRpcClient.getServer();
|
if (!extractServer) {
|
ERR("extractServer is null");
|
return;
|
}
|
auto &image = faceExtractQueueTmp[i].image;
|
auto sharedImage = cv::Mat(image.rows, image.cols, CV_8UC3, sharedMemory->data());
|
image.copyTo(sharedImage);
|
|
|
// 上传大图
|
string strBigImgUrl;
|
if (fdfsClient != nullptr && fdfsClient->fastFds != nullptr) {
|
fdfsClient->rwLock.rdlock();
|
std::vector<unsigned char> buffer;
|
CvUtil::cvMat2Buffer(image, buffer);
|
fdfsClient->fastFds->uploadFile(buffer, strBigImgUrl, "jpg");
|
fdfsClient->rwLock.unlock();
|
} else {
|
strBigImgUrl = "";
|
ERR("fdfsClient is nullptr ???");
|
}
|
|
unsigned long size = faceExtractQueueTmp[i].facesPos.size();
|
for (int j = 0; j < size; j++) {
|
auto feature = extractServer->faceExtract(image.cols, image.rows, faceExtractQueueTmp[i].facesPos[j],
|
sharedMemory->key().toStdString());
|
// {
|
// //#todo
|
// string string1(
|
// AppUtil::getTimeString() + "-ff3" + faceExtractQueueTmp[i].scoredRects[j].properties["time"] +
|
// ".jpg");
|
// cv::imwrite(string1, image);
|
// }
|
if (feature.empty()) {
|
// INFO("No Face Find: " << getProperty("imgKey"));
|
continue;
|
}
|
features.clear();
|
features.emplace_back(feature);
|
std::string strImgUrl = "http://";
|
if (fdfsClient != nullptr && fdfsClient->fastFds != nullptr) {
|
fdfsClient->rwLock.rdlock();
|
std::vector<unsigned char> buffer;
|
CvUtil::cvMat2Buffer(faceExtractQueueTmp[i].faceImages[j], buffer);
|
std::string strImgUrlTmp = "";
|
fdfsClient->fastFds->uploadFile(buffer, strImgUrlTmp, "jpg");
|
// strImgUrl.append(fdfsClient->fastFds->getIp() + "/" + strImgUrlTmp);
|
// DBG("strImgUrlTmp=" << strImgUrlTmp);
|
strImgUrl.clear();
|
strImgUrl = strImgUrlTmp;
|
// strImgUrl.append("/").append(strImgUrlTmp);
|
fdfsClient->rwLock.unlock();
|
} else {
|
strImgUrl = "";
|
ERR("fdfsClient is nullptr ???");
|
}
|
InsertToESDB(faceExtractQueueTmp, t_com_sc, i, j, feature, strImgUrl, strBigImgUrl);
|
|
}
|
}
|
} catch (std::exception &e) {
|
ERR(e.what())
|
}
|
if (!features.empty())fireConnectors();
|
}
|
|
void FaceExtractElement::InsertToESDB(const vector<FaceToExtract> &faceExtractQueueTmp, float t_com_sc, int i, int j,
|
FaceDetect::Data &feature, string &strImgUrl, string &strBigImgUrl) {
|
//拼接json
|
string str_uuid;
|
uuid_t t_uuid;
|
char str[36];
|
uuid_generate(t_uuid);
|
uuid_unparse(t_uuid, str);
|
str_uuid = str;
|
|
Json::Value t_json;
|
t_json["Id"] = str_uuid; //主键
|
|
string feature_base64;
|
feature_base64 = base64.Encode(feature.data(), feature.size());
|
|
//#在对比中添加特征值
|
t_json["FaceFeature"] = feature_base64;
|
t_json["personId"] = "";//关联底库人员id,人脸id
|
t_json["BaseName"] = "";//关联底库表名
|
//#end
|
// t_json["likePer"] = faceExtractQueueTmp[i].scoredRects[j].score;//人员相似度 Score
|
t_json["likeDate"] = AppUtil::getTimeSecString();//"2018-01-01 01:01:01";//比较时间
|
|
t_json["picName"] = "";
|
|
|
t_json["personPicUrl"] = "";//人员图片 store
|
t_json["picAddress"] = getProperty("str_addr");//抓拍地址
|
DBG("picAddress=" << t_json["picAddress"]);
|
t_json["picMaxUrl"] = strBigImgUrl;//大图路径
|
t_json["picLocalUrl"] = "";//本地路径
|
t_json["picSmUrl"] = strImgUrl;//人员抓小图
|
//#todo
|
t_json["picDate"] = faceExtractQueueTmp[i].scoredRects[j].properties["time"];
|
DBG("picDate=" << t_json["picDate"].asString());
|
// DBG("timeC ::::B" << t_json["picDate"m_bIsMask].asString());
|
// t_json["picDate"] = AppUtil::getTimeSecString();
|
|
t_json["content"] = "";
|
//t_json["viType"] = "2";//只有4种类型 1:personface 2:personbody 3:car 4:bicycle 5:none 未知类型
|
t_json["sdkType"] = to_string(
|
m_sdkRule.nSdkType);//只有4种类型 1:personface 2:personbody 3:car 4:bicycle 5:none 未知类型
|
t_json["personIsHub"] = "4";//1: 报警 2: 可疑 3: 安全 4: 未知
|
|
|
t_json["cluster_id"] = appPref.getStringData("clusterID");
|
t_json["ack_alarm"] = "0";
|
|
//faceExtractElement.setProperty("dev_id", str_device_id);
|
//faceExtractElement.setProperty("cg_id", str_ch_id);
|
t_json["videoNum"] = getProperty("dev_id");//Video设备编号//getProperty("path");//Vide编号 外键
|
t_json["videoReqNum"] = getProperty("dev_id");//Video设备编号
|
t_json["ChannlId"] = getProperty("ch_id");//通道id
|
t_json["isDelete"] = "1";//默认1 ,0无效 1有效
|
|
//人脸属性
|
t_json["Age"] = atoi(
|
faceExtractQueueTmp[i].scoredRects[j].properties["age"].c_str());//检测的年龄 应该为空 无检测结果
|
|
//#todo 优化 get vector<string> from json
|
t_json["Gender"] = faceExtractQueueTmp[i].scoredRects[j].properties["gender"];//检测的性别 为空 无检测结果
|
switch (atoi(faceExtractQueueTmp[i].scoredRects[j].properties["gender"].c_str())) {
|
case 0:
|
t_json["Gender"] = "女";
|
break;
|
case 1:
|
t_json["Gender"] = "男";
|
break;
|
}
|
|
t_json["BeautyLevel"] = faceExtractQueueTmp[i].scoredRects[j].properties["beauty"];//检测的美化水平 为空 无检测结果
|
t_json["SimleLevel"] = faceExtractQueueTmp[i].scoredRects[j].properties["smile"];//检测的微笑水平 为空 无检测结果
|
t_json["Race"] = "";//检测的种族 应该为空 无检测结果
|
t_json["videoIp"] = getProperty("local_ip");//当前服务器IP地址
|
|
t_json["cluster_id"] = appConfig.getStringProperty("clusterID");//集群id
|
t_json["ack_alarm"] = "0";//ack_alarm是否报警
|
|
//#todo 优化 get vector<string> from json
|
switch (atoi(faceExtractQueueTmp[i].scoredRects[j].properties["race"].c_str())) {
|
case 1:
|
t_json["Race"] = "白人";
|
break;
|
case 2:
|
t_json["Race"] = "黄人";
|
break;
|
case 3:
|
t_json["Race"] = "黑人";
|
break;
|
}
|
|
// DBG(t_json.toStyledString());
|
|
t_json["indeviceid"] = appPref.getStringData("fxDevID");
|
t_json["indevicename"] = appPref.getStringData("fxDevNAME");
|
|
string strImageKey = faceExtractQueueTmp[i].scoredRects[j].properties["imgKey"];
|
INFO("SaveImageKey To ES: " << strImageKey);
|
t_json["imgKey"] = strImageKey;
|
|
try {
|
auto server = m_rpcClient.getServer();
|
if (!server) {
|
ERR("server is null");
|
//return;
|
}
|
INFO("Record Video " << strImageKey);
|
server->recordVideo(strImageKey);
|
} catch (exception &e) {
|
ERR("Record Video Err: " << strImageKey << " Message: " << e.what());
|
//return;
|
}
|
auto faceSearchServer = faceSearchRpcClient.getServer();
|
if (!faceSearchServer) {
|
ERR("faceSearchServer is null");
|
EsDBTool pManagerEsDB(appPref.getStringData("ipAdd"), appPref.getIntData("ipPort"));
|
bool retface = false;
|
retface = pManagerEsDB.insertData("videopersons", "perVideoPicture", t_json.toStyledString(),
|
str_uuid);
|
// if (retface) {
|
// INFO("facedb success");
|
// } else {
|
// ERR("facedb fail");
|
// }
|
} else {
|
INFO("send faceSearchTopN ");
|
auto faceSearchResults = faceSearchServer->faceSearchTopN(feature, t_json.toStyledString(), 2,
|
t_com_sc);
|
}
|
}
|
|
std::vector<::FaceDetect::Data> FaceExtractElement::getFeatures() const {
|
return features;
|
}
|