温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Qt怎么实现人脸识别服务端

发布时间:2021-12-15 10:13:46 来源:亿速云 阅读:165 作者:iii 栏目:互联网科技

这篇文章主要介绍“Qt怎么实现人脸识别服务端”,在日常操作中,相信很多人在Qt怎么实现人脸识别服务端问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Qt怎么实现人脸识别服务端”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、前言

自定义人脸识别协议采用的是tcp通信协议,其实也可以改成http协议,这也是大部分厂家的做法,毕竟现在http post非常流行,通用性好,返回个json数据非常规范,本程序目前采用的tcp协议是为了兼容以前的旧的系统,毕竟之前的系统都是按照那个格式定义的,推翻重来那之前写过的很多设备的程序都需要更改,一个人肯定忙不过来,而且之前的程序也是经过大量的现场应用检验过的,非常稳定,一旦改动程序的话有需要很长时间的磨合测试。

自定义人脸识别协议功能:

  1. 离线使用,同时支持百度的离线包和嵌入式linux人脸识别静态库。

  2. 支持多个连接并发,自动排队处理,返回的时候带上唯一标识区分。

  3. 传入单张图片返回人脸区域。

  4. 传入单张图片返回人脸特征值。

  5. 传入单张图片或者多张图片返回是否是活体。

  6. 传入两张图片返回比对结果。

  7. 传入两个特征值返回比对结果。

  8. 传入单张图片添加人脸。

  9. 指定唯一标识符删除人脸。

  10. 传入单张照片返回相似度最大的人脸信息。

  11. 修改人脸服务的配置参数比如是否快速查找、人脸占比等。

二、功能特点

  1. 支持的功能包括人脸识别、人脸比对、人脸搜索、活体检测等。

  2. 在线版还支持身份证、驾驶证、行驶证、银行卡等识别。

  3. 在线版的协议支持百度、旷视,离线版的支持百度,可定制。

  4. 除了支持X86架构,还支持嵌入式linux比如contex-A9、树莓派等。

  5. 每个功能的执行除了返回结果还返回执行用时时间。

  6. 多线程处理,通过type控制当前处理类型。

  7. 支持单张图片检索相似度最高的图片。

  8. 支持指定目录图片用来生成人脸特征值文件。

  9. 可设置等待处理图片队列中的数量。

  10. 每次执行都有成功或者失败的信号返回。

  11. 人脸搜索的返回结果包含了原图+最大相似度图+相似度等。

  12. 人脸比对同时支持两张图片和两个特征值比对。

  13. 相关功能自定义一套协议用于客户端和服务端,可以通过TCP通信进行交互。

  14. 自定义人脸识别协议非常适用于中心一台服务器,现场若干设备请求的场景。

  15. 每个模块全部是独立的一个类,代码整洁、注释完善。

三、效果图

Qt怎么实现人脸识别服务端

四、核心代码

