2

AI的发展在最近几年如火如荼,工资待遇也是水涨船高,应用的前景也是非常广阔,去年火起来的人脸识别,今年全国遍地开花。看了下百度的AI,还免费了,效果也是越来越好,活体检测这个算法更是做的吊炸天(只需要传一张图片就能判断图片中的人是翻拍的照片非活体),牛逼的一塌糊涂,我反正是跪了。百度AI在未来的国内AI市场中,不是第一就是第二,而且会持续保持至少十年。

图片描述

1:可识别身份证正面信息+背面信息

2:可识别银行卡信息

3:可识别驾驶证+行驶证信息

4:可进行人脸识别,人脸比对,活体检测

5:可设置请求地址+用户密钥+应用密钥

6:直接传入图片即可,信号返回,毫秒级极速响应

7:通用Qt4-Qt5,windows linux 嵌入式linux
下面看一下演示效果

clipboard.png

图片描述

当然下面这个是识别不了的

当然这个是识别不了的
clipboard.png

  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}

爱码小士
173 声望15 粉丝

在此我向大家推荐一个我的技术交流群。