Qt音视频开发40-人脸识别离线版
一、前言
上一篇文章写了在线调用人脸识别api进行处理,其实很多的客户需求是要求离线使用的,尤其是一些事业单位,严禁这些刷脸数据外泄上传到服务器,尽管各个厂家号称严格保密这些数据,但要阻止这些担心,唯一的解决办法就是设备离线使用,连个屁的网,不联网看你怎么上传,于是离线的人脸识别应用应运而生,比如我们手机上的识别就是本地库在运算,至于本地模型库估计会联网更新,以保持最新的状态。百度的离线人脸识别做的还行,看官网的sdk开发包,更新也是蛮快的,提供了windows、linux、android等版本。
本篇文章采用的百度离线SDK作为解决方案。可以去官网申请,默认有6个免费的密钥使用三个月,需要与本地设备的指纹信息匹配,感兴趣的同学可以自行去官网下载SDK。百度离线人脸识别SDK文件比较大,光模型文件就645MB,估计这也许是识别率比较高的一方面原因吧,不断训练得出的模型库,本篇文章只放出Qt封装部分源码。官网对应的使用说明还是非常详细的,只要是学过编程的人就可以看懂。
处理流程:
- 实例化BaiduFaceApi类,调用sdk_init初始化。
- 调用is_auth判断授权是否成功,成功了才能继续。
- 设置最小人脸比例(set_min_face_size)、光照阈值(set_illum_thr)等参数。
- 调用track_max_face函数获取人脸区域。
- 调用rgb_liveness_check函数进行活体检测。
- 调用get_face_feature函数提取特征值。
- 调用compare_feature函数进行人脸比对。
百度人脸识别在线版和离线版SDK的封装:
- 离线版要求支持C++11的编译器,而且必须为MSVC。不支持mingw编译器。
- 在线版中的密钥等信息,务必记得换成自己申请的。
- 离线版本只能在windows上使用。
- 离线版本需要自己申请密钥。找到facebaidusdk文件夹下的LicenseTool.exe,填写后台离线SDK管理中申请到的序列号,单击激活按钮。
- 离线版本对应的动态库和模型文件自行从官网下载。
- 如果源码包中有facebaidusdk+face-resource文件夹则说明带了动态库和模型库文件夹,只需要将facebaidusdk文件夹下的所有文件复制到可执行文件同一目录,face-resource文件夹复制到可执行文件夹目录同等级目录即可。目录位置见snap文件夹下的示例图。
- facebaidusdk目录下的TestFaceApi.exe为百度提供的测试程序,先要将USB摄像头插到电脑上,会实时找人脸框。
二、功能特点
- 支持的功能包括人脸识别、人脸比对、人脸搜索、活体检测等。
- 在线版还支持身份证、驾驶证、行驶证、银行卡等识别。
- 在线版的协议支持百度、旷视,离线版的支持百度,可定制。
- 除了支持X86架构,还支持嵌入式linux比如contex-A9、树莓派等。
- 每个功能的执行除了返回结果还返回执行用时时间。
- 多线程处理,通过type控制当前处理类型。
- 支持单张图片检索相似度最高的图片。
- 支持指定目录图片用来生成人脸特征值文件。
- 可设置等待处理图片队列中的数量。
- 每次执行都有成功或者失败的信号返回。
- 人脸搜索的返回结果包含了原图+最大相似度图+相似度等。
- 人脸比对同时支持两张图片和两个特征值比对。
- 相关功能自定义一套协议用于客户端和服务端,可以通过TCP通信进行交互。
- 自定义人脸识别协议非常适用于中心一台服务器,现场若干设备请求的场景。
- 每个模块全部是独立的一个类,代码整洁、注释完善。
三、效果图

