IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> 【教程】从人脸检测与比对,实测七牛云人脸核验 API -> 正文阅读

[PHP知识库]【教程】从人脸检测与比对,实测七牛云人脸核验 API

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

导言:

08c6854e9fc8a4e65f684ae41273ed20.png

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

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

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

8b074f3fa028a17890f13e83f4d1e75b.gif

预备工作

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,选择其中一对,复制出来。


6e66ed6551eddfe435f42f0c3d8c377a.gif

人脸比对


这个 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 目录里,图片如下:

cedb678b8f6cbe8215b5be1452167531.png

Matt Damon-young

97d4368a22f9572ab6454dd6edbf5b23.png

Matt?Damon-old

fef5d7b2ce1b660402ebf52691f1dd5b.png

Leonardo?Dicaprio

5759c99ff994cedf6f0d4aca31ab0c75.png

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
)

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


af4ac7ff15946259d5068509c962b411.gif

权威人脸比对


该 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 的应答,与文档描述相符。


5995f3fe266b8d4f11a980e916ec220a.gif

人脸检测


该 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 个函数和最后的函数调用部分完全一样。

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

0d6600b8e69e002cc56f9f8d2356b42e.png

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 还返回了脸部关键点的坐标。更详细的说明请参照文档。



63e989786622bb42080a46cd258e4a2e.gif

小结


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

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

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

97219778dd9f20f785dcc4471402936d.gif

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

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-10-01 16:36:51  更:2021-10-01 16:37:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 4:32:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计