关注公众号,发现CV技术之美

导言:

本文将会实测七牛云的人脸识别 API,从应用开发者的角度来验证这套 API 的可用性。文中会选用人脸比对、权威人脸比对和人脸检测这3个API来进行测试。

本文使用 PHP 作为编程语言,需要安装 Composer,这是 PHP 开发中广泛使用的依赖库管理工具,相当于 JavaScript 里的 npm。七牛云提供的官方 PHP SDK 也是通过 Composer 来安装的。

为了尽可能排除不相关的细节,代码是以命令行方式来运行的,每个 API 对应一个 PHP 代码文件。

预备工作

1. 建立工作目录并安装依赖

首先建立一个目录存放项目代码,并进入该目录,后续所有的操作都在该目录下:

mkdir qiniu-api
cd qiniu-api

接下去用 Composer 安装依赖包,除了安装七牛云官方提供的 SDK 外,我们还要安装一个 HTTP 库,用来发送 API 请求。虽然用原生 PHP 函数也能发送 API 请求,但用库的好处是库为我们处理了很多细节,让我们不用为此操心,而且库封装后的发送代码很简洁,即便不熟悉 PHP 的开发者也容易读懂。在本文中,我们选用 Symfony 的 HTTP Client 库来发送 API 请求。

用以下的命令来安装上述的 2 个库:

composer require qiniu/php-sdk
composer require symfony/http-client

安装成功后,目录内会生成 composer.json 和 composer.lock 两个文件,库的代码放在生成的 vendors 目录下。我们无需关心这些生成的代码。

2. 获取七牛云账号的密钥

注册或登录七牛云的账户,在“个人中心”的“密钥管理”里,七牛云会自动生成两对 Access Key 和 Secret Key,选择其中一对,复制出来。

人脸比对

这个 API 主要的功能是接收 2 张发送过来的照片,根据照片上人脸的相似度给出一个分值,用以判断 2 张照片中的是否为同一人。

新建一个名为 face-compare.php 的文件,这里的代码主要分为 3 部分,第 1 部分校验命令行传入的参数并返回结构化后的命令行参数数据,第 2 部分根据命令行参数来准备发送到 API 的请求数据,第 3 部分为实际调用 API。这 3 部分会分别放在 3 个函数中,以便于理解。为了强调 API 本身的调用流程,我们对代码不会做过多的封装,完善的错误处理也不会涉及。

在开始编写那些函数之前,先在代码里做一些预备工作,具体请看代码里的注释:

<?php// 解决自动加载问题,之后引用的类会被自动加载
require_once __DIR__ . '/vendor/autoload.php';// 指定使用特定命名空间下的类
use Qiniu\Auth;
use Symfony\Component\HttpClient\HttpClient;// 定义两个常量,分别对应上文提到的七牛云里复制出的Access Key和Secret Key,这里需要替换成你实际的key
// 实际项目中,这些值可能是从配置文件或环境变量中读取
define('ACCESS_KEY', 'your_own_access_key');
define('SECRET_KEY', 'your_own_secret_key');

接着定义 3 个与人脸比对 API 相关的变量,这些变量的值都是文档里定义的。

// API的调用地址
$apiUrl = 'https://face-compare.qiniuapi.com/facecompare';// 提交到API时用到的HTTP方法,本文中涉及的3个API都是该方法
$method = 'POST';// 发送到API的请求body的mime类型,本文中涉及的3个API都是使用该类型
$contentType = 'application/json';

我们定义第一个函数,用来对参数做最基本的检验:

/*** @param int    $argc 命令行参数的数量* @param array  $argv 存储命令行参数的数组* @return array 命令行里得到的数据*/
function getInputs(int $argc, array $argv): array
{// 确保参数数量正确(参数分别是:php脚本名、第1张图片路径、第2张图片路径,所以总共是3个参数)if ($argc !== 3) {throw new \Exception('请提供2张图片的路径。');}// 确保传入的2张图片路径对应真实存在的文件if (!file_exists($argv[1]) || !file_exists($argv[2])) {throw new \Exception('请确保2张图片文件存在。');}// 以数组形式返回2张图片的路径return ['image_1' => $argv[1],'image_2' => $argv[2],];
}