void FaceSdkSocket::checkData()
{
    QMutexLocker locker(&mutex);
    QDomDocument dom;
    if (!DeviceFun::getReceiveXmlData(buffer, dom, "IFACE:", 10)) {
        return;
    }

    //逐个取出节点判断数据
    emit receiveData(clientIP, dom.toString());
    QDomElement element = dom.documentElement();
    if (element.tagName() == "FaceClient") {
        QString deviceIP = element.attribute("DeviceIP");
        QDomNode childNode = element.firstChild();
        QString name = childNode.nodeName();
        QString value = element.text();
        //qDebug() << TIMEMS << name << value;

        if (name == "DeviceHeart") {
            sendOk();
            emit receiveAnaly(deviceIP, "设备心跳");
        } else if (name == "FindFace") {
            element = childNode.toElement();
            value = element.text();
            if (value.length() == 0) {
                return;
            }

            //用连接的描述符加上用户传入的描述符组合,方便接收处判断发送给那个连接
            QString faceID = element.attribute("FaceID");
            QString flag = QString("%1_%2").arg(this->socketDescriptor()).arg(faceID);
            QImage image = DeviceFun::getImage(value);
            checkImage(image);
            emit receiveAnaly(deviceIP, "请求人脸区域");

            //发送到人脸识别线程处理
#ifdef facelocal
            FaceLocalBaiDu::Instance()->setType(0);
            FaceLocalBaiDu::Instance()->append(flag, image);
#elif facearm
            FaceLocalArm::Instance()->setType(0);
            FaceLocalArm::Instance()->append(flag, image);
#endif
        } else if (name == "FindFeature") {
            element = childNode.toElement();
            value = element.text();
            if (value.length() == 0) {
                return;
            }

            //用连接的描述符加上用户传入的描述符组合,方便接收处判断发送给那个连接
            QString faceID = element.attribute("FaceID");
            QString flag = QString("%1_%2").arg(this->socketDescriptor()).arg(faceID);
            QImage image = DeviceFun::getImage(value);
            checkImage(image);
            emit receiveAnaly(deviceIP, "请求人脸特征");

            //发送到人脸识别线程处理
#ifdef facelocal
            FaceLocalBaiDu::Instance()->setType(1);
            FaceLocalBaiDu::Instance()->append(flag, image);
#elif facearm
            FaceLocalArm::Instance()->setType(1);
            FaceLocalArm::Instance()->append(flag, image);
#endif
        } else if (name == "FindLive") {
            element = childNode.toElement();
            value = element.text();
            if (value.length() == 0) {
                return;
            }

            //用连接的描述符加上用户传入的描述符组合,方便接收处判断发送给那个连接
            QString faceID = element.attribute("FaceID");
            QString flag = QString("%1_%2").arg(this->socketDescriptor()).arg(faceID);
            QImage image = DeviceFun::getImage(value);
            checkImage(image);
            emit receiveAnaly(deviceIP, "请求活体检测");

            //发送到人脸识别线程处理
#ifdef facelocal
            FaceLocalBaiDu::Instance()->setType(5);
            FaceLocalBaiDu::Instance()->append(flag, image);
#endif
        } else if (name == "CompareByImage") {
            //取出子节点
            QDomNodeList nodeList = childNode.childNodes();
            int nodeCount = nodeList.count();
            if (nodeCount == 2) {
                QString faceID1, faceID2;
                QImage faceImage1, faceImage2;
                for (int i = 0; i < nodeCount; i++) {
                    childNode = nodeList.at(i);
                    element = childNode.toElement();
                    name = childNode.nodeName();
                    value = element.text();

                    if (name == "FaceImage1") {
                        faceID1 = element.attribute("FaceID");
                        faceImage1 = DeviceFun::getImage(value);
                    } else if (name == "FaceImage2") {
                        faceID2 = element.attribute("FaceID");
                        faceImage2 = DeviceFun::getImage(value);
                    }
                }

                checkImage(faceImage1);
                checkImage(faceImage2);

                QString flag1 = QString("%1_%2").arg(this->socketDescriptor()).arg(faceID1);
                QString flag2 = QString("%1_%2").arg(this->socketDescriptor()).arg(faceID2);
                emit receiveAnaly(deviceIP, "请求人脸照片比对");

                //发送到人脸识别线程处理
#ifdef facelocal
                FaceLocalBaiDu::Instance()->setType(2);
                FaceLocalBaiDu::Instance()->append(flag1 + "|" + flag2, faceImage1, faceImage2);
#elif facearm
                FaceLocalArm::Instance()->setType(2);
                FaceLocalArm::Instance()->append(flag1 + "|" + flag2, faceImage1, faceImage2);
#endif
            }
        } else if (name == "CompareByFeature") {
            element = childNode.toElement();
            QString faceID = element.attribute("FaceID");

            //取出子节点
            QDomNodeList nodeList = childNode.childNodes();
            int nodeCount = nodeList.count();
            if (nodeCount == 2) {
                QStringList faceFeature1, faceFeature2;
                for (int i = 0; i < nodeCount; i++) {
                    childNode = nodeList.at(i);
                    element = childNode.toElement();
                    name = childNode.nodeName();
                    value = element.text();

                    if (name == "FaceFeature1") {
                        faceFeature1 = value.split("|");
                    } else if (name == "FaceFeature2") {
                        faceFeature2 = value.split("|");
                    }
                }

                emit receiveAnaly(deviceIP, "请求人脸特征比对");

                //特征比对速度非常快,忽略不计,立即比对并将结果返回
                int count1 = faceFeature1.count();
                int count2 = faceFeature2.count();
                if (count1 != 256 || count2 != 256) {
                    sendMsg("faceFeature count != 256");
                    return;
                }

                QList<float> feature1, feature2;
                for (int i = 0; i < 256; i++) {
                    feature1 << faceFeature1.at(i).toFloat();
                    feature2 << faceFeature2.at(i).toFloat();
                }

#ifdef facelocal
                float result = FaceLocalBaiDu::Instance()->getFaceCompare(faceID, feature1, feature2);
                sendFaceCompare(faceID, result, 1);
#elif facearm
                float result = FaceLocalArm::Instance()->getFaceCompare(faceID, feature1, feature2);
                sendFaceCompare(faceID, result, 1);
#endif
            }
        } else if (name == "AppendFace") {
            element = childNode.toElement();
            value = element.text();
            if (value.length() == 0) {
                return;
            }

            //用连接的描述符加上用户传入的描述符组合,方便接收处判断发送给那个连接
            QString faceID = element.attribute("FaceID");
            QString flag = QString("%1_%2").arg(this->socketDescriptor()).arg(faceID);
            QImage image = DeviceFun::getImage(value);
            checkImage(image);
            emit receiveAnaly(deviceIP, "添加人脸");

            //发送到人脸识别线程处理
            QString file = QString("%1/%2.txt").arg(FACEPATH).arg(faceID);
#ifdef facelocal
            FaceLocalBaiDu::Instance()->appendFace(flag, image, file);
#elif facearm
            FaceLocalArm::Instance()->appendFace(flag, image, file);
#endif
        } else if (name == "DeleteFace") {
            element = childNode.toElement();
            value = element.text();
            if (value.length() == 0) {
                return;
            }

            //用连接的描述符加上用户传入的描述符组合,方便接收处判断发送给那个连接
            QString faceID = element.attribute("FaceID");
            emit receiveAnaly(deviceIP, "删除人脸");

            //发送到人脸识别线程处理
#ifdef facelocal
            FaceLocalBaiDu::Instance()->deleteFace(faceID);
#elif facearm
            FaceLocalArm::Instance()->deleteFace(faceID);
#endif
            sendOk();
        } else if (name == "FindByImage") {
            element = childNode.toElement();
            value = element.text();
            if (value.length() == 0) {
                return;
            }

            //用连接的描述符加上用户传入的描述符组合,方便接收处判断发送给那个连接
            QString faceID = element.attribute("FaceID");
            QString flag = QString("%1_%2").arg(this->socketDescriptor()).arg(faceID);
            QImage image = DeviceFun::getImage(value);
            checkImage(image);
            emit receiveAnaly(deviceIP, "根据图片查找人脸");

            //发送到人脸识别线程处理
#ifdef facelocal
            FaceLocalBaiDu::Instance()->setOneImg(flag, image);
#elif facearm
            FaceLocalArm::Instance()->setOneImg(flag, image);
#endif
        } else if (name == "FindByFeature") {
            element = childNode.toElement();
            value = element.text();
            if (value.length() == 0) {
                return;
            }

            //用连接的描述符加上用户传入的描述符组合,方便接收处判断发送给那个连接
            QString faceID = element.attribute("FaceID");
            QStringList faceFeature = value.split("|");
            emit receiveAnaly(deviceIP, "根据特征查找人脸");

            int count = faceFeature.count();
            if (count != 256) {
                return;
            }

            QList<float> feature;
            for (int i = 0; i < 256; i++) {
                feature << faceFeature.at(i).toFloat();
            }

            //比对速度很快,立即比对并返回结果
            QString targetName;
            float result;
            int msec;
#ifdef facelocal
            FaceLocalBaiDu::Instance()->getFaceOne(faceID, feature, targetName, result, msec);
#elif facearm
            FaceLocalArm::Instance()->getFaceOne(faceID, feature, targetName, result, msec);
#endif
            if (!targetName.isEmpty()) {
                QString imageFile = QString("%1/%2").arg(FACEPATH).arg(targetName);
                sendFaceCompareOne(faceID, QImage(), QImage(imageFile), targetName, result, msec);
            }
        } else if (name == "UpdateConfig") {
            element = childNode.toElement();
            emit receiveAnaly(deviceIP, "修改人脸配置");

            bool findFast = (element.attribute("FindFast") == "true" ? true : false);
            int facePercent = element.attribute("FacePercent").toInt();
#ifdef facelocal
            FaceLocalBaiDu::Instance()->setFindFast(findFast);
            FaceLocalBaiDu::Instance()->setPercent(facePercent);
#elif facearm
            FaceLocalArm::Instance()->setFindFast(findFast);
            FaceLocalArm::Instance()->setPercent(facePercent);
#endif
            //立即回复
            sendFaceConfig(findFast, facePercent);
            emit configChanged(findFast, facePercent);
        }
    }
}