四、相关站点
- 国内站点:https://gitee.com/feiyangqingyun/QWidgetDemo
- 国际站点:https://github.com/feiyangqingyun/QWidgetDemo
- 个人主页:https://blog.csdn.net/feiyangqingyun
- 知乎主页:https://www.zhihu.com/people/feiyangqingyun/
- 体验地址:https://blog.csdn.net/feiyangqingyun/article/details/97565652
五、核心代码
void FaceLocalBaiDu::init()
{
//如果已经正常则无需初始化
if (isOk) {
return;
}
int res = api->sdk_init();
res = api->is_auth();
if (res != 1) {
qDebug() << TIMEMS << QString("init sdk error: %1").arg(res);
} else {
//设置最小人脸,默认30
api->set_min_face_size(percent);
//设置光照阈值,默认40
api->set_illum_thr(20);
//设置角度阈值,默认15
//api->set_eulur_angle_thr(30, 30, 30);
isOk = true;
qDebug() << TIMEMS << "init sdk ok";
}
emit sdkInitFinsh(isOk);
}
bool FaceLocalBaiDu::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 = FaceHelper::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);
msec = getTime(time);
return true;
}
return false;
}
bool FaceLocalBaiDu::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 = FaceHelper::getImageData(img);
std::string value = api->rgb_liveness_check(imageData.constData(), 1);
QString data = value.c_str();
data = data.replace("\t", "");
data = data.replace("\"", "");
data = data.replace(" ", "");
int index = -1;
QStringList list = data.split("\n");
foreach (QString str, list) {
index = str.indexOf("score:");
if (index >= 0) {
result = str.mid(6, 4).toFloat();
break;
}
}
if (index >= 0) {
msec = getTime(time);
return true;
}
return false;
}
bool FaceLocalBaiDu::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 = FaceHelper::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]);
}
msec = getTime(time);
return true;
}
return false;
}
float FaceLocalBaiDu::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 FaceLocalBaiDu::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);
msec = getTime(time);
return true;
}
return false;
}
Qt音视频开发40-人脸识别离线版的更多相关文章
- Android IOS WebRTC 音视频开发总结(八十五)-- 使用WebRTC广播网络摄像头视频(下)
本文主要介绍WebRTC (我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:bl ...
- WebRTC 音视频开发
WebRTC 音视频开发 webrtc Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译 ...
- windows版 Java调用人脸识别离线sdk
最近因工作需求在java-web服务中调用人脸识别离线sdk,主要通过JNA及JNI技术,但均未调试通过,JNA调用时出现以下异常,一直未解决,求大佬指点,导常信息如下: in BaiduFaceAp ...
- 转:Android IOS WebRTC 音视频开发总结 (系列文章集合)
随笔分类 - webrtc Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译和整理的,译 ...
- Android开发 音视频开发需要了解的专业术语知识
前言 在摸索一段时间的音视频开发后,越来越发现这个坑的深度真是特别的深. 除了了解Android自带的音视频处理API以外,还得了解一些视频与音频方面的知识.这篇博客就是主要讲解这方面的专业术语.内容 ...
- 音视频开发-FFmpeg
音视频开发是个非常复杂的,庞大的开发话题,初涉其中,先看一下结合 OEIP(开源项目) 新增例子. 可以打开flv,mp4类型文件,以及rtmp协议音视频数据,声音的播放使用SDL. 把采集的麦/声卡 ...
- Python音视频开发:消除抖音短视频Logo的图形化工具实现
☞ ░ 前往老猿Python博文目录 ░ 一.引言 在<Python音视频开发:消除抖音短视频Logo和去电视台标的实现详解>节介绍了怎么通过Python+Moviepy+OpenCV实现 ...
- Python音视频开发:消除抖音短视频Logo和去电视台标
☞ ░ 前往老猿Python博文目录 ░ 一.引言 对于带Logo(如抖音Logo.电视台标)的视频,有三种方案进行Logo消除: 直接将对应区域用对应图像替换: 直接将对应区域模糊化: 通过变换将要 ...
- Moviepy音视频开发:视频转gif动画或jpg图片exe图形化工具开发案例
☞ ░ 前往老猿Python博文目录 ░ 一.引言 老猿之所以学习和研究Moviepy的使用,是因为需要一个将视频转成动画的工具,当时在网上到处搜索查找免费使用工具,结果找了很多自称免费的工具,但转完 ...
- 【秒懂音视频开发】02_Windows开发环境搭建
音视频开发库的选择 每个主流平台基本都有自己的音视频开发库(API),用以处理音视频数据,比如: iOS:AVFoundation.AudioUnit等 Android:MediaPlayer.Med ...
随机推荐
- JOI Open 2018
T1 Bubble Sort 2 题意:给定一个长度为 \(n\) 的序列 \(a\),进行 \(q\) 次修改,第 \(i\) 次将第 \(x_i\) 个元素的值修改为 \(y_i\). 对于每次操 ...
- 云原生周刊:K8s 的 13 个最佳开源监控工具
开源项目推荐 Silver Surfer 该项目旨在检查 Kubernetes 对象的 API 版本兼容性,并为其提供迁移路径,以便为集群升级做好准备. Actions Runner Controll ...
- appium-解决uiautomatorviewer不能定位android7以上版本元素的方法
上图是android10模拟器,发现我们是无法连接模拟器识别的 解决方法: 在模拟器内打开指定页面然后截图,最后保存为uix文件,然后用adb拉到本地,一共四个命令,可以保存为.bat文件快捷执行(这 ...
- cxv文件合并
1.新建bat脚本 @echo off setlocal enabledelayedexpansion copy *.csv new.csv echo @@@@@@@@@@@@@合并成功!@@@@@@ ...
- 每日学学Java开发规范,代码格式(附阿里巴巴Java开发手册(终极版))
前言 每次去不同的公司,码不同的代码,适应不同的规范,经常被老大教育规范问题,我都有点走火入魔的感觉,还是要去看看阿里巴巴Java开发规范,从中熟悉一下,纠正自己,码出高效,码出质量. 想细看的可以去 ...
- 6.Kubernetes集群管理工具kubectl
Kubernetes集群管理工具kubectl 概述 kubectl是Kubernetes集群的命令行工具,通过kubectl能够对集群本身进行管理,并能够在集群上进行容器化应用的安装和部署 命令格式 ...
- 一文搞懂 ARM 64 系列: PACISB
1 PAC AMR64提供了PAC(Pointer Authentication Code)机制. 所谓PAC,简单来说就是使用存储在芯片硬件上的「密钥」,一个「上下文」,与「指针地址」进行加密计算, ...
- jenkins拉取github代码报错问题解决
问题起因: 踩坑踩坑 用jenkins拉取github项目的代码时,配置完成点击构建时,报错信息为:Couldn't find any revision to build. Verify the re ...
- 命运的X
命运的X cjx 生成函数强. 思路 首先,设 \(f_i\) 为添加第 \(i\) 项后满足条件的概率,\(g_i\) 任意添加至第 \(i\) 项的概率. 我们要求的答案: \[ans=\sum_ ...
- php的各种序列化对比
php的各个序列化反序列化对比如下 function 10万条记录的序列化并写入(ms) 10万条记录文件读取并反序列化(ms) 100条记录序列化并写入(ms) 100条记录文件读取并反序列化(ms ...