qt编写百度离线版人脸识别+比对+活体检测

feiyangqingyun feiyangqingyun     2022-12-31     656

关键词:

在AI技术发展迅猛的今天,很多设备都希望加上人脸识别功能,好像不加上点人脸识别功能感觉不够高大上,都往人脸识别这边靠,手机刷脸解锁,刷脸支付,刷脸开门,刷脸金融,刷脸安防,是不是以后还可以刷脸匹配男女交友?
很多人认为人脸识别直接用opencv做,其实那只是极其基础的识别个人脸,然并卵,好比学C++写了个hello类似。拿到人脸区域图片只是万里长征的第一步,真正能够起作用的是人脸特征值的提取,然后用于搜索和查找人脸,比如两张图片比较相似度,从一堆人脸库中找到最相似的人脸,对当前人脸识别是否是活体等。
对于可以接入外网的设备,可以直接通过在线api的http请求方式获得结果,但是有很多应用场景是离线的,或者说不通外网,只能局域网使用,为了安全性考虑,这个时候就要求所有的人脸处理在本地完成,本篇文章采用的百度离线SDK作为解决方案。可以去官网申请,默认有6个免费的密钥使用三个月,需要与本地设备的指纹信息匹配,感兴趣的同学可以自行去官网下载SDK。
百度离线人脸识别SDK文件比较大,光模型文件就645MB,估计这也许是识别率比较高的一方面原因吧,不断训练得出的模型库,本篇文章只放出Qt封装部分源码。官网对应的使用说明还是非常详细的,只要是学过编程的人就可以看懂。
第一步:初始化SDK
第二步:执行动作,比如查找人脸、图片比对、特征值比对等

技术分享图片技术分享图片技术分享图片技术分享图片技术分享图片

 

完整头文件代码:

#ifndef FACEBAIDULOCAL_H
#define FACEBAIDULOCAL_H

/**
 * 百度离线版人脸识别+人脸比对等功能类 作者:feiyangqingyun(QQ:517216493) 2018-8-30
 * 1:支持活体检测
 * 2:可设置最大队列中的图片数量
 * 3:多线程处理,通过type控制当前处理类型
 * 4:支持单张图片检索相似度最高的图片
 * 5:支持指定目录图片生成特征文件
 * 6:支持两张图片比对方式
 * 7:可设置是否快速查找
 * 8:可设置是否统计用时
 */

#include <QtCore>
#include <QtGui>
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
#include <QtWidgets>
#endif
#include "baidu_face_api.h"

class FaceBaiDuLocal : public QThread

    Q_OBJECT
public:
    static FaceBaiDuLocal *Instance();
    explicit FaceBaiDuLocal(QObject *parent = 0);
    ~FaceBaiDuLocal();

protected:
    void run();

private:
    static QScopedPointer<FaceBaiDuLocal> self;

    BaiduFaceApi *api;
    std::vector<TrackFaceInfo> *faces;

    QMutex mutex;                   //锁对象
    bool stopped;                   //线程停止标志位

    int maxCount;                   //最大图片张数
    int type;                       //当前处理类型
    int percent;                    //最小人脸百分比
    int delayms;                    //减去毫秒数,用于造假
    bool findFast;                  //是否快速模式
    bool countTime;                 //统计用时
    bool busy;                      //是否正忙

    QList<QString> flags;           //等待处理的图像队列的名称
    QList<QImage> imgs;             //等待处理的图像队列
    QList<QImage> imgs2;            //等待处理的比对图像队列

    QString sdkPath;                //SDK目录
    QString imgDir;                 //图片目录
    QImage oneImg;                  //单张图片比对找出最大特征图像
    QList<QString> imgNames;        //图像队列
    QList<QList<float> > features;  //特征队列

