Newer
Older
CasicBioRecNew / device / iris / IrisRecogProcess.cpp
Tan Yue on 30 Jun 2022 7 KB 20220630 可以识别的1.0版本
#include "IrisRecogProcess.h"

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

    // 连接算法服务
    clientUtil = new SocketClientUtil(this);
    clientUtil->connect("127.0.0.1", 2015);

    // 调用socket发送消息
    connect(this, &IrisRecogProcess::sendDataToExract, clientUtil, &SocketClientUtil::sendData);
}

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

void IrisRecogProcess::setWorking(bool working)
{
    this->working = working;
}

void IrisRecogProcess::exitThread()
{
    this->exit = true;
}

void IrisRecogProcess::run()
{
    while (exit == false)
    {
        // 如果工作标志位为否, 则跳出
        if (this->working == false)
        {
            this->msleep(200); // 200ms后再判断
            continue;
        }

        // 图像栈中没有图像则直接返回
        if (ProMemory::getInstance().isIrisQueueEmpty() == true)
        {
            LOG(DEBUG) << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms").toStdString();
            this->msleep(200); // 200ms后再判断
            continue;
        }

        // 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束
//        if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START)
//        {
//            LOG(DEBUG) << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state).toStdString();

//            this->msleep(200); // 200ms后再判断
//            continue;
//        }
        LOG(DEBUG) << QString("[IrisRecogProcess]准备取出虹膜图像[%1]").arg(ProMemory::getInstance().isIrisQueueEmpty()).toStdString();

        // 取出虹膜图像栈中的一条数据
        CasicIrisInfo irisInfo = ProMemory::getInstance().popCasicIris();

        LOG(DEBUG) << QString("[IrisRecogProcess]取出虹膜图像").toStdString();

        // 调用找眼分类器算法
        casic::iris::CasicIrisInterface::getInstance().setMinEyeSize(360);
        irisInfo = casic::iris::CasicIrisInterface::getInstance().findEye(irisInfo);

        // 没有找到眼睛则返回
        if (irisInfo.hasEye == false)
        {
            // 表示本次识别结束, 可以开始下一次识别过程
            LOG(DEBUG) << QString("[IrisRecogProcess] 分类器没有找到眼睛,暂停200ms[%1]").arg(CasicIrisRecState::getInstance().noEyeCount).toStdString();

            addOneNoEyeCount();
            this->msleep(200); // 200ms后再判断
            continue;
        }

        LOG(DEBUG) << QString("[IrisRecogProcess]找到眼睛调用远程算法进行识别").toStdString();

        // 找到眼睛则开始质量评估和编码
        // 调用远程算法进行编码
        if (CasicIrisRecState::getInstance().recoginzeId == "0")
        {
            // 第一次找到眼则 虹膜识别状态初始化
            CasicIrisRecState::getInstance().initRecognize();
        }

        CasicIrisRecState::getInstance().noEyeCount = 0; // 持续未找到眼的次数清零
        CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FIND_EYE;
        CasicIrisRecState::getInstance().irisInfo->hasEye = irisInfo.hasEye;
        CasicIrisRecState::getInstance().irisInfo->leftOrRight = irisInfo.leftOrRight;
        CasicIrisRecState::getInstance().irisInfo->eyeRect = irisInfo.eyeRect;
        CasicIrisRecState::getInstance().irisInfo->matData = irisInfo.matData;
        CasicIrisRecState::getInstance().irisInfo->data = ImageUtil::MatImageToQImage(irisInfo.matData);

        QElapsedTimer timer;
        timer.start();

        QByteArray data((char*)irisInfo.matData.data, SettingConfig::getInstance().IRIS_WIDTH * SettingConfig::getInstance().IRIS_HEIGHT);
        data.prepend("[-m]"); // 识别

        // 发送TCP消息去匹配
        emit sendDataToExract(data);

        // 状态修改为特征提取
        CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT;

        QTimer toTimer;
        QEventLoop loop;
        toTimer.singleShot(3000, &loop, &QEventLoop::quit);
        connect(clientUtil, &SocketClientUtil::responseReaded, &loop, &QEventLoop::quit);
        loop.exec();

        QByteArray matchResponse = clientUtil->getResponse();

        LOG(INFO) << QString("算法匹配结果").toStdString() << matchResponse.toStdString();

        // 算法调用返回成功
        if (matchResponse.size() > 0)
        {
            QString response = matchResponse.mid(5, matchResponse.size() - 6);
            QStringList messList = response.split(";");
            QString code = messList.at(0);
            if (code.toInt() == 0)
            {
                QString personId = messList.at(1);
                CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_SEARCH_SUCC;

                LOG(INFO) << QString("匹配成功[tm: %1 ms][id: %2]").arg(timer.elapsed()).arg(personId).toStdString();

                // 保存图像文件
                cv::imwrite(QString("D:\\irisLogs\\%1-%2.bmp").arg(QDateTime::currentDateTime().toString("HHmmsszzz")).arg(irisInfo.leftOrRight).toStdString(), irisInfo.matData);

                CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START;
                emit findMatchedIris(personId, 2);
                this->afterRecogAction();
            } else if (code.toInt() == -200)
            {
                // 匹配失败
                LOG(INFO) << QString("匹配失败: ").toStdString() << matchResponse.toStdString();

                // 匹配失败则尝试次数+1
                addOneTryCount();
            } else if (code.toInt() == -100)
            {
                // 编码失败
                LOG(INFO) << QString("编码失败: ").toStdString() << matchResponse.toStdString();

                // 编码失败则尝试次数+1
                addOneTryCount();
            }
        } else
        {
            // 超时返回则尝试次数+1
            addOneTryCount();
        }
    }
}

void IrisRecogProcess::afterRecogAction()
{
    this->setWorking(false);

    ProMemory::getInstance().clearIrisQueue(); // 清理虹膜数据栈
}

void IrisRecogProcess::addOneTryCount()
{
    CasicIrisRecState::getInstance().tryCount++;
    LOG(DEBUG) << QString("[CasicIrisRecogProcess]已尝试次数[%1]").arg(CasicIrisRecState::getInstance().tryCount).toStdString();

    CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START;
    if (CasicIrisRecState::getInstance().tryCount >= SettingConfig::getInstance().MAX_IRIS_TRY_COUNT)
    {
        CasicIrisRecState::getInstance().noEyeCount = 0;
        CasicIrisRecState::getInstance().tryCount = 0;

        this->setWorking(false);
//        ProMemory::getInstance().irisCam->stopCapture();
        ProMemory::getInstance().clearIrisQueue();
        emit failedMatchedIris();
    }
}
void IrisRecogProcess::addOneNoEyeCount()
{
    CasicIrisRecState::getInstance().noEyeCount++;
    CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_NOT_START;
    if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_EYE_NOT_FOUND_COUNT)
    {
        CasicIrisRecState::getInstance().noEyeCount = 0;

        this->setWorking(false);
//        ProMemory::getInstance().irisCam->stopCapture();
        ProMemory::getInstance().clearIrisQueue();
        emit failedMatchedIris();
    }
}