#include "FaceDetectRecogProcess.h" FaceDetectRecogProcess::FaceDetectRecogProcess(QObject *parent) : QThread(parent) { this->working = false; this->exit = false; } FaceDetectRecogProcess::~FaceDetectRecogProcess() { this->setWorking(false); } void FaceDetectRecogProcess::setWorking(bool working) { this->working = working; } void FaceDetectRecogProcess::exitThread() { this->exit = true; } void FaceDetectRecogProcess::startThread() { this->exit = false; this->start(); } void FaceDetectRecogProcess::addOneTryCount() { LOG(DEBUG) << QString("[addOneTryCount]已尝试次数[%1]").arg(CasicFaceRecState::getInstance().tryCount).toStdString(); if (CasicFaceRecState::getInstance().tryCount < SettingConfig::getInstance().MAX_FACE_TRY_COUNT) { CasicFaceRecState::getInstance().state = CasicFaceRecState::FaceRecStateName::REC_NOT_START; } else { CasicFaceRecState::getInstance().tryCount = 0; CasicFaceRecState::getInstance().noFaceCount = 0; emit matchFailure(); this->setWorking(false); // 返回后则线程暂停工作 } } void FaceDetectRecogProcess::addOneNoFaceCount() { CasicFaceRecState::getInstance().noFaceCount++; CasicFaceRecState::getInstance().state = CasicFaceRecState::FaceRecStateName::REC_NOT_START; if (CasicFaceRecState::getInstance().noFaceCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) { CasicFaceRecState::getInstance().noFaceCount = 0; emit matchFailure(); this->setWorking(false); // 返回后则暂停工作 } } void FaceDetectRecogProcess::run() { while (exit == false) { if (this->working == false) { this->msleep(100); // 100ms后再判断 continue; } // 图像栈中没有图像则直接返回 if (ProMemory::getInstance().isFaceQueueEmpty() == true) { addOneNoFaceCount(); // 连续没找到脸的次数+1;注册过程有调用opencv的分类器, 没有符合要求脸的图像不入栈 LOG(TRACE) << QString("[CasicFaceRecognize][%1] 人脸图像栈空, 暂停200ms").arg(CasicFaceRecState::getInstance().noFaceCount).toStdString(); this->msleep(200); // 200ms后再判断 continue; } // 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 if (CasicFaceRecState::getInstance().state != CasicFaceRecState::FaceRecStateName::REC_NOT_START) { LOG(DEBUG) << QString("[CasicFaceRecognize] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicFaceRecState::getInstance().state).toStdString(); this->msleep(200); // 200ms后再判断 continue; } // 取出人脸图像栈中的一条数据 CasicFaceInfo faceInfo = ProMemory::getInstance().popCasicFace(); // 调用人脸检测算法 faceInfo = casic::face::CasicFaceInterface::getInstance().faceDetect(faceInfo.matData); // 没有找到人脸则返回 if (faceInfo.hasFace == false) { // 表示本次识别结束, 可以开始下一次识别过程 addOneNoFaceCount(); // 连续没找到脸的次数+1;注册过程有多调用opencv的分类器, 没有符合要求脸的图像不入栈 LOG(DEBUG) << QString("[CasicFaceRecognize] 没有找到人脸, 暂停200ms。重置识别状态为REC_NOT_START[%1]").arg(CasicFaceRecState::getInstance().noFaceCount).toStdString(); this->msleep(200); // 200ms后再判断 continue; } // 找到人脸则开始一次识别 if (CasicFaceRecState::getInstance().recoginzeId == "0") { CasicFaceRecState::getInstance().initRecognize(); } CasicFaceRecState::getInstance().faceInfo = &faceInfo; CasicFaceRecState::getInstance().tryCount++; // 尝试识别次数+1 CasicFaceRecState::getInstance().noFaceCount = 0; // 找到脸 则将连续没找到脸的次数清零 // 开始人脸活体检测, 提高活体检测的阈值到0.3/0.6 casic::face::CasicFaceInterface::getInstance().setAntiThreshold(0.3, 0.3); faceInfo = casic::face::CasicFaceInterface::getInstance().faceAntiSpoofing(faceInfo); // 活体检测判断为假脸 if (faceInfo.antiStatus != seeta::FaceAntiSpoofing::Status::REAL) { // 表示本次识别结束, 可以开始下一次识别过程 LOG(DEBUG) << QString("[CasicFaceRecognize] 人脸活体检测未通过, 暂停200ms。[%1]").arg("CasicFaceRecState::getInstance().toString()").toStdString(); addOneTryCount(); // 判断是否超过次数, 重置识别状态 this->msleep(200); // 200ms后再判断 continue; } // 设置识别状态值=通过活体检测 CasicFaceRecState::getInstance().state = CasicFaceRecState::FaceRecStateName::REC_ANTI_SPOOFING; // 调用算法提取特征值, 1024个字节的float数组 faceInfo = casic::face::CasicFaceInterface::getInstance().faceFeatureExtract(faceInfo); // 设置识别状态值=特征值提取 CasicFaceRecState::getInstance().state = CasicFaceRecState::FaceRecStateName::REC_FEATURE_EXTRACT; CasicFaceRecState::getInstance().faceInfo = &faceInfo; LOG(DEBUG) << QString("[CasicFaceRecognize] 特征提取成功[%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); // 特征值提取成功的人脸 与人脸库中的人脸进行比较 compareFaceInCollection(); } } void FaceDetectRecogProcess::compareFaceInCollection() { ProMemory::getInstance().clearFaceQueue(); // 特征值提取成功, 开始在库中匹配, 清除人脸图像栈 QVector<QVariantMap> faceFeatures = ProMemory::getInstance().getFaceFeatures(); for (int i = 0; i < faceFeatures.size(); i++) { QVariantMap ffMap = faceFeatures.at(i); QByteArray ffByteArr = ffMap.value("face_code").toByteArray(); float ffArr[1024]; for (int i = 0; i < 1024; i++) { QByteArray tempBa; tempBa.append(ffByteArr.at(i*4)).append(ffByteArr.at(i*4 + 1)).append(ffByteArr.at(i*4 + 2)).append(ffByteArr.at(i*4 + 3)); ffArr[i] = ByteUtil::binToFloat(tempBa); } float sim = casic::face::CasicFaceInterface::getInstance().faceSimCalculate(CasicFaceRecState::getInstance().faceInfo->feature, ffArr); LOG(DEBUG) << QString("[compareFaceInCollection] 特征值比对结果[%1]").arg(sim).toStdString(); if (sim > 0.62) { CasicFaceRecState::getInstance().faceInfo->sim = sim; CasicFaceRecState::getInstance().timeStampSucc = QDateTime::currentMSecsSinceEpoch(); CasicFaceRecState::getInstance().recogTimeLast = (float) ((CasicFaceRecState::getInstance().timeStampSucc - CasicFaceRecState::getInstance().timeStamp) / 1000.0); CasicFaceRecState::getInstance().state = CasicFaceRecState::FaceRecStateName::REC_SEARCH_SUCC; // 找到匹配的人脸图像 this->afterRecogAction(ffMap.value("person_id").toString()); this->setWorking(false); // 找到匹配的人脸之后停止识别线程工作 return ; } } this->addOneTryCount(); } void FaceDetectRecogProcess::afterRecogAction(QString personId) { ProMemory::getInstance().clearFaceQueue(); // 清理人脸数据栈 LOG(DEBUG) << QString("[FaceDetectRecogProcess] 识别成功 [%1]").arg(CasicFaceRecState::getInstance().toString()).toStdString(); // 识别记录存入数据库 RecognitionRecordDao recDao; QVariantMap record; record.insert("person_id", personId); record.insert("date_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")); record.insert("type", "1"); record.insert("debug_info", CasicFaceRecState::getInstance().toString()); recDao.save(record); // 发送信号, 在主界面上显示 emit matchSuccess(personId); }