signals:
    //人脸区域坐标返回
    void receiveFaceRect(const QString &flag, const QRect &rect, int msec);
    //获取人脸区域坐标失败
    void receiveFaceRectFail(const QString &flag);

    //人脸特征返回
    void receiveFaceFeature(const QString &flag, const QList<float> &feature, int msec);
    //获取人脸特征失败
    void receiveFaceFeatureFail(const QString &flag);

    //人脸比对结果返回
    void receiveFaceCompare(const QString &flag, float result, int msec);
    //人脸比对失败
    void receiveFaceCompareFail(const QString &flag);

    //单张图片检索最大相似度结果返回
    void receiveFaceCompareOne(const QString &flag, const QImage &srcImg, const QString &targetName, float result);
    //所有人脸特征提取完毕
    void receiveFaceFeatureFinsh();

    //活体检测返回
    void receiveFaceLive(const QString &flag, float result, int msec);
    //活体检测失败
    void receiveFaceLiveFail(const QString &flag);

public slots:
    //初始化SDK
    void init();
    //停止处理线程
    void stop();
    //获取当前是否忙
    bool getBusy();

    //设置图片队列最大张数
    void setMaxCount(int maxCount);
    //设置当前处理类型
    void setType(int type);
    //设置最小人脸百分比
    void setPercent(int percent);
    //设置减去毫秒数
    void setDelayms(int delayms);
    //设置是否快速模式
    void setFindFast(bool findFast);
    //设置是否统计用时
    void setCountTime(bool countTime);
    //设置是否忙
    void setBusy(bool busy);

    //设置SDK目录
    void setSDKPath(const QString &sdkPath);
    //设置要将图片提取出特征的目录
    void setImgDir(const QString &imgDir);
    //设置单张需要检索的图片
    void setOneImg(const QString &flag, const QImage &oneImg);

    //往队列中追加单张图片等待处理
    void append(const QString &flag, const QImage &img);
    //往队列中追加两张图片等待比对
    void append(const QString &flag, const QImage &img, const QImage &img2);


    //自动加载目录下的所有图片的特征
    void getFaceFeatures(const QString &imgDir);

    //获取人脸区域
    bool getFaceRect(const QString &flag, const QImage &img, QRect &rect, int &msec);

    //活体检测
    bool getFaceLive(const QString &flag, const QImage &img, float &result, int &msec);

    //获取人脸特征
    bool getFaceFeature(const QString &flag, const QImage &img, QList<float> &feature, int &msec);

    //人脸比对,传入两张照片特征
    float getFaceCompare(const QString &flag, const QList<float> &feature1, const QList<float> &feature2);
    //人脸比对,传入两张照片
    bool getFaceCompare(const QString &flag, const QImage &img1, const QImage &img2, float &result, int &msec);

    //从一堆图片中找到最像的一张图片
    void getFaceOne(const QString &flag, const QImage &img, QString &targetName, float &result);
    //指定特征找到照片
    void getFaceOne(const QString &flag, const QList<float> &feature, QString &targetName, float &result);

    //添加人脸
    void appendFace(const QString &flag, const QImage &img, const QString &txtFile);
    //删除人脸
    void deleteFace(const QString &flag);
;

#endif // FACEBAIDULOCAL_H

完整实现文件代码:

#include "facebaidulocal.h"

#define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))

QByteArray getImageData(const QImage &image)

    QByteArray imageData;
    QBuffer buffer(&imageData);
    image.save(&buffer, "JPG");
    imageData = imageData.toBase64();
    return imageData;


QScopedPointer<FaceBaiDuLocal> FaceBaiDuLocal::self;
FaceBaiDuLocal *FaceBaiDuLocal::Instance()

    if (self.isNull()) 
        QMutex mutex;
        QMutexLocker locker(&mutex);
        if (self.isNull()) 
            self.reset(new FaceBaiDuLocal);
        
    

    return self.data();


FaceBaiDuLocal::FaceBaiDuLocal(QObject *parent) : QThread(parent)

    //注册信号中未知的数据类型
    qRegisterMetaType<QList<float> >("QList<float>");
    stopped = false;

    maxCount = 100;
    type = 1;
    percent = 8;
    delayms = 0;
    findFast = false;
    countTime = true;
    busy = false;

    sdkPath = qApp->applicationDirPath() + "/facesdk";
    imgDir = "";
    oneImg = QImage();

    api = new BaiduFaceApi;
    faces = new std::vector<TrackFaceInfo>();


