感谢优秀的你打开了小白的文章
“希望在看文章的你今天又进步了一点点,离美好生活更近一步!”
目录
前言
部分函数解释
人脸检测返回数据参数详情
获取结果
在进行人脸识别之前,要对人脸的特征进行检测,获取关键部位信息。百度的api提供这一接口。对一张照片的人脸进行关键特征部位的检测,本文提供以下代码供参考。
五官位置会标记具体坐标;72个关键点坐标也包含具体坐标,但不包含对应位置的详细位置描述。
# -*- coding: utf-8 -*-
#
from aip import AipFace
import cv2
import base64
import math
import matplotlib.pyplot as plt
from graphics import*
#import tkinter as tk
from tkinter import filedialog
from time import sleep
APP_ID = '16290061'
API_KEY = '4uKwGeC2Ci7aHbn6dHuYIrGc'
SECRET_KEY = 'KRdPZdtYwLsdEthIGu03jb7GEeRtTUMF'
aipFace = AipFace(APP_ID, API_KEY, SECRET_KEY)
filepath = "C:/Users/ZXY13/Desktop/train_face/1.jpg"
win = GraphWin('人脸关键点检测', 500, 90)
win.setBackground("yellow")
Text(Point(win.getWidth()/2, 40), "请在文件夹中选择一张人脸图片进行关键点检测").draw(win)
sleep(1)
filepath = filedialog.askopenfilename()
from PIL import Image
im = Image.open(filepath)
with open(filepath, "rb") as fp:
base64_data = base64.b64encode(fp.read())
image = str(base64_data, 'utf-8')
imageType = "BASE64"
options = {}
options["face_field"] = "age,beauty,expression,faceshape,gender,glasses,landmark,race,quality,facetype"
options["max_face_num"] = 10
options["face_type"] = "LIVE"
result = aipFace.detect(image, imageType, options)
img = cv2.imread(filepath)
face_num = result['result']['face_num']
face_list = result['result']['face_list']
xvalue = []
yvalue = []
xvaluef = []
yvaluef = []
plt.figure(figsize=(9,6.5))
for num in range(0,int(face_num)):
location = result['result']['face_list'][num-1]['location']
landmark72 = result['result']['face_list'][num-1]['landmark72']
xvaluef1 = []
yvaluef1 = []
xvaluef2 = []
yvaluef2 = []
xvaluef3 = []
yvaluef3 = []
xvaluef4 = []
yvaluef4 = []
xvaluef5 = []
yvaluef5 = []
xvaluef6 = []
yvaluef6 = []
xvaluef7 = []
yvaluef7 = []
xvaluef8 = []
yvaluef8 = []
for i in range(0,72):
xvalue.append(landmark72[i]['x'])
yvalue.append(landmark72[i]['y'])
xvaluef.append(im.size[0]-landmark72[i]['x'])
yvaluef.append(im.size[1]-landmark72[i]['y'])
for i in range(0,13):
xvaluef1.append(landmark72[i]['x'])
yvaluef1.append(im.size[1]-landmark72[i]['y'])
for i in range(13,21):
xvaluef2.append(landmark72[i]['x'])
yvaluef2.append(im.size[1]-landmark72[i]['y'])
xvaluef2.append(landmark72[13]['x'])
yvaluef2.append(im.size[1]-landmark72[13]['y'])
for i in range(22,30):
xvaluef3.append(landmark72[i]['x'])
yvaluef3.append(im.size[1]-landmark72[i]['y'])
xvaluef3.append(landmark72[22]['x'])
yvaluef3.append(im.size[1]-landmark72[22]['y'])
for i in range(30,38):
xvaluef4.append(landmark72[i]['x'])
yvaluef4.append(im.size[1]-landmark72[i]['y'])
xvaluef4.append(landmark72[30]['x'])
yvaluef4.append(im.size[1]-landmark72[30]['y'])
for i in range(39,47):
xvaluef5.append(landmark72[i]['x'])
yvaluef5.append(im.size[1]-landmark72[i]['y'])
xvaluef5.append(landmark72[39]['x'])
yvaluef5.append(im.size[1]-landmark72[39]['y'])
for i in range(47,57):
xvaluef6.append(landmark72[i]['x'])
yvaluef6.append(im.size[1]-landmark72[i]['y'])
xvaluef6.append(landmark72[47]['x'])
yvaluef6.append(im.size[1]-landmark72[47]['y'])
for i in range(58,66):
xvaluef7.append(landmark72[i]['x'])
yvaluef7.append(im.size[1]-landmark72[i]['y'])
xvaluef7.append(landmark72[58]['x'])
yvaluef7.append(im.size[1]-landmark72[58]['y'])
for i in range(66,71):
xvaluef8.append(landmark72[i]['x'])
yvaluef8.append(im.size[1]-landmark72[i]['y'])
xvaluef8.append(landmark72[66]['x'])
yvaluef8.append(im.size[1]-landmark72[66]['y'])
plt.subplot(2,2,num+2)
plt.plot(xvaluef1,yvaluef1)#'ro',markersize=1
plt.plot(xvaluef2,yvaluef2)
plt.plot(xvaluef3,yvaluef3)
plt.plot(xvaluef4,yvaluef4)
plt.plot(xvaluef5,yvaluef5)
plt.plot(xvaluef6,yvaluef6)
plt.plot(xvaluef7,yvaluef7)
plt.plot(xvaluef8,yvaluef8)
plt.axis('off')
Theta = location['rotation'] / 60
A = (int(location['left']),int(location['top']))
B = (int(location['left'])+int(location['width']*math.cos(Theta)),int(location['top'])+int(location['width']*math.sin(Theta)))
AC_Len = math.sqrt(location['width']**2 + location['height']**2)
AC_Theta = math.atan(location['height']/location['width'])+location['rotation']/60
C = (int(location['left']) + int(AC_Len*math.cos(AC_Theta)), int(location['top'])+int(AC_Len*math.sin(AC_Theta)))
D = (int(location['left'])-int(location['height']*math.sin(Theta)), int(location['top']) + int(location['height']*math.cos(Theta)))
cv2.line(img, A, B, (0, 0, 255), 2)
cv2.line(img, B, C, (0, 0, 255), 2)
cv2.line(img, C, D, (0, 0, 255), 2)
cv2.line(img, D, A, (0, 0, 255), 2)
plt.axis('off')
plt.subplot(2,2,1)
img = img[:,:,[2,1,0]]
plt.imshow(img,cmap='gray')
plt.plot(xvalue,yvalue,'bo',markersize=1)
plt.axis('off')
plt.show()
plt.figure(figsize=(9,6.5))
plt.imshow(img,'gray')
plt.plot(xvalue,yvalue,'bo',markersize=1)
plt.axis('off')
plt.show()
BASE64:图片的base64值,base64编码后的图片数据,需urlencode,编码后的图片大小不超过2M;
options[“face_field”]:在”face_field”我们可以选择我们需要百度云服务器回传的信息,如年龄(age),美貌评分(beauty),表情(expression),等等。若想选择这些参数,只需将其所表示的英文名称赋值于options[“face_field”]就可以了,比如我想检测出我上传的图片的人是啥人种,年龄大致多少,就可以这么写。
aipFace.detect(image, imageType, options):即为面部检测函数,内部可填入三个参数,image,imageType,options。这三个参数你也已经在上面的代码中赋值好了
log_id | uint64 | 是 | 日志id |
result_num | uint32 | 是 | 人脸数目 |
result | object[] | 是 | 人脸属性对象的集合 |
+age | double | 否 | 年龄。face_fields包含age时返回 |
+beauty | double | 否 | 美丑打分,范围0-100,越大表示越美。face_fields包含beauty时返回 |
+location | object | 是 | 人脸在图片中的位置 |
++left | uint32 | 是 | 人脸区域离左边界的距离 |
++top | uint32 | 是 | 人脸区域离上边界的距离 |
++width | uint32 | 是 | 人脸区域的宽度 |
++height | uint32 | 是 | 人脸区域的高度 |
+face_probability | double | 是 | 人脸置信度,范围0-1 |
+rotation_angle | int32 | 是 | 人脸框相对于竖直方向的顺时针旋转角,[-180,180] |
+yaw | double | 是 | 三维旋转之左右旋转角[-90(左), 90(右)] |
+pitch | double | 是 | 三维旋转之俯仰角度[-90(上), 90(下)] |
+roll | double | 是 | 平面内旋转角[-180(逆时针), 180(顺时针)] |
+expression | uint32 | 否 | 表情,0,不笑;1,微笑;2,大笑。face_fields包含expression时返回 |
+expression_probability | double | 否 | 表情置信度,范围0~1。face_fields包含expression时返回 |
+faceshape | object[] | 否 | 脸型置信度。face_fields包含faceshape时返回 |
++type | string | 是 | 脸型:square/triangle/oval/heart/round |
++probability | double | 是 | 置信度:0~1 |
+gender | string | 否 | male、female。face_fields包含gender时返回 |
+gender_probability | double | 否 | 性别置信度,范围0~1。face_fields包含gender时返回 |
+glasses | uint32 | 否 | 是否带眼镜,0-无眼镜,1-普通眼镜,2-墨镜。face_fields包含glasses时返回 |
+glasses_probability | double | 否 | 眼镜置信度,范围0~1。face_fields包含glasses时返回 |
+landmark | object[] | 否 | 4个关键点位置,左眼中心、右眼中心、鼻尖、嘴中心。face_fields包含landmark时返回 |
++x | uint32 | 否 | x坐标 |
++y | uint32 | 否 | y坐标 |
+landmark72 | object[] | 否 | 72个特征点位置,示例图 。face_fields包含landmark时返回 |
++x | uint32 | 否 | x坐标 |
++y | uint32 | 否 | y坐标 |
+qualities | object | 否 | 人脸质量信息。face_fields包含qualities时返回 |
++occlusion | object | 是 | 人脸各部分遮挡的概率,[0, 1],0表示完整,1表示不完整 |
+++left_eye | double | 是 | 左眼 |
+++right_eye | double | 是 | 右眼 |
+++nose | double | 是 | 鼻子 |
+++mouth | double | 是 | 嘴 |
+++left_cheek | double | 是 | 左脸颊 |
+++right_cheek | double | 是 | 右脸颊 |
+++chin | double | 是 | 下巴 |
++blur | double | 是 | 人脸模糊程度,[0, 1]。0表示清晰,1表示模糊 |
++illumination | - | 是 | 取值范围在[0,255],表示脸部区域的光照程度 |
++completeness | - | 是 | 人脸完整度,[0, 1]。0表示完整,1表示不完整 |
++type | object | 是 | 真实人脸/卡通人脸置信度 |
+++human | - | 是 | 真实人脸置信度,[0, 1] |
+++cartoon | - | 是 | 卡通人脸置信度,[0, 1] |
这些就是我们在进行人脸识别的依据的特征信息。
代码也可通过公众号获取