找回密码
 立即注册
收起左侧

Qt封装百度人脸识别+图像识别

2
回复
7219
查看
[复制链接]
累计签到:7 天
连续签到:1 天
来源: 2018-8-13 22:03:34 显示全部楼层 |阅读模式
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



  1. QByteArray FaceBaiDu::getImageData(const QImage &img)
  2. {
  3.     QImage image = img;
  4.     QByteArray imageData;
  5.     QBuffer buffer(&imageData);
  6.     image.save(&buffer, "jpg");
  7.     return imageData.toBase64();
  8. }

  9. QString FaceBaiDu::getImageData2(const QImage &img)
  10. {
  11.     return QString(getImageData(img));
  12. }

  13. QHttpPart FaceBaiDu::dataToHttpPart(const QByteArray &body, const QString &name)
  14. {
  15.     QHttpPart httpPart;
  16.     httpPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(QString("form-data;name="%1"").arg(name)));
  17.     httpPart.setBody(body);
  18.     return httpPart;
  19. }

  20. void FaceBaiDu::sendData(const QString &url, const QList<QHttpPart> &httpParts)
  21. {
  22.     //初始化消息体
  23.     QHttpMultiPart *httpMultiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

  24.     //逐个添加消息内容
  25.     foreach (QHttpPart httpPart, httpParts) {
  26.         httpMultiPart->append(httpPart);
  27.     }

  28.     //初始化请求对象
  29.     QNetworkRequest request;
  30.     request.setUrl(QUrl(url));

  31. #ifdef ssl
  32.     //设置openssl签名配置,否则在ARM上会报错
  33.     QSslConfiguration conf = request.sslConfiguration();
  34.     conf.setPeerVerifyMode(QSslSocket::VerifyNone);
  35. #if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
  36.     conf.setProtocol(QSsl::TlsV1_0);
  37. #else
  38.     conf.setProtocol(QSsl::TlsV1);
  39. #endif
  40.     request.setSslConfiguration(conf);
  41. #endif

  42.     //发送请求
  43.     QNetworkReply *reply = manager->post(request, httpMultiPart);
  44.     httpMultiPart->setParent(reply);
  45. }

  46. void FaceBaiDu::finished(QNetworkReply *reply)
  47. {
  48.     QString error = reply->errorString();
  49.     if (!error.isEmpty() && error != "Unknown error") {
  50.         emit receiveError(error);
  51.     }

  52.     if (reply->bytesAvailable() > 0 && reply->error() == QNetworkReply::NoError) {
  53.         QString data = reply->readAll();
  54.         reply->deleteLater();

  55.         //发送接收数据信号
  56.         emit receiveData(data);

  57.         //初始化脚本引擎
  58.         QScriptEngine engine;
  59.         //构建解析对象
  60.         QScriptValue script = engine.evaluate("value=" + data);

  61.         //获取鉴权标识符
  62.         QString token = script.property("access_token").toString();
  63.         if (!token.isEmpty()) {
  64.             tokenFace = token;
  65.             tokenOcr = token;
  66.         }

  67.         //通用返回结果字段
  68.         int code = script.property("error_code").toInt32();
  69.         QString msg = script.property("error_msg").toString();
  70.         emit receiveResult(code, msg);

  71.         //人脸识别部分
  72.         QScriptValue result = script.property("result");
  73.         if (!result.isNull()) {
  74.             //人脸识别
  75.             QScriptValue face_list = result.property("face_list");
  76.             if (face_list.isObject()) {
  77.                 checkFaceList(face_list);
  78.             }

  79.             //人脸比对
  80.             QScriptValue score = result.property("score");
  81.             if (!score.isNull()) {
  82.                 double value = score.toString().toDouble();
  83.                 if (value > 0) {
  84.                     emit receiveFaceCompare(QRect(), QRect(), value);
  85.                 } else {
  86.                     emit receiveFaceCompareFail();
  87.                 }
  88.             }

  89.             //活体检测
  90.             QScriptValue face_liveness = result.property("face_liveness");
  91.             if (!face_liveness.isNull()) {
  92.                 double liveness = face_liveness.toString().toDouble();
  93.                 if (liveness > 0) {
  94.                     emit receiveLive(liveness);
  95.                 }
  96.             }

  97.             //银行卡
  98.             QScriptValue bank_card_number = result.property("bank_card_number");
  99.             if (!bank_card_number.isNull()) {
  100.                 QString card_number = bank_card_number.toString();
  101.                 QString bank_name = result.property("bank_name").toString();
  102.                 if (!card_number.isEmpty()) {
  103.                     emit receiveBankCardInfo(card_number, bank_name);
  104.                 }
  105.             }
  106.         }

  107.         //文字识别部分
  108.         QScriptValue words_result = script.property("words_result");
  109.         if (!words_result.isNull()) {
  110.             //身份证正面
  111.             QScriptValue nation = words_result.property("民族");
  112.             if (nation.isObject()) {
  113.                 checkCardFront(words_result);
  114.             }

  115.             //身份证反面
  116.             QScriptValue issuedby = words_result.property("签发机关");
  117.             if (issuedby.isObject()) {
  118.                 checkCardBack(words_result);
  119.             }

  120.             //驾驶证
  121.             QScriptValue license_number = words_result.property("证号");
  122.             if (license_number.isObject()) {
  123.                 checkDriverLicense(words_result);
  124.             }

  125.             //行驶证
  126.             QScriptValue model = words_result.property("品牌型号");
  127.             if (model.isObject()) {
  128.                 checkRVehicleLicense(words_result);
  129.             }
  130.         }
  131.     }
  132. }

  133. void FaceBaiDu::checkFaceList(const QScriptValue &face_list)
  134. {
  135.     QRect face_rectangle;

  136.     //创建迭代器逐个解析具体值
  137.     QScriptValueIterator it(face_list);
  138.     while (it.hasNext()) {
  139.         it.next();

  140.         QString face_token = it.value().property("face_token").toString();
  141.         if (!face_token.isEmpty()) {
  142.             QScriptValue location = it.value().property("location");
  143.             if (location.isObject()) {
  144.                 face_rectangle.setX(location.property("left").toInt32());
  145.                 face_rectangle.setY(location.property("top").toInt32());
  146.                 face_rectangle.setWidth(location.property("width").toInt32());
  147.                 face_rectangle.setHeight(location.property("height").toInt32());
  148.             }
  149.         }

  150.         it.next();
  151.         if (face_rectangle.width() > 0) {
  152.             emit receiveFaceRect(face_rectangle);
  153.         } else {
  154.             break;
  155.         }
  156.     }
  157. }

  158. void FaceBaiDu::checkCardFront(const QScriptValue &scriptValue)
  159. {
  160.     QScriptValue name = scriptValue.property("姓名");
  161.     QScriptValue address = scriptValue.property("住址");
  162.     QScriptValue birthday = scriptValue.property("出生");
  163.     QScriptValue number = scriptValue.property("公民身份号码");
  164.     QScriptValue ** = scriptValue.property("性别");
  165.     QScriptValue nation = scriptValue.property("民族");

  166.     QString strName = name.property("words").toString();
  167.     QString strAddress = address.property("words").toString();
  168.     QString strBirthday = birthday.property("words").toString();
  169.     QString strNumber = number.property("words").toString();
  170.     QString str** = **.property("words").toString();
  171.     QString strNation = nation.property("words").toString();

  172.     emit receiveIDCardInfoFront(strName, str**, strNumber, strBirthday, strNation, strAddress);
  173. }

  174. void FaceBaiDu::checkCardBack(const QScriptValue &scriptValue)
  175. {
  176.     QScriptValue issuedby = scriptValue.property("签发机关");
  177.     QScriptValue dateStart = scriptValue.property("签发日期");
  178.     QScriptValue dateEnd = scriptValue.property("失效日期");

  179.     QString strIssuedby = issuedby.property("words").toString();
  180.     QString strDataStart = dateStart.property("words").toString();
  181.     QString strDateEnd = dateEnd.property("words").toString();

  182.     QString strDate = QString("%1.%2.%3-%4.%5.%6")
  183.                       .arg(strDataStart.mid(0, 4)).arg(strDataStart.mid(4, 2)).arg(strDataStart.mid(6, 2))
  184.                       .arg(strDateEnd.mid(0, 4)).arg(strDateEnd.mid(4, 2)).arg(strDateEnd.mid(6, 2));
  185.     emit receiveIDCardInfoBack(strDate, strIssuedby);
  186. }

  187. void FaceBaiDu::checkDriverLicense(const QScriptValue &scriptValue)
  188. {
  189.     QScriptValue licenseNumber = scriptValue.property("证号");
  190.     QScriptValue name = scriptValue.property("姓名");
  191.     QScriptValue gender = scriptValue.property("性别");
  192.     QScriptValue nationality = scriptValue.property("国籍");
  193.     QScriptValue address = scriptValue.property("住址");
  194.     QScriptValue birthday = scriptValue.property("出生日期");
  195.     QScriptValue issueDate = scriptValue.property("初次领证日期");
  196.     QScriptValue classType = scriptValue.property("准驾车型");
  197.     QScriptValue validFrom = scriptValue.property("有效起始日期");
  198.     QScriptValue validFor = scriptValue.property("有效期限");

  199.     QString strLicenseNumber = licenseNumber.property("words").toString();
  200.     QString strName = name.property("words").toString();
  201.     QString strGender = gender.property("words").toString();
  202.     QString strNationality = nationality.property("words").toString();
  203.     QString strAddress = address.property("words").toString();
  204.     QString strBirthday = birthday.property("words").toString();
  205.     QString strIssueDate = issueDate.property("words").toString();
  206.     QString strClassType = classType.property("words").toString();
  207.     QString strValidFrom = validFrom.property("words").toString();
  208.     QString strValidFor = validFor.property("words").toString();

  209.     emit receiveDriverInfo(strValidFrom, strGender, "", strIssueDate, strClassType, strLicenseNumber,
  210.                            strValidFor, strBirthday, "1", strAddress, strNationality, strName);
  211. }

  212. void FaceBaiDu::checkRVehicleLicense(const QScriptValue &scriptValue)
  213. {
  214.     QScriptValue plateNo = scriptValue.property("号牌号码");
  215.     QScriptValue vehicleType = scriptValue.property("车辆类型");
  216.     QScriptValue owner = scriptValue.property("所有人");
  217.     QScriptValue address = scriptValue.property("住址");
  218.     QScriptValue useCharacter = scriptValue.property("使用性质");
  219.     QScriptValue model = scriptValue.property("品牌型号");
  220.     QScriptValue vin = scriptValue.property("车辆识别代号");
  221.     QScriptValue engineNo = scriptValue.property("发动机号码");
  222.     QScriptValue registerDate = scriptValue.property("注册日期");
  223.     QScriptValue issueDate = scriptValue.property("发证日期");

  224.     QString strPlateNo = plateNo.property("words").toString();
  225.     QString strCehicleType = vehicleType.property("words").toString();
  226.     QString strOwner = owner.property("words").toString();
  227.     QString strAddress = address.property("words").toString();
  228.     QString strUseCharacter = useCharacter.property("words").toString();
  229.     QString strModel = model.property("words").toString();
  230.     QString strVin = vin.property("words").toString();
  231.     QString strEngineNo = engineNo.property("words").toString();
  232.     QString strRegisterDate = registerDate.property("words").toString();
  233.     QString strIssueDate = issueDate.property("words").toString();

  234.     emit receiveRvehicleInfo(strIssueDate, strCehicleType, "", strVin, strPlateNo, strUseCharacter,
  235.                              strAddress, strOwner, strModel, strRegisterDate, strEngineNo);
  236. }

  237. void FaceBaiDu::sendData(const QString &url, const QString &data, const QString &header)
  238. {
  239.     QNetworkRequest request;
  240.     request.setHeader(QNetworkRequest::ContentTypeHeader, header);
  241.     request.setUrl(QUrl(url));

  242. #ifdef ssl
  243.     //设置openssl签名配置,否则在ARM上会报错
  244.     QSslConfiguration conf = request.sslConfiguration();
  245.     conf.setPeerVerifyMode(QSslSocket::VerifyNone);
  246. #if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
  247.     conf.setProtocol(QSsl::TlsV1_0);
  248. #else
  249.     conf.setProtocol(QSsl::TlsV1);
  250. #endif
  251.     request.setSslConfiguration(conf);
  252. #endif

  253.     manager->post(request, data.toUtf8());
  254. }

  255. void FaceBaiDu::getToken(const QString &client_id, const QString &client_secret)
  256. {
  257.     QStringList list;
  258.     list.append(QString("grant_type=%1").arg("client_credentials"));
  259.     list.append(QString("client_id=%1").arg(client_id));
  260.     list.append(QString("client_secret=%1").arg(client_secret));
  261.     QString data = list.join("&");

  262.     QString url = "https://aip.baidubce.com/oauth/2.0/token";
  263.     sendData(url, data);
  264. }

  265. void FaceBaiDu::detect(const QImage &img)
  266. {
  267.     QStringList list;
  268.     list.append(QString("{"image":"%1","image_type":"BASE64"}").arg(getImageData2(img)));
  269.     QString data = list.join("");

  270.     QString url = QString("https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=%1").arg(tokenFace);
  271.     sendData(url, data);
  272. }

  273. void FaceBaiDu::compare(const QImage &img1, const QImage &img2)
  274. {
  275.     QString imgData1 = getImageData2(img1);
  276.     QString imgData2 = getImageData2(img2);

  277.     //如果需要活体检测则NONE改为LOW NORMAL HIGH
  278.     QStringList list;
  279.     list.append("[");
  280.     list.append(QString("{"image":"%1","image_type":"BASE64","liveness_control":"NONE"}").arg(imgData1));
  281.     list.append(",");
  282.     list.append(QString("{"image":"%1","image_type":"BASE64","liveness_control":"NONE"}").arg(imgData2));
  283.     list.append("]");
  284.     QString data = list.join("");

  285.     QString url = QString("https://aip.baidubce.com/rest/2.0/face/v3/match?access_token=%1").arg(tokenFace);
  286.     sendData(url, data);
  287. }

  288. void FaceBaiDu::live(const QImage &img)
  289. {
  290.     QList<QImage> imgs;
  291.     if (!img.isNull()) {
  292.         imgs << img;
  293.     }

  294.     live(imgs);
  295. }

  296. void FaceBaiDu::live(const QList<QImage> &imgs)
  297. {
  298.     //记住最后一次处理的时间,限制频繁的调用
  299.     QDateTime now = QDateTime::currentDateTime();
  300.     if (lastTime.msecsTo(now) < 500) {
  301.         return;
  302.     }

  303.     lastTime = now;

  304.     QStringList list;
  305.     list.append("[");

  306.     int count = imgs.count();
  307.     for (int i = 0; i < count; i++) {
  308.         QString imgData = getImageData2(imgs.at(i));
  309.         list.append(QString("{"image":"%1","image_type":"BASE64"}").arg(imgData));
  310.         if (i < count - 1) {
  311.             list.append(",");
  312.         }
  313.     }

  314.     list.append("]");
  315.     QString data = list.join("");

  316.     QString url = QString("https://aip.baidubce.com/rest/2.0/face/v3/faceverify?access_token=%1").arg(tokenFace);
  317.     sendData(url, data);
  318. }

  319. void FaceBaiDu::idmatch(const QString &idcard, const QString &name)
  320. {
  321.     QStringList list;
  322.     list.append(QString("{"id_card_num":"%1","name":"%2"}").arg(idcard).arg(name));
  323.     QString data = list.join("");

  324.     QString url = QString("https://aip.baidubce.com/rest/2.0/face/v3/person/idmatch?access_token=%1").arg(tokenFace);
  325.     sendData(url, data);
  326. }

  327. void FaceBaiDu::idcard(const QImage &img, bool front)
  328. {
  329.     QList<QHttpPart> httpParts;
  330.     httpParts << dataToHttpPart(front ? "front" : "back", "id_card_side");
  331.     httpParts << dataToHttpPart(getImageData(img), "image");

  332.     QString url = QString("https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?access_token=%1").arg(tokenOcr);
  333.     sendData(url, httpParts);
  334. }

  335. void FaceBaiDu::bankcard(const QImage &img)
  336. {
  337.     QList<QHttpPart> httpParts;
  338.     httpParts << dataToHttpPart(getImageData(img), "image");

  339.     QString url = QString("https://aip.baidubce.com/rest/2.0/ocr/v1/bankcard?access_token=%1").arg(tokenOcr);
  340.     sendData(url, httpParts);
  341. }

  342. void FaceBaiDu::driverLicense(const QImage &img)
  343. {
  344.     QList<QHttpPart> httpParts;
  345.     httpParts << dataToHttpPart(getImageData(img), "image");

  346.     QString url = QString("https://aip.baidubce.com/rest/2.0/ocr/v1/driving_license?access_token=%1").arg(tokenOcr);
  347.     sendData(url, httpParts);
  348. }

  349. void FaceBaiDu::vehicleLicense(const QImage &img)
  350. {
  351.     QList<QHttpPart> httpParts;
  352.     httpParts << dataToHttpPart(getImageData(img), "image");

  353.     QString url = QString("https://aip.baidubce.com/rest/2.0/ocr/v1/vehicle_license?access_token=%1").arg(tokenOcr);
  354.     sendData(url, httpParts);
  355. }
复制代码


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

尚未签到

2018-8-13 23:00:51 显示全部楼层
一个文件放所有代码。。。。。。
回复 支持 反对

使用道具 举报

累计签到:621 天
连续签到:1 天
2018-8-14 09:45:56 显示全部楼层
(*@ο@*) 哇~,这么强,不过,一个文件放所有代码。。。。。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了