FaceBaiDuLocal::~FaceBaiDuLocal()

    delete api;
    this->stop();
    this->wait(1000);


void FaceBaiDuLocal::run()

    this->init();
    while(!stopped) 
        int count = flags.count();
        if (count > 0) 
            QMutexLocker lock(&mutex);
            busy = true;
            if (type == 0) 
                QString flag = flags.takeFirst();
                QImage img = imgs.takeFirst();

                QRect rect;
                int msec;
                if (getFaceRect(flag, img, rect, msec)) 
                    emit receiveFaceRect(flag, rect, msec);
                 else 
                    emit receiveFaceRectFail(flag);
                
             else if (type == 1) 
                QString flag = flags.takeFirst();
                QImage img = imgs.takeFirst();

                QList<float> feature;
                int msec;
                if (getFaceFeature(flag, img, feature, msec)) 
                    emit receiveFaceFeature(flag, feature, msec);
                 else 
                    emit receiveFaceFeatureFail(flag);
                
             else if (type == 2) 
                QString flag = flags.takeFirst();
                QImage img1 = imgs.takeFirst();
                QImage img2 = imgs2.takeFirst();

                float result;
                int msec;
                if (getFaceCompare(flag, img1, img2, result, msec)) 
                    emit receiveFaceCompare(flag, result, msec);
                 else 
                    emit receiveFaceCompareFail(flag);
                
             else if (type == 3) 
                flags.takeFirst();

                getFaceFeatures(imgDir);
             else if (type == 4) 
                QString flag = flags.takeFirst();

                QString targetName;
                float result;
                getFaceOne(flag, oneImg, targetName, result);
                if (!targetName.isEmpty()) 
                    emit receiveFaceCompareOne(flag, oneImg, targetName, result);
                
             else if (type == 5) 
                QString flag = flags.takeFirst();
                QImage img = imgs.takeFirst();

                float result;
                int msec;
                if (getFaceLive(flag, img, result, msec)) 
                    emit receiveFaceLive(flag, result, msec);
                 else 
                    emit receiveFaceLiveFail(flag);
                
            
        

        msleep(100);
        busy = false;
    

    stopped = false;


void FaceBaiDuLocal::init()

    int res = api->sdk_init();
    res = api->is_auth();
    if(res != 1) 
        qDebug() << TIMEMS << QString("init sdk error: %1").arg(res);
        return;
     else 
        //设置最小人脸,默认30
        api->set_min_face_size(percent);
        //设置光照阈值,默认40
        api->set_illum_thr(20);
        //设置角度阈值,默认15
        //api->set_eulur_angle_thr(30, 30, 30);
        qDebug() << TIMEMS << "init sdk ok";
    


void FaceBaiDuLocal::stop()

    stopped = true;


bool FaceBaiDuLocal::getBusy()

    return this->busy;


void FaceBaiDuLocal::setMaxCount(int maxCount)

    if (maxCount <= 1000) 
        this->maxCount = maxCount;
    


void FaceBaiDuLocal::setType(int type)

    if (this->type != type) 
        this->type = type;
        this->flags.clear();
        this->imgs.clear();
        this->imgs2.clear();
    


void FaceBaiDuLocal::setPercent(int percent)

    this->percent = percent;


void FaceBaiDuLocal::setDelayms(int delayms)

    this->delayms = delayms;


void FaceBaiDuLocal::setFindFast(bool findFast)

    this->findFast = findFast;


void FaceBaiDuLocal::setCountTime(bool countTime)

    this->countTime = countTime;


void FaceBaiDuLocal::setBusy(bool busy)

    this->busy = busy;


void FaceBaiDuLocal::setSDKPath(const QString &sdkPath)

    this->sdkPath = sdkPath;


void FaceBaiDuLocal::setImgDir(const QString &imgDir)

    this->imgDir = imgDir;
    this->flags.clear();
    this->flags.append("imgDir");
    this->type = 3;