void FaceSdkSocket::checkImage(const QImage &image)
{
    //如果照片宽高过大则发出提示到客户端
    if (image.width() >= 1280 || image.height() >= 720) {
        sendMsg("Image Size Is Too Large");
    }
}

void FaceSdkSocket::setClientIP(const QString &clientIP)
{
    this->clientIP = clientIP;
}

QString FaceSdkSocket::getClientIP()
{
    return this->clientIP;
}

void FaceSdkSocket::sendData(const QString &body)
{
    //构建xml字符串
    QStringList list;
    list.append(QString("<FaceServer TargetIP=\"%1\" NowTime=\"%2\">").arg(clientIP).arg(DATETIME));
    list.append(body);
    list.append("</FaceServer>");

    QString data = DeviceFun::getSendXmlData(list.join(""), "IFACE:");
    this->write(data.toUtf8());
    emit sendData(clientIP, data);
}

void FaceSdkSocket::sendOk()
{
    sendData("");
    emit sendAnaly(clientIP, "心跳应答");
}

void FaceSdkSocket::sendMsg(const QString &msg)
{
    sendData(QString("<Msg>%1</Msg>").arg(msg));
    emit sendAnaly(clientIP, "提示信息");
}

void FaceSdkSocket::sendFaceRect(const QString &faceID, const QString &faceRect, int msec)
{
    QString data = QString("<FaceRect FaceID=\"%1\" TimeUsed=\"%3\">%2</FaceRect>")
                   .arg(faceID).arg(faceRect).arg(msec);
    sendData(data);
    emit sendAnaly(clientIP, "返回人脸区域");
}