然后定义第 2 个函数,用于生成发送 API 的 HTTP 请求的 header 和 body。按照文档,必须的 header 有 2个,一个是 Content-Type,另一个是 Authorization。Content-Type 固定为 application/json;而 Authorization 的值需要根据七牛云的签名算法来生成,相对比较复杂,好在官方提供的 SDK 里提供了 Auth 类,可以直接调用来生成这个 header 的值。

/*** @param string $apiUrl API地址* @param string $method 调用API的HTTP方法* @param string $contentType API请求body的mime类型 * @param array  $inputs 前一个函数返回的数组* @return array 发送HTTP请求用到的headers和body*/
function composeRequestOptions(string $apiUrl, string $method, string $contentType, array $inputs): array {// 对2张图片内容进行base64编码,放入一个文档要求的结构,并生成json格式的数据作为请求的body$body = json_encode(['data_uri_a' => encodeMediaToBase64($inputs['image_1']),'data_uri_b' => encodeMediaToBase64($inputs['image_2']),]);// 调用官方SDK来生成凭证的HTTP头$auth = new Auth(ACCESS_KEY, SECRET_KEY);// $authHeader的值为诸如['Authorization' => 'Qiniu QNJi_bYJlmO5LeY08FfoNj9w_r7...']的数组$authHeader = $auth->authorizationV2($apiUrl, $method, $body, $contentType);// 请求头里除了包含mime类型,也要包含凭证,所以这里把两个头合并在一个数组里$headers = array_merge(['Content-Type' => $contentType],$authHeader);// 返回包含header和body的数组return ['headers' => $headers,'body' => $body,];
}

这里我们调用了 Auth 类的 authorizationV2 方法,传入 HTTP 请求里用到的一些参数(API 地址、方法、body 和 mime 类型)即可得到凭证。如果查看 SDK 的代码,会看到 Auth 类还有一个 authorization 方法(签名略有不同),经实测该方法也能返回正确的凭证。

另外,这里也用到了一个工具函数 encodeMediaToBase64,它的作用是根据参数里的路径读取文件内容,并编码成base64格式:

/*** @param string  $mediaPath 文件在本地的路径* @return string base64字符串*/
function encodeMediaToBase64(string $mediaPath): string {$mediaData = file_get_contents($mediaPath);return base64_encode($mediaData);
}

有了第 2 个方法返回的 header 和 body,我们就能发送调用 API 请求了,这是第 3 个函数的作用:

/*** @param string $apiUrl API地址* @param string $method 调用API的HTTP方法* @param array  $requestOptions 包含请求header和body* @return array API返回的应答body,转成了数组格式*/
function callApi(string $apiUrl, string $method, array $requestOptions): array {// 创建发送客户端$client = HttpClient::create();// 发送请求$response = $client->request($method, $apiUrl, $requestOptions);// 这里获得的应答是json格式$content = $response->getContent();// 把json转为数组并返回return json_decode($content, true);
}

当以上 3 个函数完成后,只需要调用它们即可,最后在标准输出中打印结果:

$inputs = getInputs($argc, $argv);
$requestOptions = composeRequestOptions($apiUrl, $method, $contentType, $inputs);
$responseBody = callApi($apiUrl, $method, $requestOptions);// 打印输出API返回的结果
print_r($responseBody);

第 1 个函数调用里用到的 和argv 是 PHP 在命令行运行时自动提供的,分别对应命令行的参数个数和参数的具体值构成的数组,这和 C 语言里 main 函数里的参数相似。

笔者在网上找了 5 张国外明星的照片,其中 2 张为 Matt Damon 不同年龄的照片,以及 1 张 Leonardo Dicaprio 和 1 张 Morgan Freeman 的照片,共 4 张图作为测试照片,放在当前目录下的 images 目录里,图片如下:

Matt Damon-young

Matt Damon-old

Leonardo Dicaprio

Morgan Freeman

实际运行结果如下:

# Matt Damon的2张图片比对,相似度得分为100:
php face-compare.php images/matt-damon-young.jpg images/matt-damon-old.jpg
Array
([session_id] => 20210915084600UrzDdFAvk5[Errorcode] => 0[Errormsg] => OK[similarity] => 100
)
# Matt Damon和Leonardo Dicaprio图片比对,相似度得分68:
php face-compare.php images/matt-damon-young.jpg images/leonardo-dicaprio.jpg
Array
([session_id] => 20210915084715c8YXlSJrK6[Errorcode] => 0[Errormsg] => OK[similarity] => 68
)
# 如果将Matt Damon和Morgan Freeman对比,两者除了相貌外,年龄肤色也差别很大,得分为0:
php face-compare.php images/matt-damon-young.jpg images/morgan-freeman.jpg
Array
([session_id] => 20210915084829S6leTB1V2R[Errorcode] => 0[Errormsg] => OK[similarity] => 0
)

以上结果和笔者预期比较符合。

权威人脸比对

该 API 用于将发送过来的姓名、身份照号和照片这些身份信息来和官方的身份证数据库进行比对,从而判别提供的身份信息是否属实。

新建一个名为 face-hdphoto-auth.php 的文件,代码的结构和人脸比对完全一样,也是分为 3 部分,差别主要是 API 地址和命令行接收的参数不同。为了简洁起见,不再把完整的代码列出,只是列出不一样的部分。

一开始的 3 个变量中,API 地址改为如下,其它 2 个变量值不变:

$apiUrl = 'https://face-hdphotoauth.qiniuapi.com/hdphoto_auth';

第 1 个函数仍然用于检查命令行参数,这里需要接收 3 个输入:姓名、身份照号和照片路径。这个函数里,我们对输入做一些简单的检查,然后返回数据。

function getInputs(int $argc, array $argv): array
{if ($argc !== 4) {throw new \Exception('请提供姓名、身份证号和1张照片的路径。');}// 检查18位身份证号的格式if (!preg_match('/^\d{17}[\dX]$/', $argv[2])) {throw new \Exception('请提供18位身份证号。');}if (!file_exists($argv[3])) {throw new \Exception('请确保1张照片文件存在。');}// 以数组形式返回姓名、身份照号和图片路径return ['name' => $argv[1],'id' => $argv[2],'image' => $argv[3],];
}

第 2 个函数里只有一开始的 $body 数据有所不同。

function composeRequestOptions(string $apiUrl, string $method, string $contentType, array $inputs): array {$body = json_encode(['realname' => $inputs['name'],'idcard' => $inputs['id'],'data_uri' => encodeMediaToBase64($inputs['image']),]);// 其余部分和人脸比对里的函数完全一致
}

第 3 个函数和最后的函数调用部分完全一样。

通过以下方式来调用此 PHP 脚本:

# 用真实存在的名字和身份证号代替下面的数据,并使用此人的照片
php face-hdphoto-auth.php 张三 000000000000000000 images/photo-for-id-auth.jpg

笔者用自己的身份信息,再加上两张自己的照片,做了实测比对:

# 使用了自己一张近期的照片,相似度为96.92
Array
([session_id] => 20210914013725tA3iTEoS09[Errorcode] => 0[Errormsg] => OK[similarity] => 96.92
)
# 使用了自己一张十几年前的照片,相似度为81.88
Array
([session_id] => 20210914013752cJy9ZYtMge[Errorcode] => 0[Errormsg] => OK[similarity] => 81.88
)

笔者也故意测试了一些错误情况,如果身份证号存在对但名字不对,API 会正常返回,但 similarity 字段数值为 0:

# 故意把名字写错,但身份照号是真实存在的,会得到如下数据:
Array
([session_id] => 20210914015325r6i8WjT2KB[Errorcode] => 0[Errormsg] => OK[similarity] => 0
)

如果名字和身份证号都正确,但照片不是本人时,经实测有 2 种情况:如果 API 判断照片与本人有一定程度相符,会返回正常结果,但 similarity 里的份数较低;如果系统判断出压根不是一个人,直接返回了 400 错误。

笔者也尝试使用了一张用软件随便做的图片(不含人脸),得到了 Errormsg 为 PHOTO_NOT_ACCEPTED 的应答,与文档描述相符。

人脸检测

该 API 接收一张图片,来检查图片中出现的人脸,允许图片里有多个脸。

新建一个名为 face-detect.php 的文件,代码的结构和上面两个文件对完全一样,也是分为 3 部分,这里也只列出不同的部分。

一开始的 3 个变量中,API 地址改为如下,其它 2 个变量值不变:

$apiUrl = 'https://face-detect.qiniuapi.com/facedetect';

第 1 个函数仍然用于检查命令行参数,这里只需要接收 1 个输入:图片文件的地址。

function getInputs(int $argc, array $argv): array
{if ($argc !== 2) {throw new \Exception('请提供1张图片的路径。');}if (!file_exists($argv[1])) {throw new \Exception('请确保1张图片文件存在。');}return ['image' => $argv[1],];
}

第 2 个函数里只有一开始的 $body 数据有所不同。

function composeRequestOptions(string $apiUrl, string $method, string $contentType, array $inputs): array {$body = json_encode(['image_b64' => encodeMediaToBase64($inputs['image']),]);// 其余部分和人脸比对里的函数完全一致
}

第 3 个函数和最后的函数调用部分完全一样。

我们用一张网上找的家庭合照来测试:

php face-detect.php images/family.jpg

返回的结果里信息量比较大,以下是一个节选的版本:

Array
([num_face] => 3[rotate_angle] => 0[face] => Array([0] => Array([score] => 99.48[x] => 147[y] => 74[width] => 162[height] => 162[pitch] => -1.87[yaw] => -1.55[roll] => 2.25[eye] => 0[mouth] => 0[blur] => 100[gender] => M[age] => 35[illumination] => 72.84[face_shape] => Array(...)[completeness] => 100[area] => 26103[facesize] => 100[quality] => 92.58[face_aligned_b64] => ...)[1] => Array(...)[2] => Array(...))[errorcode] => 0[errormsg] => OK[session_id] => 20210917012718zjLc9tSBNu
)

可以看到,API 正确判断出了人脸的个数、每个人的性别和年龄、甚至每个脸部在三维中的旋转角度(当然,年龄只要比较接近就行,另外小孩子的性别可能更容易误判,但这也很正常);具体到每一个脸,API 还返回了脸部关键点的坐标。更详细的说明请参照文档。

小结

本文编写了 3 个命令行运行的 PHP 代码,来实测调用七牛云的 API。为了精简,代码里省去了很多和演示无关的部分。在实际项目中,需要对代码进行进一步的重构和封装,除去重复代码;由于发送网络请求会受制于网络的不稳定,需要增加 API 调用时异常处理(超时、返回错误代码等);也要对提交到 API 的数据进行更严格的校验。

经过实测,就案例里用到的 3 个 API 来说,总的感觉还是比较可靠的,可以逐步应用到生产环境中。当然,推测七牛云内部也在不断优化更新 API 背后的算法,相信之后这套 API 的可靠性还会得到进一步提升。

除了人脸核验,七牛云智能多媒体服务还提供了票证识别、多媒体处理、智能风控等功能,感兴趣的小伙伴可以体验一下,点击阅读原文即可跳转到官网页面~

戳下面的原文阅读,更有料