void FaceBaiDuLocal::setOneImg(const QString &flag, const QImage &oneImg)

    setType(4);

    //需要将图片重新拷贝一个,否则当原图像改变之后也会改变
    this->oneImg = oneImg.copy();
    this->flags.append(flag);


void FaceBaiDuLocal::append(const QString &flag, const QImage &img)

    QMutexLocker lock(&mutex);
    int count = flags.count();
    if (count < maxCount) 
        flags.append(flag);
        imgs.append(img);
    


void FaceBaiDuLocal::append(const QString &flag, const QImage &img, const QImage &img2)

    QMutexLocker lock(&mutex);
    int count = flags.count();
    if (count < maxCount) 
        flags.append(flag);
        imgs.append(img);
        imgs2.append(img2);
    


void FaceBaiDuLocal::getFaceFeatures(const QString &imgDir)

    imgNames.clear();
    features.clear();

    //载入指定目录图像处理特征
    QDir imagePath(imgDir);
    QStringList filter;
    filter << "*.jpg" << "*.bmp" << "*.png" << "*.jpeg" << "*.gif";
    imgNames.append(imagePath.entryList(filter));

    qDebug() << TIMEMS << "getFaceFeatures" << imgNames;

    //从目录下读取同名的txt文件(存储的特征)
    //如果存在则从文件读取特征,如果不存在则转码解析出特征
    //转码完成后将得到的特征存储到同名txt文件
    int count = imgNames.count();
    for (int i = 0; i < count; i++) 
        QList<float> feature;
        int msec;

        QString imgName = imgNames.at(i);
        QStringList list = imgName.split(".");
        QString txtName = imgDir + "/" + list.at(0) + ".txt";
        QFile file(txtName);

        if (file.exists()) 
            if (file.open(QFile::ReadOnly)) 
                QString data = file.readAll();
                file.close();

                qDebug() << TIMEMS << "readFaceFeature" << txtName;

                QStringList list = data.split(",");
                foreach (QString str, list) 
                    if (!str.isEmpty()) 
                        feature.append(str.toFloat());
                    
                
            
         else 
            QImage img(imgDir + "/" + imgName);
            bool ok = getFaceFeature(imgName, img, feature, msec);

            if (ok) 
                emit receiveFaceFeature(imgName, feature, msec);
                if (file.open(QFile::WriteOnly)) 
                    QStringList list;
                    foreach (float fea, feature) 
                        list.append(QString::number(fea));
                    

                    qDebug() << TIMEMS << "writeFaceFeature" << txtName;

                    file.write(list.join(",").toLatin1());
                    file.close();
                
            
        

        features.append(feature);
        msleep(1);
    

    qDebug() << TIMEMS << "getFaceFeatures finsh";
    emit receiveFaceFeatureFinsh();


bool FaceBaiDuLocal::getFaceRect(const QString &flag, const QImage &img, QRect &rect, int &msec)

    //qDebug() << TIMEMS << flag << "getFaceRect";

    QTime time;
    if (countTime) 
        time.start();
    

    faces->clear();
    QByteArray imageData = getImageData(img);
    int result = api->track_max_face(faces, imageData.constData(), 1);

    if (result == 1) 
        TrackFaceInfo info = faces->at(0);
        FaceInfo ibox = info.box;
        float width = ibox.mWidth;
        float x = ibox.mCenter_x;
        float y = ibox.mCenter_y;

        rect = QRect(x - width / 2, y - width / 2, width, width);
        if (countTime) 
            msec = time.elapsed() - delayms;
         else 
            msec = delayms;
        

        msec = msec < 0 ? 0 : msec;
        return true;
     else 
        return false;
    

    return false;


