AI的發展在最近幾年如火如荼,工資待遇也是水漲船高,應用的前景也是很是廣闊,去年火起來的人臉識別,今年全國遍地開花。看了下百度的AI,還免費了,效果也是愈來愈好,活體檢測這個算法更是作的吊炸天(只須要傳一張圖片就能判斷圖片中的人是翻拍的照片非活體),牛逼的一塌糊塗,我反正是跪了。百度AI在將來的國內AI市場中,不是第一就是第二,並且會持續保持至少十年。linux
1:可識別身份證正面信息+背面信息算法
2:可識別銀行卡信息windows
3:可識別駕駛證+行駛證信息app
4:可進行人臉識別,人臉比對,活體檢測ide
5:可設置請求地址+用戶密鑰+應用密鑰post
6:直接傳入圖片便可,信號返回,毫秒級極速響應lua
7:通用Qt4-Qt5,windows linux 嵌入式linux
下面看一下演示效果 url
固然下面這個是識別不了的spa
1QByteArray 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 10QString FaceBaiDu::getImageData2(const QImage &img) 11{ 12 return QString(getImageData(img)); 13} 14 15QHttpPart FaceBaiDu::dataToHttpPart(const QByteArray &body, const QString &name) 16{ 17 QHttpPart httpPart; 18 httpPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(QString("form-data;name=\"%1\"").arg(name))); 19 httpPart.setBody(body); 20 return httpPart; 21} 22 23void FaceBaiDu::sendData(const QString &url, const QList<QHttpPart> &httpParts) 24{ 25 //初始化消息體 26 QHttpMultiPart *httpMultiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); 27 28 //逐個添加消息內容 29 foreach (QHttpPart httpPart, httpParts) { 30 httpMultiPart->append(httpPart); 31 } 32 33 //初始化請求對象 34 QNetworkRequest request; 35 request.setUrl(QUrl(url)); 36 37#ifdef ssl 38 //設置openssl簽名配置,不然在ARM上會報錯 39 QSslConfiguration conf = request.sslConfiguration(); 40 conf.setPeerVerifyMode(QSslSocket::VerifyNone); 41#if (QT_VERSION > QT_VERSION_CHECK(5,0,0)) 42 conf.setProtocol(QSsl::TlsV1_0); 43#else 44 conf.setProtocol(QSsl::TlsV1); 45#endif 46 request.setSslConfiguration(conf); 47#endif 48 49 //發送請求 50 QNetworkReply *reply = manager->post(request, httpMultiPart); 51 httpMultiPart->setParent(reply); 52} 53 54void FaceBaiDu::finished(QNetworkReply *reply) 55{ 56 QString error = reply->errorString(); 57 if (!error.isEmpty() && error != "Unknown error") { 58 emit receiveError(error); 59 } 60 61 if (reply->bytesAvailable() > 0 && reply->error() == QNetworkReply::NoError) { 62 QString data = reply->readAll(); 63 reply->deleteLater(); 64 65 //發送接收數據信號 66 emit receiveData(data); 67 68 //初始化腳本引擎 69 QScriptEngine engine; 70 //構建解析對象 71 QScriptValue script = engine.evaluate("value=" + data); 72 73 //獲取鑑權標識符 74 QString token = script.property("access_token").toString(); 75 if (!token.isEmpty()) { 76 tokenFace = token; 77 tokenOcr = token; 78 } 79 80 //通用返回結果字段 81 int code = script.property("error_code").toInt32(); 82 QString msg = script.property("error_msg").toString(); 83 emit receiveResult(code, msg); 84 85 //人臉識別部分 86 QScriptValue result = script.property("result"); 87 if (!result.isNull()) { 88 //人臉識別 89 QScriptValue face_list = result.property("face_list"); 90 if (face_list.isObject()) { 91 checkFaceList(face_list); 92 } 93 94 //人臉比對 95 QScriptValue score = result.property("score"); 96 if (!score.isNull()) { 97 double value = score.toString().toDouble(); 98 if (value > 0) { 99 emit receiveFaceCompare(QRect(), QRect(), value); 100 } else { 101 emit receiveFaceCompareFail(); 102 } 103 } 104 105 //活體檢測 106 QScriptValue face_liveness = result.property("face_liveness"); 107 if (!face_liveness.isNull()) { 108 double liveness = face_liveness.toString().toDouble(); 109 if (liveness > 0) { 110 emit receiveLive(liveness); 111 } 112 } 113 114 //銀行卡 115 QScriptValue bank_card_number = result.property("bank_card_number"); 116 if (!bank_card_number.isNull()) { 117 QString card_number = bank_card_number.toString(); 118 QString bank_name = result.property("bank_name").toString(); 119 if (!card_number.isEmpty()) { 120 emit receiveBankCardInfo(card_number, bank_name); 121 } 122 } 123 } 124 125 //文字識別部分 126 QScriptValue words_result = script.property("words_result"); 127 if (!words_result.isNull()) { 128 //身份證正面 129 QScriptValue nation = words_result.property("民族"); 130 if (nation.isObject()) { 131 checkCardFront(words_result); 132 } 133 134 //身份證反面 135 QScriptValue issuedby = words_result.property("簽發機關"); 136 if (issuedby.isObject()) { 137 checkCardBack(words_result); 138 } 139 140 //駕駛證 141 QScriptValue license_number = words_result.property("證號"); 142 if (license_number.isObject()) { 143 checkDriverLicense(words_result); 144 } 145 146 //行駛證 147 QScriptValue model = words_result.property("品牌型號"); 148 if (model.isObject()) { 149 checkRVehicleLicense(words_result); 150 } 151 } 152 } 153} 154 155void FaceBaiDu::checkFaceList(const QScriptValue &face_list) 156{ 157 QRect face_rectangle; 158 159 //建立迭代器逐個解析具體值 160 QScriptValueIterator it(face_list); 161 while (it.hasNext()) { 162 it.next(); 163 164 QString face_token = it.value().property("face_token").toString(); 165 if (!face_token.isEmpty()) { 166 QScriptValue location = it.value().property("location"); 167 if (location.isObject()) { 168 face_rectangle.setX(location.property("left").toInt32()); 169 face_rectangle.setY(location.property("top").toInt32()); 170 face_rectangle.setWidth(location.property("width").toInt32()); 171 face_rectangle.setHeight(location.property("height").toInt32()); 172 } 173 } 174 175 it.next(); 176 if (face_rectangle.width() > 0) { 177 emit receiveFaceRect(face_rectangle); 178 } else { 179 break; 180 } 181 } 182} 183 184void FaceBaiDu::checkCardFront(const QScriptValue &scriptValue) 185{ 186 QScriptValue name = scriptValue.property("姓名"); 187 QScriptValue address = scriptValue.property("住址"); 188 QScriptValue birthday = scriptValue.property("出生"); 189 QScriptValue number = scriptValue.property("公民身份號碼"); 190 QScriptValue sex = scriptValue.property("性別"); 191 QScriptValue nation = scriptValue.property("民族"); 192 193 QString strName = name.property("words").toString(); 194 QString strAddress = address.property("words").toString(); 195 QString strBirthday = birthday.property("words").toString(); 196 QString strNumber = number.property("words").toString(); 197 QString strSex = sex.property("words").toString(); 198 QString strNation = nation.property("words").toString(); 199 200 emit receiveIDCardInfoFront(strName, strSex, strNumber, strBirthday, strNation, strAddress); 201} 202 203void FaceBaiDu::checkCardBack(const QScriptValue &scriptValue) 204{ 205 QScriptValue issuedby = scriptValue.property("簽發機關"); 206 QScriptValue dateStart = scriptValue.property("簽發日期"); 207 QScriptValue dateEnd = scriptValue.property("失效日期"); 208 209 QString strIssuedby = issuedby.property("words").toString(); 210 QString strDataStart = dateStart.property("words").toString(); 211 QString strDateEnd = dateEnd.property("words").toString(); 212 213 QString strDate = QString("%1.%2.%3-%4.%5.%6") 214 .arg(strDataStart.mid(0, 4)).arg(strDataStart.mid(4, 2)).arg(strDataStart.mid(6, 2)) 215 .arg(strDateEnd.mid(0, 4)).arg(strDateEnd.mid(4, 2)).arg(strDateEnd.mid(6, 2)); 216 emit receiveIDCardInfoBack(strDate, strIssuedby); 217} 218 219void FaceBaiDu::checkDriverLicense(const QScriptValue &scriptValue) 220{ 221 QScriptValue licenseNumber = scriptValue.property("證號"); 222 QScriptValue name = scriptValue.property("姓名"); 223 QScriptValue gender = scriptValue.property("性別"); 224 QScriptValue nationality = scriptValue.property("國籍"); 225 QScriptValue address = scriptValue.property("住址"); 226 QScriptValue birthday = scriptValue.property("出生日期"); 227 QScriptValue issueDate = scriptValue.property("初次領證日期"); 228 QScriptValue classType = scriptValue.property("準駕車型"); 229 QScriptValue validFrom = scriptValue.property("有效起始日期"); 230 QScriptValue validFor = scriptValue.property("有效期限"); 231 232 QString strLicenseNumber = licenseNumber.property("words").toString(); 233 QString strName = name.property("words").toString(); 234 QString strGender = gender.property("words").toString(); 235 QString strNationality = nationality.property("words").toString(); 236 QString strAddress = address.property("words").toString(); 237 QString strBirthday = birthday.property("words").toString(); 238 QString strIssueDate = issueDate.property("words").toString(); 239 QString strClassType = classType.property("words").toString(); 240 QString strValidFrom = validFrom.property("words").toString(); 241 QString strValidFor = validFor.property("words").toString(); 242 243 emit receiveDriverInfo(strValidFrom, strGender, "", strIssueDate, strClassType, strLicenseNumber, 244 strValidFor, strBirthday, "1", strAddress, strNationality, strName); 245} 246 247void FaceBaiDu::checkRVehicleLicense(const QScriptValue &scriptValue) 248{ 249 QScriptValue plateNo = scriptValue.property("號牌號碼"); 250 QScriptValue vehicleType = scriptValue.property("車輛類型"); 251 QScriptValue owner = scriptValue.property("全部人"); 252 QScriptValue address = scriptValue.property("住址"); 253 QScriptValue useCharacter = scriptValue.property("使用性質"); 254 QScriptValue model = scriptValue.property("品牌型號"); 255 QScriptValue vin = scriptValue.property("車輛識別代號"); 256 QScriptValue engineNo = scriptValue.property("發動機號碼"); 257 QScriptValue registerDate = scriptValue.property("註冊日期"); 258 QScriptValue issueDate = scriptValue.property("發證日期"); 259 260 QString strPlateNo = plateNo.property("words").toString(); 261 QString strCehicleType = vehicleType.property("words").toString(); 262 QString strOwner = owner.property("words").toString(); 263 QString strAddress = address.property("words").toString(); 264 QString strUseCharacter = useCharacter.property("words").toString(); 265 QString strModel = model.property("words").toString(); 266 QString strVin = vin.property("words").toString(); 267 QString strEngineNo = engineNo.property("words").toString(); 268 QString strRegisterDate = registerDate.property("words").toString(); 269 QString strIssueDate = issueDate.property("words").toString(); 270 271 emit receiveRvehicleInfo(strIssueDate, strCehicleType, "", strVin, strPlateNo, strUseCharacter, 272 strAddress, strOwner, strModel, strRegisterDate, strEngineNo); 273} 274 275void FaceBaiDu::sendData(const QString &url, const QString &data, const QString &header) 276{ 277 QNetworkRequest request; 278 request.setHeader(QNetworkRequest::ContentTypeHeader, header); 279 request.setUrl(QUrl(url)); 280 281#ifdef ssl 282 //設置openssl簽名配置,不然在ARM上會報錯 283 QSslConfiguration conf = request.sslConfiguration(); 284 conf.setPeerVerifyMode(QSslSocket::VerifyNone); 285#if (QT_VERSION > QT_VERSION_CHECK(5,0,0)) 286 conf.setProtocol(QSsl::TlsV1_0); 287#else 288 conf.setProtocol(QSsl::TlsV1); 289#endif 290 request.setSslConfiguration(conf); 291#endif 292 293 manager->post(request, data.toUtf8()); 294} 295 296void FaceBaiDu::getToken(const QString &client_id, const QString &client_secret) 297{ 298 QStringList list; 299 list.append(QString("grant_type=%1").arg("client_credentials")); 300 list.append(QString("client_id=%1").arg(client_id)); 301 list.append(QString("client_secret=%1").arg(client_secret)); 302 QString data = list.join("&"); 303 304 QString url = "https://aip.baidubce.com/oauth/2.0/token"; 305 sendData(url, data); 306} 307 308void FaceBaiDu::detect(const QImage &img) 309{ 310 QStringList list; 311 list.append(QString("{\"image\":\"%1\",\"image_type\":\"BASE64\"}").arg(getImageData2(img))); 312 QString data = list.join(""); 313 314 QString url = QString("https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=%1").arg(tokenFace); 315 sendData(url, data); 316} 317 318void FaceBaiDu::compare(const QImage &img1, const QImage &img2) 319{ 320 QString imgData1 = getImageData2(img1); 321 QString imgData2 = getImageData2(img2); 322 323 //若是須要活體檢測則NONE改成LOW NORMAL HIGH 324 QStringList list; 325 list.append("["); 326 list.append(QString("{\"image\":\"%1\",\"image_type\":\"BASE64\",\"liveness_control\":\"NONE\"}").arg(imgData1)); 327 list.append(","); 328 list.append(QString("{\"image\":\"%1\",\"image_type\":\"BASE64\",\"liveness_control\":\"NONE\"}").arg(imgData2)); 329 list.append("]"); 330 QString data = list.join(""); 331 332 QString url = QString("https://aip.baidubce.com/rest/2.0/face/v3/match?access_token=%1").arg(tokenFace); 333 sendData(url, data); 334} 335 336void FaceBaiDu::live(const QImage &img) 337{ 338 QList<QImage> imgs; 339 if (!img.isNull()) { 340 imgs << img; 341 } 342 343 live(imgs); 344} 345 346void FaceBaiDu::live(const QList<QImage> &imgs) 347{ 348 //記住最後一次處理的時間,限制頻繁的調用 349 QDateTime now = QDateTime::currentDateTime(); 350 if (lastTime.msecsTo(now) < 500) { 351 return; 352 } 353 354 lastTime = now; 355 356 QStringList list; 357 list.append("["); 358 359 int count = imgs.count(); 360 for (int i = 0; i < count; i++) { 361 QString imgData = getImageData2(imgs.at(i)); 362 list.append(QString("{\"image\":\"%1\",\"image_type\":\"BASE64\"}").arg(imgData)); 363 if (i < count - 1) { 364 list.append(","); 365 } 366 } 367 368 list.append("]"); 369 QString data = list.join(""); 370 371 QString url = QString("https://aip.baidubce.com/rest/2.0/face/v3/faceverify?access_token=%1").arg(tokenFace); 372 sendData(url, data); 373} 374 375void FaceBaiDu::idmatch(const QString &idcard, const QString &name) 376{ 377 QStringList list; 378 list.append(QString("{\"id_card_num\":\"%1\",\"name\":\"%2\"}").arg(idcard).arg(name)); 379 QString data = list.join(""); 380 381 QString url = QString("https://aip.baidubce.com/rest/2.0/face/v3/person/idmatch?access_token=%1").arg(tokenFace); 382 sendData(url, data); 383} 384 385void FaceBaiDu::idcard(const QImage &img, bool front) 386{ 387 QList<QHttpPart> httpParts; 388 httpParts << dataToHttpPart(front ? "front" : "back", "id_card_side"); 389 httpParts << dataToHttpPart(getImageData(img), "image"); 390 391 QString url = QString("https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?access_token=%1").arg(tokenOcr); 392 sendData(url, httpParts); 393} 394 395void FaceBaiDu::bankcard(const QImage &img) 396{ 397 QList<QHttpPart> httpParts; 398 httpParts << dataToHttpPart(getImageData(img), "image"); 399 400 QString url = QString("https://aip.baidubce.com/rest/2.0/ocr/v1/bankcard?access_token=%1").arg(tokenOcr); 401 sendData(url, httpParts); 402} 403 404void FaceBaiDu::driverLicense(const QImage &img) 405{ 406 QList<QHttpPart> httpParts; 407 httpParts << dataToHttpPart(getImageData(img), "image"); 408 409 QString url = QString("https://aip.baidubce.com/rest/2.0/ocr/v1/driving_license?access_token=%1").arg(tokenOcr); 410 sendData(url, httpParts); 411} 412 413void FaceBaiDu::vehicleLicense(const QImage &img) 414{ 415 QList<QHttpPart> httpParts; 416 httpParts << dataToHttpPart(getImageData(img), "image"); 417 418 QString url = QString("https://aip.baidubce.com/rest/2.0/ocr/v1/vehicle_license?access_token=%1").arg(tokenOcr); 419 sendData(url, httpParts); 420}