void FaceSdkSocket::sendFaceFeature(const QString &faceID, const QString &faceFeature, int msec)
{
    QString data = QString("<FaceFeature FaceID=\"%1\" TimeUsed=\"%3\">%2</FaceFeature>")
                   .arg(faceID).arg(faceFeature).arg(msec);
    sendData(data);
    emit sendAnaly(clientIP, "返回人脸特征");
}

void FaceSdkSocket::sendFaceCompare(const QString &faceID, float result, int msec)
{
    QString data = QString("<FaceCompare FaceID=\"%1\" TimeUsed=\"%3\" Result=\"%2\" />")
                   .arg(faceID).arg(result).arg(msec);
    sendData(data);
    emit sendAnaly(clientIP, "返回人脸比对结果");
}

void FaceSdkSocket::sendFaceCompareOne(const QString &faceID, const QImage &sourceImage, const QImage &targetImage, const QString &targetName, float result, int msec)
{
    QString data = QString("<FaceCompareOne FaceID=\"%1\" TimeUsed=\"%6\" Result=\"%2\" TargetName=\"%3\">%4|%5</FaceCompareOne>")
                   .arg(faceID).arg(result).arg(targetName).arg(DeviceFun::getImageData(sourceImage)).arg(DeviceFun::getImageData(targetImage)).arg(msec);
    sendData(data);
    emit sendAnaly(clientIP, "返回最相似人脸");
}

到此,关于“Qt怎么实现人脸识别服务端”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

qt
AI