bool FaceBaiDuLocal::getFaceLive(const QString &flag, const QImage &img, float &result, int &msec)

    //qDebug() << TIMEMS << flag << "getFaceLive";

    QTime time;
    if (countTime) 
        time.start();
    

    result = 0;
    QByteArray imageData = getImageData(img);
    std::string value = api->rgb_liveness_check(imageData.constData(), 1);

    QString data = value.c_str();
    data = data.replace("	", "");
    data = data.replace(""", "");
    data = data.replace(" ", "");

    int index = -1;
    QStringList list = data.split("
");
    foreach (QString str, list) 
        index = str.indexOf("score:");
        if (index >= 0) 
            result = str.mid(6, 4).toFloat();
            break;
        
    

    if (index >= 0) 
        if (countTime) 
            msec = time.elapsed() - delayms;
         else 
            msec = delayms;
        

        msec = msec < 0 ? 0 : msec;
        return true;
     else 
        return false;
    

    return false;


bool FaceBaiDuLocal::getFaceFeature(const QString &flag, const QImage &img, QList<float> &feature, int &msec)

    //qDebug() << TIMEMS << flag << "getFaceFeature" << img.width() << img.height() << img.size();

    QTime time;
    if (countTime) 
        time.start();
    

    const float *fea = nullptr;
    QByteArray imageData = getImageData(img);
    int result = api->get_face_feature(imageData.constData(), 1, fea);

    if (result == 512) 
        feature.clear();
        for (int i = 0; i < 512; i++) 
            feature.append(fea[i]);
        

        if (countTime) 
            msec = time.elapsed() - delayms;
         else 
            msec = delayms;
        

        msec = msec < 0 ? 0 : msec;
        return true;
     else 
        return false;
    

    return false;


float FaceBaiDuLocal::getFaceCompare(const QString &flag, const QList<float> &feature1, const QList<float> &feature2)

    //qDebug() << TIMEMS << flag << "getFaceCompareXXX";

    std::vector<float> fea1, fea2;
    for (int i = 0; i < 512; i++) 
        fea1.push_back(feature1.at(i));
        fea2.push_back(feature2.at(i));
    

    float result = api->compare_feature(fea1, fea2);
    //过滤非法的值
    result = result > 100 ? 0 : result;
    return result;


bool FaceBaiDuLocal::getFaceCompare(const QString &flag, const QImage &img1, const QImage &img2, float &result, int &msec)

    //qDebug() << TIMEMS << flag << "getFaceCompare";

    result = 0;
    bool ok1, ok2;
    QList<float> feature1, feature2;
    int msec1, msec2;
    QString flag1, flag2;
    if (flag.contains("|")) 
        QStringList list = flag.split("|");
        flag1 = list.at(0);
        flag2 = list.at(1);
     else 
        flag1 = flag;
        flag2 = flag;
    

    QTime time;
    if (countTime) 
        time.start();
    

    ok1 = getFaceFeature(flag1, img1, feature1, msec1);
    if (ok1) 
        emit receiveFaceFeature(flag1, feature1, msec1);
    

    ok2 = getFaceFeature(flag2, img2, feature2, msec2);
    if (ok2) 
        emit receiveFaceFeature(flag2, feature2, msec2);
    

    if (ok1 && ok2) 
        result = getFaceCompare(flag, feature1, feature2);

        if (countTime) 
            msec = time.elapsed() - delayms;
         else 
            msec = delayms;
        

        msec = msec < 0 ? 0 : msec;
        return true;
     else 
        return false;
    

    return false;


void FaceBaiDuLocal::getFaceOne(const QString &flag, const QImage &img, QString &targetName, float &result)

    QList<float> feature;
    int msec;
    bool ok = getFaceFeature(flag, img, feature, msec);
    if (ok) 
        emit receiveFaceFeature(flag, feature, msec);
        getFaceOne(flag, feature, targetName, result);
    


void FaceBaiDuLocal::getFaceOne(const QString &flag, const QList<float> &feature, QString &targetName, float &result)

    //用当前图片的特征与特征数据库比对
    result = 0;
    int count = imgNames.count();
    for (int i = 0; i < count; i++) 
        QString imgName = imgNames.at(i);
        float currentResult = getFaceCompare(flag, feature, features.at(i));
        //qDebug() << TIMEMS << "getFaceOne" << imgName << currentResult;

        if (currentResult > result) 
            result = currentResult;
            targetName = imgName;
        
    

    qDebug() << TIMEMS << "getFaceOne result" << targetName << result;


void FaceBaiDuLocal::appendFace(const QString &flag, const QImage &img, const QString &txtFile)

    QList<float> feature;
    int msec;

    QImage image = img;
    bool ok = getFaceFeature(flag, image, feature, msec);
    msleep(100);

    qDebug() << TIMEMS << "getFaceFeature result" << ok << "appendFace" << txtFile;

    if (ok) 
        emit receiveFaceFeature(flag, feature, msec);

        //保存txt文件
        QFile file(txtFile);
        if (file.open(QFile::WriteOnly)) 
            QStringList list;
            foreach (float fea, feature) 
                list.append(QString::number(fea));
            

            file.write(list.join(",").toLatin1());
            file.close();
        

        //保存图片文件
        QString imgName = txtFile;
        imgName = imgName.replace("txt", "jpg");
        image.save(imgName, "jpg");

        imgNames.append(QFileInfo(imgName).fileName());
        features.append(feature);
    


void FaceBaiDuLocal::deleteFace(const QString &flag)

    //从图片名称中找到标识符
    int index = imgNames.indexOf(flag);
    if (index >= 0) 
        imgNames.removeAt(index);
        features.removeAt(index);

        //删除图片文件
        QString imgFileName = QString("%1/face/%2.jpg").arg(qApp->applicationDirPath()).arg(flag);
        QFile imgFile(imgFileName);
        imgFile.remove();
        qDebug() << TIMEMS << "delete faceImage" << imgFileName;

        //删除特征文件
        QString txtFileName = QString("%1/face/%2.txt").arg(qApp->applicationDirPath()).arg(flag);
        QFile txtFile(txtFileName);
        txtFile.remove();
        qDebug() << TIMEMS << "delete faceTxt" << txtFileName;
    

人脸识别中的活体检测是啥?

...频在摄像头来测试的话,是不可能通过的。,屏管家采用百度深度AI人脸识别就完全可以解决这个问题 参考技术B活体检测就是能通过眨眼、张嘴、摇头、点头等组合动作,使用人脸关键点定位和人脸追踪等技术,验证用户是否... 查看详情

虹软人脸识别活体检测有没有用过的,效果怎么样?

...较高,用起来也比较方便。 参考技术C没有用过,查一下百度便知效果 参考技术D可以也挺灵的 第5个回答 2019-04-18没有用过到听说功能很强大的 查看详情

多维活体检测,让人脸识别更安全

今年的315晚会提到人脸识别领域的安全风险,主持人用现场合成的视频通过了活体检测和人脸验证,因此人脸识别的安全性引起大众关注。对于活体检测的安全隐患,腾讯优图团队一直保持高度关注,并依托多年积累的技术能力... 查看详情

多维活体检测,让人脸识别更安全

今年的315晚会提到人脸识别领域的安全风险,主持人用现场合成的视频通过了活体检测和人脸验证,因此人脸识别的安全性引起大众关注。对于活体检测的安全隐患,腾讯优图团队一直保持高度关注,并依托多年积累的技术能力... 查看详情

为啥人脸识别要用彩灯

参考技术A活体检测一种。离线3D结构光活体检测-->基于3D结构光成像原理,通过人脸表面反射光线构建深度图像,判断目标是否为活体,可强效防御图片、视频、屏幕、模具等攻击。3D结构光成像是将图案投影到三维空间物体表... 查看详情

人脸识别中活体检测的重要性是啥?

是防止被攻击欺诈,提高安全性。人脸活体检测主要是通过识别活体上的生理信息来进行,它把生理信息作为生命特征来区分用照片、硅胶、塑料等非生命物质假座的生物特征。一旦虚假人脸攻击成功,极有可能对用户造成重大... 查看详情

人脸检测实战进阶:使用opencv进行活体检测(代码片段)

...体检测。您将创建一个活体检测器,该检测器能够在人脸识别系统中发现假人脸并执行反人脸欺骗。在教程的第一部分,我们将讨论活体检测,包括它是什么以及我们为什么需要它来改进我们的人脸识别系统。从那里... 查看详情

基于android虹软人脸人证对比,活体检测

最近虹软新增了人证识别、活体检测的功能,好像之前的人脸识别也更新过版本,之前一篇文章用虹软AndroidSDK做人脸识别,写过虹软人脸识别的用法,最近把人脸识别、人证识别,活体检测功能都简单的封装了一下,使用起来... 查看详情

netcore百度人脸识别httpsdk实战:基于c#asp.netcorenet6(代码片段)

预计这是第一篇介绍在ASP.NETCORE3.1平台下使用百度人脸识别在线sdk的文章,主要介绍人脸1:n检测/活体检验/人脸注册三大关键功能。先看几个效果图吧(1)人脸1:N检测,返回人脸对应用户信息(2࿰... 查看详情

如何通过活体检测

...[1]在一些身份验证场景确定对象真实生理特征的方法,在人脸识别应用中,活体检测能通过眨眼、张嘴、摇头、点头等组合动作,使用人脸关键点定位和人脸追踪等技术,验证用户是否为真实活体本人操作。可有效抵御照片、换... 查看详情

人脸活体检测人脸识别:眨眼+张口(代码片段)

一:dlib的shape_predictor_68_face_landmarks模型该模型能够检测人脸的68个特征点(faciallandmarks),定位图像中的眼睛,眉毛,鼻子,嘴巴,下颌线(ROI,RegionofInterest) 下颌线 查看详情

android人脸识别sdk有没有离线版的?

...,你可以去官网了解一下,他们的SDK是免费提供的,可以离线使用,在该有的准确率和速度的基础上,安全性也比较高。 参考技术B安卓的SDK离线的有虹软的,局域网和联网都能行,基本特征提取时间在400-600ms,看设备配置了本回... 查看详情

人脸识别活体检测技术讨论:基于背景人脸相对运动的活体判断方法

活体检测是人脸识别安全性的重要保障,是人脸识别厂商将产品普及应用于各行业的重要竞争力。目前活体判断的方法很多,但很难基于一种方法就能达到理想的效果,往往需要多种算法的交叉判断,本文主要介绍一种简单有效... 查看详情

opencv-活体检测

▲项目目的:识别真实人脸和照片,实现“识真”而不止“识脸”。▲使用工具:opencv,python,matlab首先1.构建图像数据集2.实现一个能够进行活体检测的卷积神经网络(我们称之为「LivenessNet」)3.训练活体检测网络... 查看详情

人脸识别sdk虹软的好用吗?

...API能力,适配多种软硬件环境,根据业务需求灵活使用;离线SDK/用户自主可控,信息更加安全;多平台支持/支持iOS,Windows,Linux,Android,满足开发者的各种环境需求。推荐~~ 第5个回答 2020-07-20是功能很全,安全性比较高的... 查看详情

华为机器学习服务活体检测再升级,构建安全友好的交互式体验

人脸识别技术被广泛应用于公共安全、金融支付、交通安全等领域。使用较多的场景是用户通过智能手机上的人脸识别技术完成解锁、支付等动作,俗称“刷脸”,还有一些开发者会在应用中集成人脸识别技术便于用户... 查看详情

华为机器学习服务活体检测再升级,构建安全友好的交互式体验

人脸识别技术被广泛应用于公共安全、金融支付、交通安全等领域。使用较多的场景是用户通过智能手机上的人脸识别技术完成解锁、支付等动作,俗称“刷脸”,还有一些开发者会在应用中集成人脸识别技术便于用户... 查看详情

人脸识别模型的动手实践!

作者:宋志龙 来源:Datawhale人脸识别已经成为生活中越来越常见的技术,其中最关键的问题就是安全,而活体检测技术又是保证人脸识别安全性的一个重要手段,本文将向大家简单介绍活体检测,并动手... 查看详情