首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Qt音视频开发39-人脸识别在线版

Qt音视频开发39-人脸识别在线版

原创
作者头像
feiyangqingyun
修改于 2020-10-26 04:06:38
修改于 2020-10-26 04:06:38
1.8K0
举报
文章被收录于专栏:Qt项目实战Qt项目实战

一、前言

关于人脸识别这块,前些年不要太火,哪怕是到了今天依然火的一塌糊涂,什么玩意都要跟人脸识别搭个边,这东西应该只是人工智能的一个很小的部分,人脸识别光从字面上理解就是识别出人脸区域,其实背后真正的处理是拿到人脸区域图片,提取人脸特征值,再用这些特征值去做比对分析处理,识别出到底是谁,国内厂家也不少,比拼的就是准确度误报率,速度无非就是靠堆硬件来,什么VPU各种并行运算都堆上去,速度杠杠的,好多厂家都做到了几个毫秒的级别,估计很多厂家都是在开源的基础上加上了自家的算法,一直跑呀跑的整出了符合自家算法的人脸模型文件,比如百度的人脸识别模型文件,经过好几年的发展,越来越大越来越细越来越准。

听某个大神说过,很多时候人工智能其实并不是完全的智能,绝大部分都停留在半智能阶段,而且这种半智能阶段还需要借助很多辅助的硬件甚至人为的判断,很多模型库文件的生成就是靠一小小姑娘在那边流水线上类似的不停的点呀点,号称深度学习算法,就是让他识别更多的数据,使得更准确。关于人脸识别或者人工智能,外行一般觉得很科幻,内行一般觉得很绝望,业界领袖和领袖各种打鸡血。

国内的厂家大部分都提供了官网对应的api来进行处理,注册个账号,搞个key,直接就可以撸起来,关于这块技术上没有任何难点,初学者都可以搞定,无非就是先post数据,拿到返回的数据进行解析,要搞清楚的就是如何填充要post的数据,比如带上key,组织其他数据比如图片是base64字符串上传还是二进制文件上传等,返回的数据都是json啦,直接用现成的json库进行解析就ok。

百度人脸识别在线版和离线版SDK的封装:

  1. 离线版要求支持C++11的编译器,而且必须为MSVC。不支持mingw编译器。
  2. 在线版中的密钥等信息,务必记得换成自己申请的。
  3. 离线版本只能在windows上使用。
  4. 离线版本需要自己申请密钥。找到facebaidusdk文件夹下的LicenseTool.exe,填写后台离线SDK管理中申请到的序列号,单击激活按钮。
  5. 离线版本对应的动态库和模型文件自行从官网下载。
  6. 如果源码包中有facebaidusdk+face-resource文件夹则说明带了动态库和模型库文件夹,只需要将facebaidusdk文件夹下的所有文件复制到可执行文件同一目录,face-resource文件夹复制到可执行文件夹目录同等级目录即可。目录位置见snap文件夹下的示例图。
  7. facebaidusdk目录下的TestFaceApi.exe为百度提供的测试程序,先要将USB摄像头插到电脑上,会实时找人脸框。

二、功能特点

  1. 支持的功能包括人脸识别、人脸比对人脸搜索、活体检测等。
  2. 在线版还支持身份证、驾驶证、行驶证、银行卡等识别。
  3. 在线版的协议支持百度、旷视,离线版的支持百度,可定制。
  4. 除了支持X86架构,还支持嵌入式linux比如contex-A9、树莓派等。
  5. 每个功能的执行除了返回结果还返回执行用时时间。
  6. 多线程处理,通过type控制当前处理类型。
  7. 支持单张图片检索相似度最高的图片。
  8. 支持指定目录图片用来生成人脸特征值文件。
  9. 可设置等待处理图片队列中的数量。
  10. 每次执行都有成功或者失败的信号返回。
  11. 人脸搜索的返回结果包含了原图+最大相似度图+相似度等。
  12. 人脸比对同时支持两张图片和两个特征值比对。
  13. 相关功能自定义一套协议用于客户端和服务端,可以通过TCP通信进行交互。
  14. 自定义人脸识别协议非常适用于中心一台服务器,现场若干设备请求的场景。
  15. 每个模块全部是独立的一个类,代码整洁、注释完善。

三、效果图

QQ截图20200504195214.jpg
QQ截图20200504195214.jpg

四、相关站点

  1. 国内站点:https://gitee.com/feiyangqingyun/QWidgetDemo
  2. 国际站点:https://github.com/feiyangqingyun/QWidgetDemo
  3. 个人主页:https://blog.csdn.net/feiyangqingyun
  4. 知乎主页:https://www.zhihu.com/people/feiyangqingyun/
  5. 体验地址:https://blog.csdn.net/feiyangqingyun/article/details/97565652