【教程】从人脸检测与比对,实测七牛云人脸核验 API相关推荐

  1. python 人脸检测 大胡子_Python | 50行代码实现人脸检测

    信息安全公益宣传,信息安全知识启蒙. 加微信群回复公众号:微信群:QQ群:16004488 加微信群或QQ群可免费索取:学习教程 教程列表见微信公众号底部菜单 现在的人脸识别技术已经得到了非常广泛的应 ...

  2. linux使用mtcnn进行人脸检测,Linux下使用FDDB 测试MTCNN人脸检测模型生成 ROC 曲线

    FDDB是全世界最具权威的人脸检测评测平台之一,是专门针对人脸识别算法的评测方法与标准.FDDB数据集官网:http://vis-www.cs.umass.edu/fddb/ 下面介绍如何使用FDDB ...

  3. 人脸检测(十五)--改进版VJ人脸检测(LBP特征,VISAPP2017)

    老实说,评估了从传统VJ到深度学习人脸检测各种算法后,我还是喜欢LBP+级联Adaboost这种架构的人脸检测,毕竟,boost框架还是最快的.在某些限制性场景应用中,大量的扫描窗方式虽然很low,但 ...

  4. python视频人脸检测_Python基于OpenCV实现视频的人脸检测

    本文实例为大家分享了基于OpenCV实现视频的人脸检测具体代码,供大家参考,具体内容如下 前提条件 1.摄像头 2.已安装Python和OpenCV3 代码 import cv2 import sys ...

  5. flutter 人脸检测_【转载】opencv实现人脸检测

    全文转载自CSDN的博客(不知道怎么将CSDN的博客转到博客园,应该没这功能吧,所以直接复制全文了),转载地址如下 http://blog.csdn.net/lsq2902101015/article ...

  6. 无需人脸检测,实时6自由度3维人脸姿态估计img2pose

    效果图: 提出了一种实时的6自由度3D人脸姿态估计方法,其不依赖于人脸检测和关键点对齐.我们观察到直接估计6自由度刚体变换是一个比在3D人脸对齐中广泛使用的关键点检测更简单的问题.基于此我们做出了一下 ...

  7. 人脸检测算法_目前最强!开源人脸检测算法:RetinaFace

    加入极市专业CV交流群,与6000+来自腾讯,华为,百度,北大,清华,中科院等名企名校视觉开发者互动交流!更有机会与李开复老师等大牛群内互动! 同时提供每月大咖直播分享.真实项目需求对接.干货资讯汇总 ...

  8. 基于PCA 人脸识别/人脸识别算法/人脸检测程序源码MATLAB ELM+PCA人脸识别 PCA人脸识别matlab代码 基于PCA算法的人脸识别

    1.基于PCA的人脸识别代码 2.MATLAB ELM+PCA人脸识别 2.基于PCA的人脸识别(matlab)(采用PCA算法进行人脸识别,通过抽取人脸的主要成 分,构成特征脸空间,识别时将测试图像 ...

  9. python人脸检测代码_python3+openCV实现图片的人脸人眼检测,原理+参数+源代码

    上学时候用matlab学过一些图像处理的基础知识,当时课程作业是用haar实现人脸检测 but当时是心思根本不在图像处理上,so找了个同学帮忙做的,自己没上心 然鹅天道好轮回,现在捡起来了原来的算法一 ...

最新文章

  1. 年后跳槽季,如何在编程面试中大获成功?
  2. cocoapods管理第三方框架
  3. Py_Initialize fails - unable to load the file system codec
  4. 【Android APT】注解处理器 ( 配置注解依赖、支持的注解类型、Java 版本支持 )
  5. Redis的数据类型详解
  6. python中统计计数的几种方法
  7. highcharts如何把图多余的空白页面_如何进行前端性能测试入门篇
  8. m2eclipse插件
  9. mdp框架_强化学习:MDP(Markov Decision Process)
  10. Linux下Nginx的安装和配置
  11. python装饰器的通俗理解_Python|闭包、装饰器,简单的实例,通俗的理解
  12. 【渗透测试实战】具体案例——讲讲SQL注入攻击是怎么回事?
  13. Go语言学习笔记(8)——包和结构体
  14. VMware Explore 2022 China,赋能中国企业加速实现云智能
  15. 使用Gstreamer播放未知格式视频(python)
  16. 【C/C++笔记】 C/C++常见问题笔记 1
  17. 第一门编程语言选谁?
  18. 当程序员追求佛系,会发生什么……
  19. 梳理:WPS JS宏之WPS表格单元格读写值
  20. Dubbo注解方式与spring的整合原理即@DubboService的机制(2)

热门文章

  1. matlab中关于程序运行的快捷键
  2. 一张图学会Xmind创建思维导图【转载】
  3. 设计模式学习笔记——适配器(Adapter)模式
  4. 小程序 - 腾讯云 - wafer - PHP - 数据库接口的应用和研究 - 01 - DB::insert
  5. php仿微信朋友圈网站源码,Smobiler仿微信朋友圈的消息代码实例
  6. 当前主要使用的python版本_动力火车当歌词
  7. 360安全浏览器兼容模式怎么设置_360浏览器及安全卫士怎么减少广告弹出?
  8. ajax高效分页查询,基于 Jquery+Ajax+Json高效分页实现代码
  9. 操作系统考研辅导教程(计算机专业研究生入学考试全真题解) pdf,计算机组成原理考研辅导教程:计算机专业研究生入学考试全真题解...
  10. android 页面icon拉伸_所有同学!注意咯!!设计师不可忽略的页面转场来咯!!...