#ifdef _MSC_VER #pragma execution_character_set("utf-8") // Qt VS 中文兼容(UTF-8) #endif #include "IrisRecogProcess.h" IrisRecogProcess::IrisRecogProcess(QObject *parent) : QThread(parent) { this->working = false; this->exit = false; // 连接算法服务 clientUtil = new SocketClientUtil(this); clientUtil->connect("192.168.83.223", 50007); // 调用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(THREAD_MSLEEP); // 200ms后再判断 continue; } // 1. 图像栈中没有图像则直接返回 if (ProMemory::getInstance().isIrisQueueEmpty() == true) { qDebug() << QString("[IrisRecogProcess] 虹膜图像栈空, 暂停200ms"); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } // 2. 识别状态不等于未开始, 表示已经进入识别程序了, 后续不再执行, 等待本次识别过程结束 if (CasicIrisRecState::getInstance().state != CasicIrisRecState::IrisRecStateName::REC_NOT_START) { qDebug() << QString("[IrisRecogProcess] 已在一次识别过程中, 暂停200ms。当前状态为: %1").arg(CasicIrisRecState::getInstance().state); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } // 3. 取出虹膜图像栈中的一条数据 CasicIrisInfo irisInfo = ProMemory::getInstance().popCasicIris(); // 4. 调用找眼分类器算法 casic::iris::CasicIrisInterface::getInstance().setMinEyeSize(SettingConfig::getInstance().MIN_EYE_SIZE); irisInfo = casic::iris::CasicIrisInterface::getInstance().findAndCutEye(irisInfo); // 4.1 没有找到眼睛则返回 if (irisInfo.hasEye == false) { // 表示本次识别结束, 可以开始下一次识别过程 qDebug() << QString("[IrisRecogProcess] 分类器没有找到眼睛,暂停200ms[%1]").arg(CasicIrisRecState::getInstance().noEyeCount); addOneNoEyeCount(); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } // 4.2 找到眼睛则开始识别 // 发送信号更新界面 emit startIdentifyIris(); // 调用远程算法进行编码 if (CasicIrisRecState::getInstance().recoginzeId == "0") { // 第一次找到眼则 虹膜识别状态初始化 CasicIrisRecState::getInstance().initRecognize(); } CasicIrisRecState::getInstance().noEyeCount = 0; // 持续未找到眼的次数清零 CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FIND_EYE; QElapsedTimer timer; timer.start(); // 进行预处理 转换成 320 * 240 的三通道图像 送去压缩 cv::Mat segMat; // 图像转换为RGB的彩色图像 cv::cvtColor(irisInfo.matData, segMat, cv::COLOR_GRAY2RGB); // 缩放到320 * 240 cv::resize(segMat, segMat, cv::Size(SettingConfig::getInstance().IRIS_WIDTH * 0.5, SettingConfig::getInstance().IRIS_HEIGHT * 0.5)); // std::string filename = QString("%1\\%2\\%3-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); // cv::imwrite(filename, segMat); // irisInfo = casic::iris::CasicIrisInterface::getInstance().irisPreProcess(irisInfo); QByteArray data((char*)segMat.data, SettingConfig::getInstance().IRIS_WIDTH * 0.5 * SettingConfig::getInstance().IRIS_HEIGHT * 0.5 * 3); // 发送TCP消息去匹配 emit sendDataToExract(data); // 等待接收算法返回的结果 QTimer toTimer; QEventLoop loop; toTimer.singleShot(3000, &loop, &QEventLoop::quit); // 等待3秒后退出等待 connect(clientUtil, &SocketClientUtil::responseReaded, &loop, &QEventLoop::quit); loop.exec(); if (clientUtil->getResponse().size() < SettingConfig::getInstance().IRIS_WIDTH * 0.5 * SettingConfig::getInstance().IRIS_HEIGHT * 0.5 * 3) { addOneTryCount(); qDebug() << QString("算法分割图像失败,暂停200ms[%1 ms]").arg(timer.elapsed()); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } char recvPupil[320 * 240 * 1]; char recvMask[320 * 240 * 1]; char recvIris[320 * 240 * 1]; memset(recvPupil, 0, sizeof(recvPupil)); memset(recvMask, 0, sizeof(recvMask)); memset(recvIris, 0, sizeof(recvIris)); for (int i = 0; i < clientUtil->getResponse().size(); i++) { if (i < 320 * 240) recvPupil[i] = clientUtil->getResponse().at(i); else if (i >= 320 * 240 && i < 2 * 320 * 240) recvMask[i - 320 * 240] = clientUtil->getResponse().at(i); else recvIris[i - 2 * 320 * 240] = clientUtil->getResponse().at(i); } // 成功接收后清除缓存区 clientUtil->resetRecvBuffer(); cv::Mat pupil(240, 320, CV_8UC1, recvPupil); cv::Mat mask(240, 320, CV_8UC1, recvMask); cv::Mat iris(240, 320, CV_8UC1, recvIris); irisInfo.segResult.innerMask = pupil; irisInfo.segResult.irisMask = mask; irisInfo.segResult.outerCircle = iris; /* std::string pupilSeg = QString("%1\\%2\\%3-pupil-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); std::string maskSeg = QString("%1\\%2\\%3-mask-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); std::string irisSeg = QString("%1\\%2\\%3-iris-seg.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(pupilSeg, pupil); cv::imwrite(maskSeg, mask); cv::imwrite(irisSeg, iris); */ qDebug() << QString("算法分割图像成功[%1 ms]").arg(timer.elapsed()); // 分割后的后处理 if (cv::countNonZero(mask) == 0 || cv::countNonZero(pupil) == 0|| cv::countNonZero(iris) == 0) { qDebug() << "算法分割图像失败,暂停200ms"; addOneTryCount(); this->msleep(THREAD_MSLEEP); // 200ms后再判断 continue; } // 状态修改为特征提取 CasicIrisRecState::getInstance().state = CasicIrisRecState::IrisRecStateName::REC_FEATURE_EXTRACT; timer.restart(); irisInfo = casic::iris::CasicIrisInterface::getInstance().irisEncode(irisInfo); std::string codeFilename = QString("%1\\%2\\%3-code.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); std::string maskFilename = QString("%1\\%2\\%3-mask.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).toStdString(); cv::imwrite(codeFilename, irisInfo.irisCode); cv::imwrite(maskFilename, irisInfo.maskNorm); qDebug() << QString("虹膜图像编码成功[%1 ms]").arg(timer.elapsed()); // 开始匹配 for (int i = 0; i < ProMemory::getInstance().getIrisFeatures().size(); i++) { CasicIrisFeature feature = ProMemory::getInstance().getIrisFeatures().at(i); float score = casic::iris::CasicIrisInterface::getInstance().calculateMatchScore(feature, irisInfo); // SpeakerUtil::getInstance().speak(QString::number(score)); cv::imwrite(QString("%1\\%2\\%3-%4.bmp").arg("d:\\irisLogs").arg(QDate::currentDate().toString("yyyyMMdd")).arg(QTime::currentTime().toString("HHmmss")).arg(score).toStdString(), irisInfo.matData); if (score <= 0.32) { CasicIrisRecState::getInstance().state = CasicIrisRecState::REC_SEARCH_SUCC; CasicIrisRecState::getInstance().matchedId = feature.personId; break ; } } if (CasicIrisRecState::getInstance().state == CasicIrisRecState::REC_SEARCH_SUCC) { // 找到匹配结果 emit findMatchedIris(CasicIrisRecState::getInstance().matchedId); ProMemory::getInstance().irisCam->stopCapture(); ProMemory::getInstance().clearIrisQueue(); this->setWorking(false); } else { // 没有匹配上 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(); // 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() { if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_IDENTIFYING) { CasicIrisRecState::getInstance().noEyeCount++; // 如果在识别中 则超过一定次数后返回识别失败 if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_EYE_NOT_FOUND_COUNT) { // 发送信号识别失败 emit failedMatchedIris(); CasicIrisRecState::getInstance().noEyeCount = 0; // 识别失败时暂停工作 待返回识别界面时再开始工作和拍图 this->setWorking(false); ProMemory::getInstance().irisCam->stopCapture(); ProMemory::getInstance().clearIrisQueue(); } } else if (ProMemory::getInstance().appState == AppConstants::ApplicationState::STATE_WORKING) { CasicIrisRecState::getInstance().noEyeCount++; // 如果在工作状态 则超过一定次数后返回待机 if (CasicIrisRecState::getInstance().noEyeCount >= SettingConfig::getInstance().MAX_FACE_NOT_FOUND_COUNT) { // 发送信号待机 emit backToLockScreen(); CasicIrisRecState::getInstance().noEyeCount = 0; // 待机界面还在拍图和工作 ProMemory::getInstance().clearIrisQueue(); } } else { // 待机界面 不做处理 等待找到眼 } }