本文共 9880 字,大约阅读时间需要 32 分钟。
主要是使用OpenCV和Python进行人脸面部的检测。
1.在linux上安装OpenCV等软件
sudo apt-get updatesudo apt-get install vim build-essential python-software-properties sudo apt-get install python-opencv python-numpy python-scipysudo apt-get install libopencv-dev libopencv-contrib-devsudo apt-get install python-picamera python-pil python-tk
测试opencv的状态
pi@raspberrypi:~$ pythonPython 2.7.9 (default, Sep 17 2016, 20:26:04)[GCC 4.9.2] on linux2Type "help", "copyright", "credits" or "license" for more information.>>> import cv2>>> print cv2.__version__2.4.9.1
2.下载人脸检测的Haar特征分类器
$ wget http://eclecti.cc/files/2008/03/haarcascade_frontalface_alt.xml
人脸的Haar特征分类器就是一个XML文件,该文件会描述人脸的Haar的特征值。Haar特征的用途可不止可以用来描述人脸这一种,用来描述眼睛,嘴唇或是其它物体也是可以的。
当然OpenCV已经自带了人脸的Haar特征分类器。OpenCv安装目录中的\data\haarcascades目录下的haarcascade_frontalface_alt.xml与haarcascade_frontalface_alt2.xml都是用来检测人脸的Haar分类器。这个haarcascades目录下还有人的全身,眼睛,嘴唇的Haar分类器。
3.检查图片中的人脸图像
(1)首先我们新建一个face目录用来存放整个项目的数据和源码
(2)获取原始图像
raspistill -o image.jpg
(3)对image.jpg原始图像进行人脸识别
jiance.py代码
import cv2def detect(path): img = cv2.imread(path) cascade = cv2.CascadeClassifier("/home/pi/haarcascade_frontalface_alt.xml") rects = cascade.detectMultiScale(img, 1.3, 4, cv2.cv.CV_HAAR_SCALE_IMAGE, (20,20)) if len(rects) == 0: return [], img rects[:, 2:] += rects[:, :2] return rects, imgdef box(rects, img): for x1, y1, x2, y2 in rects: cv2.rectangle(img, (x1, y1), (x2, y2), (127, 255, 0), 2) cv2.imwrite('/home/pi/face/handle_data/image.jpg', img);rects, img = detect("/home/pi/face/data/image.jpg")box(rects, img)
(4)识别出的图片存储在handle_data中
4.对检测出人脸的图片进行裁剪,裁剪出人脸图像
(1)face.py代码
#-*-coding:utf8-*-import osimport cv2import timeimport shutildef getAllPath(dirpath, *suffix): PathArray = [] for r, ds, fs in os.walk(dirpath): for fn in fs: if os.path.splitext(fn)[1] in suffix: fname = os.path.join(r, fn) PathArray.append(fname) return PathArray#从源路径中读取所有图片放入一个list,然后逐一进行检查,把其中的脸扣下来,存储到目标路径中def readPicSaveFace(sourcePath,targetPath,invalidPath,*suffix): try: ImagePaths=getAllPath(sourcePath, *suffix) #对list中图片逐一进行检查,找出其中的人脸然后写到目标文件夹下 count = 1 # haarcascade_frontalface_alt.xml为库训练好的分类器文件,下载opencv,安装目录中可找到 face_cascade = cv2.CascadeClassifier('/home/pi/haarcascade_frontalface_alt.xml') for imagePath in ImagePaths: img = cv2.imread(imagePath) if type(img) != str: faces = face_cascade.detectMultiScale(img, 1.1, 5) if len(faces): for (x, y, w, h) in faces: # 设置人脸宽度大于128像素,去除较小的人脸 if w>=128 and h>=128: # 以时间戳和读取的排序作为文件名称 listStr = [str(int(time.time())), str(count)] fileName = ''.join(listStr) # 扩大图片,可根据坐标调整 X = int(x*1) W = min(int((x + w)*1),img.shape[1]) Y = int(y*1) H = min(int((y + h)*1),img.shape[0]) f = cv2.resize(img[Y:H, X:W], (W-X,H-Y)) cv2.imwrite(targetPath+os.sep+'%s.jpg' % fileName, f) count += 1 print imagePath + "have face" else: shutil.move(imagePath, invalidPath) except IOError: print "Error" else: print 'Find '+str(count-1)+' faces to Destination '+targetPathif __name__ == '__main__': invalidPath = r'/home/pi/face/haveNoPeople' sourcePath = r'/home/pi/face/data' targetPath = r'/home/pi/face/faceOfPeople' readPicSaveFace(sourcePath,targetPath,invalidPath,'.jpg','.JPG','png','PNG')
(2)裁剪出的人脸图像
5.在树莓派上实现人脸识别验证操作
在这里我们利用Face++视觉服务平台,将树莓派作为硬件载体,使用Face++人脸识别云平台搭建一个人脸识别验证的登录系统。
(1)face++的注册与配置
首先登入face++的官方网站
点击右上角的注册按钮进入注册界面,按步骤完成注册信息填写并进行邮箱验证。 在概览界面可以看到快速开始栏,点击“填写开发者资料”完善相关资料。之后按步骤进行API Key的创建,这是非常关键的一步。
其中类型一定要填写试用,只有创建试用API Key才能使用 API 免费服务,并且一个用户只能有一个免费API Key。免费服务是有一些限制的:
Face 存储有上限:每个用户使用免费服务只能创建 1000个 FaceSet,总计最多存储 100 万个人脸。
一个用户只能有一个 API Key 使用免费服务,而且该 API Key 不能转为正式 API Key。SDK 不提供免费使用或免费测试。
之后在应用管理-API Key界面就可以看到两个非常关键的参数,API Key和API Secret,在所有的POST调用当中均需要这两个参数。
(2)人脸识别的模块
文档中心https://console.faceplusplus.com.cn/documents/4888373
传入图片进行人脸检测和人脸分析。
可以检测图片内的所有人脸,对于每个检测出的人脸,会给出其唯一标识 face_token,可用于后续的人脸分析、人脸比对等操作。对于正式 API Key,支持指定图片的某一区域进行人脸检测。
如果您需要将检测出的人脸用于后续的分析、比对等操作,建议将对应的 face_token 添加到 FaceSet 中。如果一个 face_token 在 72 小时内没有存放在任一 FaceSet 中,则该 face_token 将会失效。
如果对同一张图片进行多次人脸检测,同一个人脸得到的 face_token 是不同的。
调用URL:
是否必选 | 参数名 | 类型 | 参数说明 | ||||||
必选 | api_key | String | 调用此API的API Key | ||||||
必选 | api_secret | String | 调用此API的API Secret | ||||||
必选(三选一) | image_url | String | 图片的 URL。 注:在下载图片时可能由于网络等原因导致下载图片时间过长,建议使用 image_file 或 image_base64 参数直接上传图片。 | ||||||
image_file | File | 一个图片,二进制文件,需要用post multipart/form-data的方式上传。 | |||||||
image_base64 | String | base64 编码的二进制图片数据 如果同时传入了 image_url、image_file 和 image_base64 参数,本API使用顺序为 image_file 优先,image_url 最低。 | |||||||
可选 | return_landmark | Int | 是否检测并返回人脸关键点。合法值为:
注:本参数默认值为 0 | ||||||
可选 | return_attributes | String | 是否检测并返回根据人脸特征判断出的年龄、性别、情绪等属性。合法值为:
注:本参数默认值为 none | ||||||
可选(仅正式 API Key 可以使用) | calculate_all | Int | 是否检测并返回所有人脸的人脸关键点和人脸属性。如果不使用此功能,则本 API 只会对人脸面积最大的五个人脸分析人脸关键点和人脸属性。合法值为:
注:本参数默认值为 0 | ||||||
可选(仅正式 API Key 可以使用) | face_rectangle | String | 是否指定人脸框位置进行人脸检测。 如果此参数传入值为空,或不传入此参数,则不使用此功能。本 API 会自动检测图片内所有区域的所有人脸。 如果使用正式 API Key 对此参数传入符合格式要求的值,则使用此功能。需要传入一个字符串代表人脸框位置,系统会根据此坐标对框内的图像进行人脸检测,以及人脸关键点和人脸属性等后续操作。系统返回的人脸矩形框位置会与传入的 face_rectangle 完全一致。对于此人脸框之外的区域,系统不会进行人脸检测,也不会返回任何其他的人脸信息。 参数规格:四个正整数,用逗号分隔,依次代表人脸框左上角纵坐标(top),左上角横坐标(left),人脸框宽度(width),人脸框高度(height)。例如:70,80,100,100 |
代码face_token.py用来获取图片的face_token的值
#coding=utf8import cv2import requestsimport jsonurl = 'https://api-cn.faceplusplus.com/facepp/v3/detect'files = {'image_file':open('owner.jpg', 'rb')}payload = {'api_key': '**填入你的api值***', 'api_secret': '**填写你的api值**', 'return_landmark': 0, 'return_attributes':'gender,age,glass'}r = requests.post(url,files=files,data=payload)data=json.loads(r.text)print r.textwidth = data['faces'][0]['face_rectangle']['width']top = data['faces'][0]['face_rectangle']['top']height = data['faces'][0]['face_rectangle']['height']left = data['faces'][0]['face_rectangle']['left']img = cv2.imread("owner.jpg")vis = img.copy()cv2.rectangle(vis, (left, top), (left+width, top+height),(0, 255, 0), 2)cv2.imshow("Image", vis)cv2.waitKey (0)
获取的face_token值,需保存,后续要用。
(3)人脸集合建立的模块
文档中心:https://console.faceplusplus.com.cn/documents/4888391
创建一个人脸的集合FaceSet,用于存储人脸标识face_token。一个FaceSet能够存储1,000个face_token。
调用URL:
是否必选 | 参数名 | 类型 | 参数说明 |
必选 | api_key | String | 调用此 API 的 API Key |
必选 | api_secret | String | 调用此 API 的 API Secret |
可选 | display_name | String | 人脸集合的名字,最长256个字符,不能包括字符^@,&=*'" |
可选 | outer_id | String | 账号下全局唯一的 FaceSet 自定义标识,可以用来管理 FaceSet 对象。最长255个字符,不能包括字符^@,&=*'" |
可选 | tags | String | FaceSet 自定义标签组成的字符串,用来对 FaceSet 分组。最长255个字符,多个 tag 用逗号分隔,每个 tag 不能包括字符^@,&=*'" |
可选 | face_tokens | String | 人脸标识 face_token,可以是一个或者多个,用逗号分隔。最多不超过5个 face_token |
可选 | user_data | String | 自定义用户信息,不大于16 KB,不能包括字符^@,&=*'" |
可选 | force_merge | Int | 在传入 outer_id 的情况下,如果 outer_id 已经存在,是否将 face_token 加入已经存在的 FaceSet 中 0:不将 face_tokens 加入已存在的 FaceSet 中,直接返回 FACESET_EXIST 错误 1:将 face_tokens 加入已存在的 FaceSet 中 默认值为0 |
face_tokens.py所需的代码
#coding=utf8import requestsurl = 'https://api-cn.faceplusplus.com/facepp/v3/faceset/create'payload = {'api_key': '***申请的值****', 'api_secret': '***申请的值***', 'display_name':'jiankong_lcz', 'outer_id':'jiankong_lcz', 'face_tokens':'上一步图片的face_token的值' }r = requests.post(url,data=payload)print r.text
返回的faceset_token值,也需要保存
(4)人脸搜索对比模块
文档中心:
在Faceset中找出与目标人脸最相似的一张或多张人脸。支持传入face_token或者直接传入图片进行人脸搜索。使用图片进行比对时会选取图片中检测到人脸尺寸最大的一个人脸。
调用URL:
是否必选 | 参数名 | 类型 | 参数说明 |
必选 | api_key | String | 调用此 API 的 API Key |
必选 | api_secret | String | 调用此 API 的 API Secret |
必选(四选一) | face_token | String | 进行搜索的目标人脸的 face_token,优先使用该参数 |
image_url | String | 目标人脸所在的图片的 URL | |
image_file | File | 目标人脸所在的图片,二进制文件,需要用 post multipart/form-data 的方式上传。 | |
image_base64 | String | base64 编码的二进制图片数据 如果同时传入了 image_url、image_file 和 image_base64 参数,本 API 使用顺序为 image_file 优先,image_url 最低。 | |
必选(二选一) | faceset_token | String | 用来搜索的 FaceSet 的标识 |
outer_id | String | 用户自定义的 FaceSet 标识 | |
可选 | return_result_count | Int | 控制返回比对置信度最高的结果的数量。合法值为一个范围 [1,5] 的整数。默认值为 1 |
可选(仅正式 API Key 可以使用) | face_rectangle | String | 当传入图片进行人脸检测时,是否指定人脸框位置进行检测。 如果此参数传入值为空,或不传入此参数,则不使用此功能。本 API 会自动检测图片内所有区域的所有人脸。 如果使用正式 API Key 对此参数传入符合格式要求的值,则使用此功能。需要传入一个字符串代表人脸框位置,系统会根据此坐标对框内的图像进行人脸检测,以及人脸关键点和人脸属性等后续操作。系统返回的人脸矩形框位置会与传入的 face_rectangle 完全一致。对于此人脸框之外的区域,系统不会进行人脸检测,也不会返回任何其他的人脸信息。 参数规格:四个正整数,用逗号分隔,依次代表人脸框左上角纵坐标(top),左上角横坐标(left),人脸框宽度(width),人脸框高度(height)。例如:70,80,100,100 注:只有在传入 image_url、image_file 和 image_base64 三个参数中任意一个时,本参数才生效。 |
distinguish.py所需的代码:
#coding=utf8import cv2import cv2.cv as cvimport requestsimport jsonimport picameraimport oscamera=picamera.PiCamera()camera.capture("current_photo.jpg")filename='current_photo.jpg'url = 'https://api-cn.faceplusplus.com/facepp/v3/search'payload = {'api_key': '***填入你申请的key值****', 'api_secret': '***填入你申请的key值****', 'faceset_token':'**上一步你获取对的faceset值**', }files = {'image_file':open('current_photo.jpg', 'rb')}r = requests.post(url,files=files,data=payload)data=json.loads(r.text)print r.textif os.path.exists(filename): os.remove(filename)if data["results"][0]["face_token"] == "***owner图片的face_token值***" and data["results"][0]["confidence"]>=data["thresholds"]["1e-5"]: print'\n主人'else: print '\n闯入者'
首先这个会调用树莓派的摄像头获取当前图像,并截图,截图成功之后会将这张人脸图片上传至云端进行对比并返回结果。
验证结果: