Newer
Older
CasicBioRecNew / device / face / FaceRecogProcess.cpp
#include "FaceRecogProcess.h"

FaceRecogProcess::FaceRecogProcess(QObject *parent) : QThread(parent)
{
    this->working = false;
    this->exit = false;
}

FaceRecogProcess::~FaceRecogProcess()
{
    this->setWorking(false);
}

void FaceRecogProcess::setWorking(bool working)
{
    this->working = working;
}
void FaceRecogProcess::exitThread()
{
    this->exit = true;
}
void FaceRecogProcess::startThread()
{
    this->exit = false;
    this->start();
}

void FaceRecogProcess::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;
        ProMemory::getInstance().clearFaceQueue();
        emit matchFailure();

        this->setWorking(false); // 返回后则线程暂停工作
    }
}

void FaceRecogProcess::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;
        ProMemory::getInstance().clearFaceQueue();
        emit matchFailure();

        this->setWorking(false); // 返回后则暂停工作
    }
}

void FaceRecogProcess::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().recoginzeId == "")
        {
            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 FaceRecogProcess::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;

            // 找到匹配的人脸图像
            // 发送信号, 在主界面上显示
            emit matchSuccess(ffMap.value("person_id").toString(), 1);

            this->afterRecogAction();
            return ;
        }
    }

    this->addOneTryCount();
}

void FaceRecogProcess::afterRecogAction()
{
    ProMemory::getInstance().clearFaceQueue(); // 清理人脸数据栈
    this->setWorking(false); // 找到匹配的人脸之后停止识别线程工作
}