zoukankan      html  css  js  c++  java
  • Qt封装百度人脸识别+图像识别

    AI技术的发展在最近几年如火如荼,工资待遇也是水涨船高,应用的前景也是非常广阔,去年火起来的人脸识别,今年全国遍地开花,之前封装了下face++的人脸识别等接口,今年看了下百度的AI,还免费了,效果也是越来越好,活体检测这个算法更是做的吊炸天(只需要传一张图片就能判断图片中的人是翻拍的照片非活体),牛逼的一塌糊涂,我反正是跪了。特意花了半天时间将百度人脸识别+图像识别封装了下,以便后期使用。顺便预测下,百度AI在未来的国内AI市场中,不是第一就是第二,而且会持续保持至少十年。
    为了兼容qt4,特意采用了qtscript解析收到的数据。

     * 1:可识别身份证正面信息+背面信息
     * 2:可识别银行卡信息
     * 3:可识别驾驶证+行驶证信息
     * 4:可进行人脸识别,人脸比对,活体检测
     * 5:可设置请求地址+用户密钥+应用密钥
     * 6:直接传入图片即可,信号返回,毫秒级极速响应
     * 7:通用Qt4-Qt5,windows linux 嵌入式linux

    可执行文件下载:https://pan.baidu.com/s/1pzhQL_YMYZyn4hW94e0QsQ 

    QByteArray FaceBaiDu::getImageData(const QImage &img)
    {
        QImage image = img;
        QByteArray imageData;
        QBuffer buffer(&imageData);
        image.save(&buffer, "jpg");
        return imageData.toBase64();
    }
    
    QString FaceBaiDu::getImageData2(const QImage &img)
    {
        return QString(getImageData(img));
    }
    
    QHttpPart FaceBaiDu::dataToHttpPart(const QByteArray &body, const QString &name)
    {
        QHttpPart httpPart;
        httpPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(QString("form-data;name="%1"").arg(name)));
        httpPart.setBody(body);
        return httpPart;
    }
    
    void FaceBaiDu::sendData(const QString &url, const QList<QHttpPart> &httpParts)
    {
        //初始化消息体
        QHttpMultiPart *httpMultiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
    
        //逐个添加消息内容
        foreach (QHttpPart httpPart, httpParts) {
            httpMultiPart->append(httpPart);
        }
    
        //初始化请求对象
        QNetworkRequest request;
        request.setUrl(QUrl(url));
    
    #ifdef ssl
        //设置openssl签名配置,否则在ARM上会报错
        QSslConfiguration conf = request.sslConfiguration();
        conf.setPeerVerifyMode(QSslSocket::VerifyNone);
    #if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
        conf.setProtocol(QSsl::TlsV1_0);
    #else
        conf.setProtocol(QSsl::TlsV1);
    #endif
        request.setSslConfiguration(conf);
    #endif
    
        //发送请求
        QNetworkReply *reply = manager->post(request, httpMultiPart);
        httpMultiPart->setParent(reply);
    }
    
    void FaceBaiDu::finished(QNetworkReply *reply)
    {
        QString error = reply->errorString();
        if (!error.isEmpty() && error != "Unknown error") {
            emit receiveError(error);
        }
    
        if (reply->bytesAvailable() > 0 && reply->error() == QNetworkReply::NoError) {
            QString data = reply->readAll();
            reply->deleteLater();
    
            //发送接收数据信号
            emit receiveData(data);
    
            //初始化脚本引擎
            QScriptEngine engine;
            //构建解析对象
            QScriptValue script = engine.evaluate("value=" + data);
    
            //获取鉴权标识符
            QString token = script.property("access_token").toString();
            if (!token.isEmpty()) {
                tokenFace = token;
                tokenOcr = token;
            }
    
            //通用返回结果字段
            int code = script.property("error_code").toInt32();
            QString msg = script.property("error_msg").toString();
            emit receiveResult(code, msg);
    
            //人脸识别部分
            QScriptValue result = script.property("result");
            if (!result.isNull()) {
                //人脸识别
                QScriptValue face_list = result.property("face_list");
                if (face_list.isObject()) {
                    checkFaceList(face_list);
                }
    
                //人脸比对
                QScriptValue score = result.property("score");
                if (!score.isNull()) {
                    double value = score.toString().toDouble();
                    if (value > 0) {
                        emit receiveFaceCompare(QRect(), QRect(), value);
                    } else {
                        emit receiveFaceCompareFail();
                    }
                }
    
                //活体检测
                QScriptValue face_liveness = result.property("face_liveness");
                if (!face_liveness.isNull()) {
                    double liveness = face_liveness.toString().toDouble();
                    if (liveness > 0) {
                        emit receiveLive(liveness);
                    }
                }
    
                //银行卡
                QScriptValue bank_card_number = result.property("bank_card_number");
                if (!bank_card_number.isNull()) {
                    QString card_number = bank_card_number.toString();
                    QString bank_name = result.property("bank_name").toString();
                    if (!card_number.isEmpty()) {
                        emit receiveBankCardInfo(card_number, bank_name);
                    }
                }
            }
    
            //文字识别部分
            QScriptValue words_result = script.property("words_result");
            if (!words_result.isNull()) {
                //身份证正面
                QScriptValue nation = words_result.property("民族");
                if (nation.isObject()) {
                    checkCardFront(words_result);
                }
    
                //身份证反面
                QScriptValue issuedby = words_result.property("签发机关");
                if (issuedby.isObject()) {
                    checkCardBack(words_result);
                }
    
                //驾驶证
                QScriptValue license_number = words_result.property("证号");
                if (license_number.isObject()) {
                    checkDriverLicense(words_result);
                }
    
                //行驶证
                QScriptValue model = words_result.property("品牌型号");
                if (model.isObject()) {
                    checkRVehicleLicense(words_result);
                }
            }
        }
    }
    
    void FaceBaiDu::checkFaceList(const QScriptValue &face_list)
    {
        QRect face_rectangle;
    
        //创建迭代器逐个解析具体值
        QScriptValueIterator it(face_list);
        while (it.hasNext()) {
            it.next();
    
            QString face_token = it.value().property("face_token").toString();
            if (!face_token.isEmpty()) {
                QScriptValue location = it.value().property("location");
                if (location.isObject()) {
                    face_rectangle.setX(location.property("left").toInt32());
                    face_rectangle.setY(location.property("top").toInt32());
                    face_rectangle.setWidth(location.property("width").toInt32());
                    face_rectangle.setHeight(location.property("height").toInt32());
                }
            }
    
            it.next();
            if (face_rectangle.width() > 0) {
                emit receiveFaceRect(face_rectangle);
            } else {
                break;
            }
        }
    }
    
    void FaceBaiDu::checkCardFront(const QScriptValue &scriptValue)
    {
        QScriptValue name = scriptValue.property("姓名");
        QScriptValue address = scriptValue.property("住址");
        QScriptValue birthday = scriptValue.property("出生");
        QScriptValue number = scriptValue.property("公民身份号码");
        QScriptValue sex = scriptValue.property("性别");
        QScriptValue nation = scriptValue.property("民族");
    
        QString strName = name.property("words").toString();
        QString strAddress = address.property("words").toString();
        QString strBirthday = birthday.property("words").toString();
        QString strNumber = number.property("words").toString();
        QString strSex = sex.property("words").toString();
        QString strNation = nation.property("words").toString();
    
        emit receiveIDCardInfoFront(strName, strSex, strNumber, strBirthday, strNation, strAddress);
    }
    
    void FaceBaiDu::checkCardBack(const QScriptValue &scriptValue)
    {
        QScriptValue issuedby = scriptValue.property("签发机关");
        QScriptValue dateStart = scriptValue.property("签发日期");
        QScriptValue dateEnd = scriptValue.property("失效日期");
    
        QString strIssuedby = issuedby.property("words").toString();
        QString strDataStart = dateStart.property("words").toString();
        QString strDateEnd = dateEnd.property("words").toString();
    
        QString strDate = QString("%1.%2.%3-%4.%5.%6")
                          .arg(strDataStart.mid(0, 4)).arg(strDataStart.mid(4, 2)).arg(strDataStart.mid(6, 2))
                          .arg(strDateEnd.mid(0, 4)).arg(strDateEnd.mid(4, 2)).arg(strDateEnd.mid(6, 2));
        emit receiveIDCardInfoBack(strDate, strIssuedby);
    }
    
    void FaceBaiDu::checkDriverLicense(const QScriptValue &scriptValue)
    {
        QScriptValue licenseNumber = scriptValue.property("证号");
        QScriptValue name = scriptValue.property("姓名");
        QScriptValue gender = scriptValue.property("性别");
        QScriptValue nationality = scriptValue.property("国籍");
        QScriptValue address = scriptValue.property("住址");
        QScriptValue birthday = scriptValue.property("出生日期");
        QScriptValue issueDate = scriptValue.property("初次领证日期");
        QScriptValue classType = scriptValue.property("准驾车型");
        QScriptValue validFrom = scriptValue.property("有效起始日期");
        QScriptValue validFor = scriptValue.property("有效期限");
    
        QString strLicenseNumber = licenseNumber.property("words").toString();
        QString strName = name.property("words").toString();
        QString strGender = gender.property("words").toString();
        QString strNationality = nationality.property("words").toString();
        QString strAddress = address.property("words").toString();
        QString strBirthday = birthday.property("words").toString();
        QString strIssueDate = issueDate.property("words").toString();
        QString strClassType = classType.property("words").toString();
        QString strValidFrom = validFrom.property("words").toString();
        QString strValidFor = validFor.property("words").toString();
    
        emit receiveDriverInfo(strValidFrom, strGender, "", strIssueDate, strClassType, strLicenseNumber,
                               strValidFor, strBirthday, "1", strAddress, strNationality, strName);
    }
    
    void FaceBaiDu::checkRVehicleLicense(const QScriptValue &scriptValue)
    {
        QScriptValue plateNo = scriptValue.property("号牌号码");
        QScriptValue vehicleType = scriptValue.property("车辆类型");
        QScriptValue owner = scriptValue.property("所有人");
        QScriptValue address = scriptValue.property("住址");
        QScriptValue useCharacter = scriptValue.property("使用性质");
        QScriptValue model = scriptValue.property("品牌型号");
        QScriptValue vin = scriptValue.property("车辆识别代号");
        QScriptValue engineNo = scriptValue.property("发动机号码");
        QScriptValue registerDate = scriptValue.property("注册日期");
        QScriptValue issueDate = scriptValue.property("发证日期");
    
        QString strPlateNo = plateNo.property("words").toString();
        QString strCehicleType = vehicleType.property("words").toString();
        QString strOwner = owner.property("words").toString();
        QString strAddress = address.property("words").toString();
        QString strUseCharacter = useCharacter.property("words").toString();
        QString strModel = model.property("words").toString();
        QString strVin = vin.property("words").toString();
        QString strEngineNo = engineNo.property("words").toString();
        QString strRegisterDate = registerDate.property("words").toString();
        QString strIssueDate = issueDate.property("words").toString();
    
        emit receiveRvehicleInfo(strIssueDate, strCehicleType, "", strVin, strPlateNo, strUseCharacter,
                                 strAddress, strOwner, strModel, strRegisterDate, strEngineNo);
    }
    
    void FaceBaiDu::sendData(const QString &url, const QString &data, const QString &header)
    {
        QNetworkRequest request;
        request.setHeader(QNetworkRequest::ContentTypeHeader, header);
        request.setUrl(QUrl(url));
    
    #ifdef ssl
        //设置openssl签名配置,否则在ARM上会报错
        QSslConfiguration conf = request.sslConfiguration();
        conf.setPeerVerifyMode(QSslSocket::VerifyNone);
    #if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
        conf.setProtocol(QSsl::TlsV1_0);
    #else
        conf.setProtocol(QSsl::TlsV1);
    #endif
        request.setSslConfiguration(conf);
    #endif
    
        manager->post(request, data.toUtf8());
    }
    
    void FaceBaiDu::getToken(const QString &client_id, const QString &client_secret)
    {
        QStringList list;
        list.append(QString("grant_type=%1").arg("client_credentials"));
        list.append(QString("client_id=%1").arg(client_id));
        list.append(QString("client_secret=%1").arg(client_secret));
        QString data = list.join("&");
    
        QString url = "https://aip.baidubce.com/oauth/2.0/token";
        sendData(url, data);
    }
    
    void FaceBaiDu::detect(const QImage &img)
    {
        QStringList list;
        list.append(QString("{"image":"%1","image_type":"BASE64"}").arg(getImageData2(img)));
        QString data = list.join("");
    
        QString url = QString("https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=%1").arg(tokenFace);
        sendData(url, data);
    }
    
    void FaceBaiDu::compare(const QImage &img1, const QImage &img2)
    {
        QString imgData1 = getImageData2(img1);
        QString imgData2 = getImageData2(img2);
    
        //如果需要活体检测则NONE改为LOW NORMAL HIGH
        QStringList list;
        list.append("[");
        list.append(QString("{"image":"%1","image_type":"BASE64","liveness_control":"NONE"}").arg(imgData1));
        list.append(",");
        list.append(QString("{"image":"%1","image_type":"BASE64","liveness_control":"NONE"}").arg(imgData2));
        list.append("]");
        QString data = list.join("");
    
        QString url = QString("https://aip.baidubce.com/rest/2.0/face/v3/match?access_token=%1").arg(tokenFace);
        sendData(url, data);
    }
    
    void FaceBaiDu::live(const QImage &img)
    {
        QList<QImage> imgs;
        if (!img.isNull()) {
            imgs << img;
        }
    
        live(imgs);
    }
    
    void FaceBaiDu::live(const QList<QImage> &imgs)
    {
        //记住最后一次处理的时间,限制频繁的调用
        QDateTime now = QDateTime::currentDateTime();
        if (lastTime.msecsTo(now) < 500) {
            return;
        }
    
        lastTime = now;
    
        QStringList list;
        list.append("[");
    
        int count = imgs.count();
        for (int i = 0; i < count; i++) {
            QString imgData = getImageData2(imgs.at(i));
            list.append(QString("{"image":"%1","image_type":"BASE64"}").arg(imgData));
            if (i < count - 1) {
                list.append(",");
            }
        }
    
        list.append("]");
        QString data = list.join("");
    
        QString url = QString("https://aip.baidubce.com/rest/2.0/face/v3/faceverify?access_token=%1").arg(tokenFace);
        sendData(url, data);
    }
    
    void FaceBaiDu::idmatch(const QString &idcard, const QString &name)
    {
        QStringList list;
        list.append(QString("{"id_card_num":"%1","name":"%2"}").arg(idcard).arg(name));
        QString data = list.join("");
    
        QString url = QString("https://aip.baidubce.com/rest/2.0/face/v3/person/idmatch?access_token=%1").arg(tokenFace);
        sendData(url, data);
    }
    
    void FaceBaiDu::idcard(const QImage &img, bool front)
    {
        QList<QHttpPart> httpParts;
        httpParts << dataToHttpPart(front ? "front" : "back", "id_card_side");
        httpParts << dataToHttpPart(getImageData(img), "image");
    
        QString url = QString("https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?access_token=%1").arg(tokenOcr);
        sendData(url, httpParts);
    }
    
    void FaceBaiDu::bankcard(const QImage &img)
    {
        QList<QHttpPart> httpParts;
        httpParts << dataToHttpPart(getImageData(img), "image");
    
        QString url = QString("https://aip.baidubce.com/rest/2.0/ocr/v1/bankcard?access_token=%1").arg(tokenOcr);
        sendData(url, httpParts);
    }
    
    void FaceBaiDu::driverLicense(const QImage &img)
    {
        QList<QHttpPart> httpParts;
        httpParts << dataToHttpPart(getImageData(img), "image");
    
        QString url = QString("https://aip.baidubce.com/rest/2.0/ocr/v1/driving_license?access_token=%1").arg(tokenOcr);
        sendData(url, httpParts);
    }
    
    void FaceBaiDu::vehicleLicense(const QImage &img)
    {
        QList<QHttpPart> httpParts;
        httpParts << dataToHttpPart(getImageData(img), "image");
    
        QString url = QString("https://aip.baidubce.com/rest/2.0/ocr/v1/vehicle_license?access_token=%1").arg(tokenOcr);
        sendData(url, httpParts);
    }
    

      

  • 相关阅读:
    检测iphone设备是否越狱
    iphone震动提示
    单线,双线
    塔式服务器
    IPHONE锁屏控制代码
    iPhone开发之显示WiFi提示
    代码关闭程序的几种方法
    获取手机左边音量+ -按键的事件方法或私有api
    1u
    servlet在什么时候调用destroy()方法
  • 原文地址:https://www.cnblogs.com/feiyangqingyun/p/9471319.html
Copyright © 2011-2022 走看看