五、核心代码

代码语言:txt
AI代码解释
复制
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 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Qt音视频开发43-人脸识别服务端
上一篇文章写道人脸识别客户端程序,当然要对应一个服务端程序,客户端才能正常运行,毕竟客户端程序需要与服务端程序进行交互他才能正常工作。通常人脸识别服务端程序需要和人脸识别的相关处理库在一起,这样他接收到相关的处理需求以后比如人脸识别的处理请求,需要调用本地的人脸识别库来处理,处理完成以后拿到结果,再组成协议的格式返回给客户端程序。
feiyangqingyun
2020/10/30
8820
Qt音视频开发43-人脸识别服务端
Qt音视频开发40-人脸识别离线版
上一篇文章写了在线调用人脸识别api进行处理,其实很多的客户需求是要求离线使用的,尤其是一些事业单位,严禁这些刷脸数据外泄上传到服务器,尽管各个厂家号称严格保密这些数据,但要阻止这些担心,唯一的解决办法就是设备离线使用,连个屁的网,不联网看你怎么上传,于是离线的人脸识别应用应运而生,比如我们手机上的识别就是本地库在运算,至于本地模型库估计会联网更新,以保持最新的状态。百度的离线人脸识别做的还行,看官网的sdk开发包,更新也是蛮快的,提供了windows、linux、android等版本。
feiyangqingyun
2020/10/27
1.1K0
Qt音视频开发40-人脸识别离线版
Qt音视频开发41-人脸识别嵌入式
大概几年前搞过一套嵌入式linux上的人脸识别程序,当然人脸识别的核心算法并不是自己开发的,关于人脸识别算法这一块,虽然有众多的开源库可以用,甚至还可以用opencv搞算法训练深度学习之类的,个人认为始终达不到准确度的要求,尤其是人脸比对的准确度,这个需要专业的人脸训练模型才行。目前市面上绝大部分的人脸识别库提供的都是X86的或者安卓ios的库,并没有嵌入式linux的库,估计一方面因为嵌入式linux跑的板子性能比较低,还有一个就是依赖特定编译器,版本众多难以提供,市场也小,所以大部分的厂家都没有提供嵌入式linux的开发包,这个就比较鸡肋,所以很多终端厂家最终弃用linux而选用安卓作为载体系统,这样就可以用上高大上的人脸识别库了,比如萤火虫开发板,RK3288 RK3399等。
feiyangqingyun
2020/10/28
1.1K0
Qt音视频开发41-人脸识别嵌入式
Qt音视频开发42-人脸识别客户端
人脸识别客户端程序,不需要和人脸识别相关的库在一起,而是通过协议通信来和人脸识别服务端通信交互,人脸识别客户端和服务端程序框架,主要是为了提供一套通用的框架,按照定好的协议,实现人脸识别的相关处理,很多厂家都会有也都会做类似的机制,以便第三方厂家或者自家的其他设备按照这个通信协议来处理,比如客户端程序可以在PC机上,也可以是网页,还可以是安卓客户端,前端设备比如人工访客机,访客机本地是不需要做人脸识别等处理的,而是发送到服务端处理完以后再拿到结果进行展示,这样就可以利用服务端强大的运算能力。
feiyangqingyun
2020/10/29
1K0
Qt音视频开发42-人脸识别客户端
人脸识别 | Java 实现 AI人工智能技术 - 人脸识别-附源码
一是这几天确实比较忙,工作是饭碗,不能砸了吧,不然康哥吃啥,孩子的奶粉又得买了。靠工资肯定不够奶粉啊,还得有自己的一些其他项目,您说对吧,另外还在总结《SpringBoot2.x企业实战教程》,这本电子书从入门到实战项目,总共20章,此处就不具体说了,等写完之后,再来吹吧。总之最近有点忙。
码神联盟
2018/08/27
16.5K13
人脸识别 | Java 实现 AI人工智能技术 - 人脸识别-附源码
Qt音视频开发45-视频传输TCP版
做音视频开发,会遇到将音视频重新转发出去的需求,当然终极大法是推流转发,还有一些简单的场景是直接自定义协议将视频传出去就行,局域网的话速度还是不错的。很多年前就做过类似的项目,无非就是将本地的图片上传到服务器,就这么简单,其实用http的post上传比较简单容易,无需自定义协议,直接设置好二进制数据即可,而采用TCP或者UDP通信的话,必须自定义协议,因为不知道什么时候数据接收完了是完整的图片数据,可能同时在发送很多图片数据,而且还不能区分收到的图片是哪个客户端发来的,TCP长连接的话,还需要有心跳来检测连接,所以必须自定义一套协议来支撑通信,这套协议采用的是上海监管平台的通信协议格式,拓展性比较强,其中头部信息包括了类型+当前完整包的数据长度,这个类型就是通信协议的标识,这样下次来一个其他类型的比如楼宇对讲可以叫IDOOR,服务端根据这个标识就能知道采用何种解析算法来处理后面的数据,而当前完整包的数据长度可以用来处理收到的数据,只有该长度的数据才表示接收完成一个完整的图片数据,再去解码处理。当传输的图片到了一定速度的时候比如一秒钟传输20张图片,其实就相当于传输视频了,一般人的肉眼看到一秒钟20张图片基本上认识就是视频了。
feiyangqingyun
2020/11/03
1.3K0
Qt音视频开发45-视频传输TCP版
Python有趣|寻找知乎最美小姐姐
本月将更新八篇Python有趣系列文章。本系列通过多个有趣案例,讲解Python的玩法,其中包含如下内容,一一推进讲解。
罗罗攀
2019/03/15
2.9K1
Python快速实现人脸识别
今天给大家带了的人脸识别非常简单,不需要大家了解TensorFlow,只需要对Python基本语法有一定了解。由于TensorFlow的火爆,把人脸识别再度推向我们的视线。像前段时间比较火的dee pfake,和人脸支付技术。虽然现阶段人脸识别仍有很大的争议性,但是它已经走进我们的视线当中了。很多小区在门禁系统中加入了人脸识别的功能,有些景区也添加了刷脸通道。但是对于技术的争议不是今天探讨的课题。下面开始我们的准备工作。
ZackSock
2020/02/14
2K0
PC人脸识别登录,出乎意料的简单
之前不是做了个开源项目嘛,在做完GitHub登录后,想着再显得有逼格一点,说要再加个人脸识别登录,就我这佛系的开发进度,过了一周总算是抽时间安排上了。
程序员小富
2020/07/29
2.7K2
PC人脸识别登录,出乎意料的简单
用Python寻找知乎最美小姐姐
导读:最近知乎老是给我推送两个问答,一个是「长得好看是种什么体验?」,另一个是「女朋友长得好看是怎样的体验?」。
IT阅读排行榜
2019/04/24
1.1K0
用Python寻找知乎最美小姐姐
Qt音视频开发38-USB摄像头解码linux方案
做嵌入式linux上的开发很多年了,扳手指头算算,也起码9年了,陆陆续续做过很过诸如需要读取外接的USB摄像头或者CMOS摄像机的程序,实时采集视频,将图像传到前端,或者对图像进行人脸分析处理,最开始尝试的就是QCamera来处理,直接歇菜放弃,后面通过搜索发现都说要用v4l2视频框架来进行,于是东搞搞西搞搞尝试了很多次,终于整出来了,前后完善了好几年,无论写什么程序,发现要简简单单的实现基础的功能,都是非常快速而且容易的,但是想要做得好做得精,要花不少的精力时间去完善,适应各种不同的场景,比如就说用v4l2加载摄像头这个,需要指定设备文件来读取,而现场不可能让用户来给你指定,频繁的拔插也会导致设备文件名的改动,所以必须找到一个机制自动寻找你想要的摄像机的设备文件名称,比如开个定时器去调用linux命令来处理,甚至在不同的系统平台上要执行的命令还有些许的区别,如果本地有多个摄像头还需要区分左右之类的时候,那就只能通过断电先后上电顺序次序来区分了。
feiyangqingyun
2020/10/21
2.9K0
Qt音视频开发38-USB摄像头解码linux方案
Qt音视频开发46-视频传输UDP版
上篇文章写道采用的TCP传输视频,优缺点很明显,优点就是不丢包,缺点就是速度慢,后面换成UDP通信,速度快了很多,少了3次握手,而且在局域网中基本上不丢包,就算偶尔丢包,对于一秒钟25-30张图片来说,偶尔一张图片丢失,基本上看不出来,所以忽略,但是放到广域网或者互联网比如阿里云平台上测试的话,UDP惨不忍睹,丢包蛮多的,毕竟包数据特别多。
feiyangqingyun
2020/11/04
1.2K0
Qt音视频开发46-视频传输UDP版
Qt音视频开发31-Onvif抓拍图片
抓拍是个很重要的功能,比如在报警视频联动中需要一张实时的图片,很多SDK不提供抓拍功能,而通过预览抓图,得到的图片已不具有实时性,那如何得到实时的图片呢?现在的IPC基本上都支持ONVIF协议,ONVIF协议除了提供RTSP的URL外,其实也给出了抓拍的URL,从Media的GetSnapshotUri获取。
feiyangqingyun
2020/10/10
1.4K0
Qt音视频开发31-Onvif抓拍图片
Qt音视频开发44-实时人脸框
在人脸识别到以后,需要在实时视频上将所有人脸框绘制出来,一把来说识别人脸会有多种选择,一个是识别最大人脸,这种场景主要用于刷脸门禁,还有一种是识别所有人脸,这种场景主要用于人脸识别摄像机,就是将画面中的所有人脸识别出来发给服务器,人脸框的数据主要是四个参数,左上角和右下角的位置,也可以说是x、y、width、height,可能有些做的比较好的还有倾斜角度,这个意义不是很大,人脸识别的速度一般都是飞快的,就算你用学习上用的opencv做识别也是非常快的,基本上都是毫秒级的响应,主要的耗时操作在特征值的提取,所以一般要求能够响应每个通道每秒钟25帧-30帧的画面绘制+人脸框的绘制,当然人脸框的数据可能会有多个。
feiyangqingyun
2020/11/01
1.3K0
Qt音视频开发44-实时人脸框
Qt音视频开发32-Onvif网络设置
用onvif协议来对设备的网络信息进行获取和设置,这个操作在众多的NVR产品中,用的很少,绝大部分用户都还是习惯直接通过摄像机的web页面进去配置,其实修改网络配置的功能在大部分的NVR中都是具备的,网络的参数主要包括IP地址、子网掩码、网关地址、DNS解析地址、NTP地址、网卡信息、网络协议等,这些都可以通过不同的onvif命令来获取和设置,一直没有搞懂为啥这些要分开不同的命令去处理,其实大可以合并成一个命令嘛,搞得设置个网络信息还要post好多次的数据才行。
feiyangqingyun
2020/10/12
1.1K0
Qt音视频开发32-Onvif网络设置
Qt音视频开发33-ffmpeg安卓版
一直都想搞个安卓版本的视频监控程序,很早以前弄过一个,采用的是早期的ffmpeg2的lib文件,对于现在众多的网络流媒体格式,支持有限,而且新的Qt编写安卓程序,结构上也变动了,新的安卓系统权限要求也和以前处理不一样了,现在需要动态授权,以前是直接配置文件写好需要哪些权限就行,所以近期特意全部重写了一遍安卓版本的视频监控程序,内核还是采用的ffmpeg,换成了最新的ffmpeg4版本,在ubuntu系统上用安卓编译器编译了对应的lib文件,然后放到win上编写Qt+安卓程序。
feiyangqingyun
2020/10/13
9630
Qt音视频开发33-ffmpeg安卓版
Qt音视频开发48-通用通道管理
把通用的视频控件搞定以后,后期增加新的内核方便多了,不需要在好多个文件复制粘贴之类的,接下来就是需要一个统一的类来管理视频监控系统中的16个通道或者32个通道,甚至64个通道也有可能,当然,通用通道管理也兼容各种监控内核,以前通道管理类,是每个内核写一个,也是很繁琐,大量的重复性代码,所以将通用视频监控控件整理好以后,顺其自然的要改造这个通用通道管理的类了。
feiyangqingyun
2020/11/20
8610
Qt音视频开发48-通用通道管理
Qt音视频开发34-Onvif时间设置
对设备设置时间很有必要,这个是必备的功能,毕竟大部分的前端设备比如摄像机本身不带BIOS电池的,所以没法存储时间,要么设置了NTP地址来同步时间,要么其他设备主动对他进行设置时间,如果时间不正确了,意味着本地画面显示的时间字符串,本地存储的视频录像文件等,都可能是不正确的,所以一般的处理是NVR一旦连上摄像机设备以后,立马将摄像机的时间设置成NVR的时间,这样就保持了一致。
feiyangqingyun
2020/10/14
1.2K0
Qt音视频开发34-Onvif时间设置
微博网红都长什么样子?
在之前的分享中,我们已经学会了简书和知乎小姐姐的爬虫。今天罗罗攀把魔爪伸向了微博网红们,我们找找谁是最美网红。今天的流程如下:
龙哥
2019/07/15
1.2K0
微博网红都长什么样子?
Qt音视频开发27-Onvif设备搜索
最近业余时间主要研究音视频开发这块,前面的文章写了好多种视频监控内核,一旦将这些内核搞定以后,视频监控的相关功能水到渠成。做视频监控系统,绕不过onvif这玩意,这玩意主要就是为了统一一个大概的标准,能够对各个厂家的监控设备进行常用的一些操作,比如搜索、获取信息、云台控制、事件订阅、抓拍图片等,如果没有这个规范,那么各个厂家都各自为政,需要用私有的sdk去处理,这样就很麻烦很惨了,几十个厂家就需要几十个sdk,对于程序员来说简直是灾难,想想就很恐怖的事情,哪个程序员不想多活几年!
feiyangqingyun
2020/10/04
1.1K0
Qt音视频开发27-Onvif设备搜索
相关推荐
Qt音视频开发43-人脸识别服务端
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档