
关于人脸识别这块,前些年不要太火,哪怕是到了今天依然火的一塌糊涂,什么玩意都要跟人脸识别搭个边,这东西应该只是人工智能的一个很小的部分,人脸识别光从字面上理解就是识别出人脸区域,其实背后真正的处理是拿到人脸区域图片,提取人脸特征值,再用这些特征值去做比对分析处理,识别出到底是谁,国内厂家也不少,比拼的就是准确度误报率,速度无非就是靠堆硬件来,什么VPU各种并行运算都堆上去,速度杠杠的,好多厂家都做到了几个毫秒的级别,估计很多厂家都是在开源的基础上加上了自家的算法,一直跑呀跑的整出了符合自家算法的人脸模型文件,比如百度的人脸识别模型文件,经过好几年的发展,越来越大越来越细越来越准。
听某个大神说过,很多时候人工智能其实并不是完全的智能,绝大部分都停留在半智能阶段,而且这种半智能阶段还需要借助很多辅助的硬件甚至人为的判断,很多模型库文件的生成就是靠一小小姑娘在那边流水线上类似的不停的点呀点,号称深度学习算法,就是让他识别更多的数据,使得更准确。关于人脸识别或者人工智能,外行一般觉得很科幻,内行一般觉得很绝望,业界领袖和领袖各种打鸡血。
国内的厂家大部分都提供了官网对应的api来进行处理,注册个账号,搞个key,直接就可以撸起来,关于这块技术上没有任何难点,初学者都可以搞定,无非就是先post数据,拿到返回的数据进行解析,要搞清楚的就是如何填充要post的数据,比如带上key,组织其他数据比如图片是base64字符串上传还是二进制文件上传等,返回的数据都是json啦,直接用现成的json库进行解析就ok。
百度人脸识别在线版和离线版SDK的封装:

void FaceWebBaiDu::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()) {
            this->token = token;
            emit receiveResult(0, "鉴权标识返回成功");
            return;
        }
        //通用返回结果字段
        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()) {
            //人脸识别
            if (data.contains("location")) {
                QScriptValue face_list = result.property("face_list");
                checkFaceList(face_list);
            }
            //人脸比对
            if (data.contains("score") && !data.contains("location")) {
                QScriptValue score = result.property("score");
                float result = score.toString().toFloat();
                if (result > 0) {
                    emit receiveFaceCompare(QRect(), QRect(), result);
                } else {
                    emit receiveFaceCompareFail();
                }
            }
            //活体检测
            if (data.contains("face_liveness")) {
                QScriptValue face_liveness = result.property("face_liveness");
                float result = face_liveness.toString().toFloat();
                if (result >= 0) {
                    emit receiveLive(result);
                }
            }           
        }        
    }
}
void FaceWebBaiDu::checkFaceList(const QScriptValue &scriptValue)
{
    //创建迭代器逐个解析具体值
    QScriptValueIterator it(scriptValue);
    while (it.hasNext()) {
        it.next();
        if (it.flags() & QScriptValue::SkipInEnumeration) {
            continue;
        }
        QRect rect;
        QString face_token = it.value().property("face_token").toString();
        if (!face_token.isEmpty()) {
            QScriptValue value = it.value().property("location");
            rect = FaceHelper::getRect(value);
        }
        if (rect.width() > 0) {
            emit receiveFaceRect(rect);
            break;
        }
    }
}
void FaceWebBaiDu::getToken()
{
    //具体参见 http://ai.baidu.com/ai-doc/REFERENCE/Ck3dwjhhu
    QStringList list;
    list.append(QString("grant_type=%1").arg("client_credentials"));
    list.append(QString("client_id=%1").arg(key));
    list.append(QString("client_secret=%1").arg(secret));
    QString data = list.join("&");
    QString url = "https://aip.baidubce.com/oauth/2.0/token";
    FaceHelper::sendData(manager, url, data);
}
void FaceWebBaiDu::detect(const QImage &img)
{
    QString imgData = FaceHelper::getImageData2(img);
    QStringList list;
    list.append(QString("{\"image\":\"%1\",\"image_type\":\"BASE64\"}").arg(imgData));
    QString data = list.join("");
    QString url = QString("https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=%1").arg(token);
    FaceHelper::sendData(manager, url, data);
}
void FaceWebBaiDu::compare(const QImage &img1, const QImage &img2)
{
    QString imgData1 = FaceHelper::getImageData2(img1);
    QString imgData2 = FaceHelper::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(token);
    FaceHelper::sendData(manager, url, data);
}
void FaceWebBaiDu::live(const QImage &img)
{
    QList<QImage> imgs;
    if (!img.isNull()) {
        imgs << img;
    }
    live(imgs);
}
void FaceWebBaiDu::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 = FaceHelper::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(token);
    FaceHelper::sendData(manager, url, data);
}原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。