上一篇文章写了在线调用人脸识别api进行处理,其实很多的客户需求是要求离线使用的,尤其是一些事业单位,严禁这些刷脸数据外泄上传到服务器,尽管各个厂家号称严格保密这些数据,但要阻止这些担心,唯一的解决办法就是设备离线使用,连个屁的网,不联网看你怎么上传,于是离线的人脸识别应用应运而生,比如我们手机上的识别就是本地库在运算,至于本地模型库估计会联网更新,以保持最新的状态。百度的离线人脸识别做的还行,看官网的sdk开发包,更新也是蛮快的,提供了windows、linux、android等版本。
本篇文章采用的百度离线SDK作为解决方案。可以去官网申请,默认有6个免费的密钥使用三个月,需要与本地设备的指纹信息匹配,感兴趣的同学可以自行去官网下载SDK。百度离线人脸识别SDK文件比较大,光模型文件就645MB,估计这也许是识别率比较高的一方面原因吧,不断训练得出的模型库,本篇文章只放出Qt封装部分源码。官网对应的使用说明还是非常详细的,只要是学过编程的人就可以看懂。
处理流程:
百度人脸识别在线版和离线版SDK的封装:
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;
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。