用2263份证件照图片样本测试how-old.net的人脸识别
上一年也就是这个时候微软根据自己的人脸识别API推出了一个识别照片中人脸年龄和性别的网站——http://how-old.net,小伙伴们各种玩耍,一年后的今天突发“奇想”地想测试一下这个网站的识别情况。正好手里有3万多份标识有身份证信息、性别及照片拍摄时间的证件照(别问我从哪儿弄的,这玩意儿你懂的)。今天就写了个脚本来测试一下。测试识别的目标有两个:
- 性别
- 年龄
提交数据获得识别结果
寻找接口
首先,查看一下how-old.net的提交接口。
用Chrome查看一下网络请求的情况
查看一下前三个请求的数据情况:
第一个:
第二个:
第三个:
很奇怪有没有,第一个是一个bolb地址,第二个是图片的base64编码后的字符,第三个倒像是真正的请求,可查看请求中,尽然找不到对应图片的参数。再查看一下第三个请求的响应:
嗯,一个添加转移符号的json数据,我们想要的识别结果确实在里面。这就确定这个请求就是我们需要的请求接口,现在的问题是怎样上传图片数据呢?
我们不妨从头看一下这三个请求。第一个中的bolb地址和第二个请求中的base64数据是怎么个情况呢?在Stack Overflow上查找到了下面的信息:
简单来说就是,在二进制数据以流式方式提交的时候,有这样一个模式:生成一个bolb地址做本机数据访问 -> 访问具体的信息是是base64编码的的文件 -> 对指定接口以流式上传数据。也就是说前两个请求时发生在本机的,是对本地资源的访问,第三个请求才是真正的请求,只不过数据是前两个“本机请求”生成的流式数据。
上传数据获得识别结果
这样我们就得到了我们需要的访问接口及数据提交方式:
- 接口:
- 提交方式:POST流式提交
我们可以在上面第三个请求图中查看到请求参数及header,cookies等信息。使用requests库能很容易做到数据流式提交,针对此接口请求代码如下:
#访问主页获得cookie
t = requests.get("http://how-old.net",timeout=60)
_cookies = t.cookies
t.close()
#构建请求头
headers = {
"Content-Type": "application/octet-stream",
"Referer": "http://how-old.net/",
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36"
}
info = None
#POST方式流式提交(pic_name是图片地址)
with open(pic_name, 'rb') as f:
r = requests.post("http://how-old.net/Home/Analyze?isTest=False&source=&version=how-old.net",
data=f,
headers=headers,
cookies=_cookies,
timeout=10)
info = r.content
将返回的识别数据存储在info
中,其样式像下面这样:
"{\"AnalyticsEvent\":\"[\\r\\n {\\r\\n \\\"face\\\": {\\r\\n \\\"age\\\": 16.0,\\r\\n \\\"gender\\\": \\\"Male\\\"\\r\\n },\\r\\n \\\"event_datetime\\\": \\\"2016-04-30T11:39:30.4786437Z\\\",\\r\\n \\\"user_id\\\": \\\"ab85e356-6638-41e7-a46f-be54c1f94f97\\\",\\r\\n \\\"session_id\\\": \\\"ba5ec8e4-65e0-481d-b034-970494680bca\\\",\\r\\n \\\"submission_method\\\": \\\"Upload\\\",\\r\\n \\\"user_agent\\\": \\\"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36\\\",\\r\\n \\\"location\\\": {\\r\\n \\\"latitude\\\": 35.71,\\r\\n \\\"longitude\\\": 115.23\\r\\n },\\r\\n \\\"location_city\\\": {\\r\\n \\\"latitude\\\": 35.7,\\r\\n \\\"longitude\\\": 115.2\\r\\n },\\r\\n \\\"is_mobile_device\\\": false,\\r\\n \\\"browser_type\\\": \\\"Chrome\\\",\\r\\n \\\"platform\\\": \\\"Windows\\\",\\r\\n \\\"mobile_device_model\\\": \\\"Unknown\\\"\\r\\n }\\r\\n]\",\"Faces\":[{\"faceId\":null,\"faceRectangle\":{\"top\":29,\"left\":49,\"width\":51,\"height\":51},\"attributes\":{\"gender\":\"Male\",\"age\":16.0}}]}"
正想我们在Chrome中观测到的返回数据一样,这样通过Python提交图片并获得识别数据就成功了。
但是这样的数据我们很难使用,因为里面数据很多且有很多的转义,所以先把\r``\n``\
这样的数据清洗掉,并选取其中最后面的一部分,获得下面的结构数据:
{
"Faces": [
{
"faceId": null,
"faceRectangle": {
"top": 29,
"left": 49,
"width": 51,
"height": 51
},
"attributes": {
"gender": "Male",
"age": 16
}
}
]
}
faceId
是图片中识别出的脸的标号,faceRectangle
是将脸部框前来的矩形左上坐标及宽高,attributes
中是识别出的性别和年龄。由于证件照都是标准的一个人,网站基本都能识别出来,所以只考虑一张图片对应的一个attributes
。将照片对应的信息存在一个persons列表中,样式如下:
persons = [
{
"num":num,
"real_age":real_age,
"real_gender":real_gender,
"rec_age":rec_age,
"rec_gender":rec_gender
}
]
识别结果统计
性别识别
性别识别统计很容易,直接比对一张照片对应的实际性别和识别:
toatal = len(persons)
right = 0
wrong_fm = 0
wrong_mf = 0
for person in persons:
if person["real_gender"] == person["rec_gender"]:
right += 1
elif person["real_gender"] == "Female":
wrong_fm += 1
else:
wrong_mf +=1
最终的结果是:
年龄识别
年龄的识别统计采用一个字典记录,其结构是识别{某年龄差:识别为该年龄差的个数}:
age_rec = {}
for person in persons:
tmp = person["rec_age"] - person["real_age"]
try:
age_rec[tmp] += 1
except:
pass
finally:
age_rec[tmp] = 1
最终的统计结果是:
结语
本实践统计了HOW-OLD对两千多份图片样本的识别结果,性别识别正确率很高,而年龄识别错误范围较大,且识别结果偏大的居多。我甚至觉得,这东西可以用来检测摄影师的拍照技术,识别结果越小,人物摄影技术越好:)(开个玩笑)。整个实践最麻烦的地方是找接口及上传数据的方法,最费时间的是上传数据获得结果这个过程(受网络IO的限制,用家里的小破wifi,使用多线程也没多大用,而且线程一多,就会掉线:()。
用2263份证件照图片样本测试how-old.net的人脸识别的更多相关文章
- AI人脸识别的测试重点
最常见的 AI应用就是人脸识别,因此这篇文章从人脸识别的架构和核心上,来讲讲测试的重点. 测试之前需要先了解人脸识别的整个流程,红色标识代表的是对应AI架构中的各个阶段 首先是人脸采集. 安装拍照摄像 ...
- 百度人脸识别api及face++人脸识别api测试(python)
一.百度人脸识别服务 1.官方网址:http://apistore.baidu.com/apiworks/servicedetail/464.html 2.提供的接口包括: 2.1 多人脸比对:请求多 ...
- Face Recognition 人脸识别该如何测试
猪圈子,一个有个性的订阅号 01 测量人脸识别的主要性能指标有 1.误识率(False;Accept;Rate;FAR):这是将其他人误作指定人员的概率; 2.拒识率(False;RejectRate ...
- openFace 人脸识别框架测试
openface 人脸识别框架 但个人感觉精度还是很一般 openface的githup文档地址:http://cmusatyalab.github.io/openface/ openface的安 ...
- Android静态图片人脸识别的完整demo(附完整源码)
Demo功能:利用android自带的人脸识别进行识别,标记出眼睛和人脸位置.点击按键后进行人脸识别,完毕后显示到imageview上. 第一部分:布局文件activity_main.xml < ...
- 【C#】人脸识别 视频数据转图片数据
使用虹软人脸识别的开发过程中遇到了转换的问题 因为不会用C#直接打开摄像头,就只能用第三方dll.一开始用Aforge,后来发现有个问题,关闭摄像头老是陷入等待,所以抛弃了.前一阵子开始用封装了Ope ...
- 【AI图像识别一】人脸识别测试探索
****************************************************************************** 本文主要介绍AI能力平台的人脸识别技术的测 ...
- AI大厂算法测试心得:人脸识别关键指标有哪些?
仅仅在几年前,程序员要开发一款人脸识别应用,就必须精通算法的编写.但现在,随着成熟算法的对外开放,越来越多开发者只需专注于开发垂直行业的产品即可. 由调查机构发布的<中国AI产业地图研究> ...
- python使用matplotlib画图,jieba分词、词云、selenuium、图片、音频、视频、文字识别、人脸识别
一.使用matplotlib画图 关注公众号"轻松学编程"了解更多. 使用matplotlib画柱形图 import matplotlib from matplotlib impo ...
随机推荐
- node(redis)
给出node下redis操作的简单例子: var redis = require("redis"), client = redis.createClient(6379,'127.0 ...
- objective-c(反射)
objective-c中提供类似JAVA的反射特性,给出基本例子如下: #import <Foundation/Foundation.h> @interface ClassA : NSOb ...
- 架构设计:前后端分离之Web前端架构设计
在前面的文章里我谈到了前后端分离的一些看法,这个看法是从宏观的角度来思考的,没有具体的落地实现,今天我将延续上篇文章的主题,从纯前端的架构设计角度谈谈前后端分离的一种具体实现方案,该方案和我原来设想有 ...
- ASP.NET MVC从视图传递多个模型到Controller
从后台组织好数据然后传递到页面倒是水到渠成很方便,因为MVC自身就将这样的需求内建到了这个系统中.我只需要在后台组织好一个List 或IEnumerable类型的变量,将需要传递的数据模型扔进去便可. ...
- vmware安装ubuntu12.04嵌套安装xen server(实现嵌套虚拟化)
环境准备 软件:vmware workstation 9.0 ubuntu-12.04.2-server-amd64(官方下载) 硬件:确认CPU支持虚拟化VM-T vmware设置 vmwar ...
- C++ std::multiset
std::multiset template < class T, // multiset::key_type/value_type class Compare = less<T>, ...
- Linux常用命令(转)
源自:http://www.linuxidc.com/Linux/2011-08/40437.htm Linux管理文件和目录的命令 命令 功能 命令 功能 pwd 显示当前目录 ls 查看目录下的内 ...
- shell 中命令输入的快!捷!键!
非常棒!! 非常棒!! 删除ctrl + d 删除光标所在位置上的字符相当于VIM里x或者dlctrl + h 删除光标所在位置前的字符相当于VIM里hx或者dhctrl + k 删除光标后面所有字符 ...
- underscore源码阅读记录
这几天有大神推荐读underscore源码,趁着项目测试的空白时间,看了一下. 整个underscore包括了常用的工具函数,下面以1.3.3源码为例分析一下. _.size = function(o ...
- swift 加载 storyboard 里的UIViewController
let storyBoard:UIStoryboard! = UIStoryboard(name: "Main", bundle: nil) let deskVC:DeskView ...