通知:今年的圣诞节推迟到2021年1月8日,因为圣诞老人到了之后还要被隔离14天。
马上就要圣诞节了,大家想好送什么礼物给自己对象了吗?
因为疫情原因,圣诞老人不能来中国给我们送礼物了,所以今年由我来给大家圣诞礼物——用python给你的头像戴圣诞帽!
我知道网上已经有很多关于这个的代码了,他们一般都是调用cv或者dlib的人脸识别库来实现,但今天我想通过调用百度AI的人脸识别接口来实现。
实现步骤
首先我们需要申请百度AI的密钥,之后就可以通过开发文档来进行人脸识别了。(我之前的一篇文章已经讲的十分清楚了python颜值分析,这里就不再描述。)
其次我们需要一个背景透明的圣诞帽。可以通过ps等软件把圣诞帽抠出来,也可以通过python代码。
python使图片白色背景变透明代码:
这是一个单独的python file,你可以命名为transparent.py
from PIL import Image
def transparent():
img = Image.open('hat.jpg')
# 图片转换为四通道。第四个通道就是我们要修改的透明度。
#RGBA是代表Red(红色)Green(绿色)Blue(蓝色)和Alpha的色彩空间。
#如果一个像素的alpha通道数值为0%,那它就是完全透明的(也就是看不见的),而数值为100%则意味着一个完全不透明的像素(传统的数字图像)。
img = img.convert('RGBA')
# 获取图片像素尺寸
width, height = img.size
pix = img.load()
#方法load()返回一个用于读取和修改像素的像素访问对象
#print(pixel_data[0,0])
for i in range(height):
for j in range(width):
pixel = pix[j, i]
r = pixel[0]
g = pixel[1]
b = pixel[2]
a = pixel[3]
# 四通道色彩值大于250(白色且不透明),则将像素点变为透明块
if r > 245 and g > 245 and b > 245 and a > 250:
pix[j, i] = (255, 255, 255, 0)
img.save('newhat.png') # 保存新图片
transparent()
原图:
透明化后:
然后我们需要通过百度AI人脸识别接口得到人脸位置、大小等信息。
获取人脸信息核心代码:
def face_identification(self):
# 人脸检测与属性分析
img = self.img_to_base64(self.img_src)
request_url = "https://aip.baidubce.com/rest/2.0/face/v3/detect"
post_data = {
"image": img,
"image_type": "BASE64",
"max_face_num":10,
"face_field": "face_num,face_list",#包括age,beauty,expression,face_shape,gender,glasses,landmark,emotion,face_type,mask,spoofing信息
"face_type": "LIVE"#人脸的类型。LIVE表示生活照,IDCARD表示身份证芯片照,WATERMARK表示带水印证件照,CERT表示证件照片,默认LIVE。
}
access_token = self.get_AccessToken()
request_url = request_url + "?access_token=" + access_token
response = requests.post(url=request_url, data=post_data, headers=self.headers)
json_result = json.loads(response.text)
print(json_result)
if json_result['error_code'] == 0:
a = 1
print('检测到的图片中的人脸数量:',json_result['result']['face_num'])
for i in json_result['result']['face_list']:
face_info = []
print('第{}张人脸信息:'.format(a))
a=a+1
left=i['location']['left']
face_info.append(left)
top=i['location']['top']
face_info.append(top)
width=i['location']['width']
face_info.append(width)
height=i['location']['height']
face_info.append(height)
print('人脸区域离左边界的距离:',left)
print('人脸区域离上边界的距离:', top)
print("人脸区域的宽度:",width )
print("人物区域的高度:", height)
faces.append(face_info)
#print("人物特征点位置:", json_result['result']['face_list'][0]['landmark72'])
else:
print(json_result['error_code'])
print(json_result['error_msg'])
最后我们需要根据人脸信息确定圣诞帽的位置。
确定圣诞帽位置代码:
def addhat(faces,face_image,hat_image):
for face in faces:
hat = cv2.imread(hat_image, -1) # 读入完整图片,包括alpha通道。
scale = face[3] / hat.shape[0] * 1.4
hat = cv2.resize(hat, (0, 0), fx=scale, fy=scale) # 改变帽子大小
x_offset = int(face[0] -10+face[2] / 2 - hat.shape[1] / 2)
y_offset = int(face[1] - hat.shape[0]/1) # 根据人脸坐标调整帽子位置
x1, x2 = max(x_offset, 0), min(x_offset + hat.shape[1], face_image.shape[1])
y1, y2 = max(y_offset, 0), min(y_offset + hat.shape[0], face_image.shape[0])
hat_x1 = max(0, -x_offset)
hat_x2 = hat_x1 + x2 - x1
hat_y1 = max(0, -y_offset)
hat_y2 = hat_y1 + y2 - y1 # 计算贴图位置
alpha_h = hat[hat_y1:hat_y2, hat_x1:hat_x2, 3] / 255 # 透明部分的处理
alpha = 1 - alpha_h
for c in range(0, 3):
face_image[y1:y2, x1:x2, c] = (alpha_h * hat[hat_y1:hat_y2, hat_x1:hat_x2, c] + alpha * face_image[y1:y2, x1:x2,c]) # 按3个通道合并图片
return face_image
上面代码参考于网上。
给头像添加圣诞帽完整代码:
这是另一个独立的python file,你可以命名为add_hat.py
# encoding:utf-8
import base64
import json
import requests
import cv2
class BaiduAI:
def __init__(self, img):
self.AK = ""#你的应用API Key
self.SK = ""#你的应用Secret Key
self.img_src = img
self.headers = {
"Content-Type": "application/json; charset=UTF-8"
}
def get_AccessToken(self):
#获取Access Token
host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' + self.AK + '&client_secret=' + self.SK
response = requests.get(host, headers=self.headers)
json_result = json.loads(response.text)
if response:
return json_result['access_token']
else:
print(json_result)
return 0
def img_to_base64(slef, path):
#图片转化为base64
with open(path, 'rb') as f:
image = f.read()
image_base64 = str(base64.b64encode(image), encoding='utf-8')
return image_base64
def face_identification(self):
# 人脸检测与属性分析
img = self.img_to_base64(self.img_src)
request_url = "https://aip.baidubce.com/rest/2.0/face/v3/detect"
post_data = {
"image": img,
"image_type": "BASE64",
"max_face_num":10,
"face_field": "face_num,face_list",#包括age,beauty,expression,face_shape,gender,glasses,landmark,emotion,face_type,mask,spoofing信息
"face_type": "LIVE"#人脸的类型。LIVE表示生活照,IDCARD表示身份证芯片照,WATERMARK表示带水印证件照,CERT表示证件照片,默认LIVE。
}
access_token = self.get_AccessToken()
request_url = request_url + "?access_token=" + access_token
response = requests.post(url=request_url, data=post_data, headers=self.headers)
json_result = json.loads(response.text)
print(json_result)
if json_result['error_code'] == 0:
a = 1
print('检测到的图片中的人脸数量:',json_result['result']['face_num'])
for i in json_result['result']['face_list']:
face_info = []
print('第{}张人脸信息:'.format(a))
a=a+1
left=i['location']['left']
face_info.append(left)
top=i['location']['top']
face_info.append(top)
width=i['location']['width']
face_info.append(width)
height=i['location']['height']
face_info.append(height)
print('人脸区域离左边界的距离:',left)
print('人脸区域离上边界的距离:', top)
print("人脸区域的宽度:",width )
print("人物区域的高度:", height)
faces.append(face_info)
#print("人物特征点位置:", json_result['result']['face_list'][0]['landmark72'])
else:
print(json_result['error_code'])
print(json_result['error_msg'])
def addhat(faces,face_image,hat_image):
for face in faces:
hat = cv2.imread(hat_image, -1) # 读入完整图片,包括alpha通道。
scale = face[3] / hat.shape[0] * 1.5
hat = cv2.resize(hat, (0, 0), fx=scale, fy=scale) # 改变帽子大小
x_offset = int(face[0] +face[2] / 2 - hat.shape[1] / 2)
y_offset = int(face[1] - hat.shape[0]/1.2) # 根据人脸坐标调整帽子位置
x1, x2 = max(x_offset, 0), min(x_offset + hat.shape[1], face_image.shape[1])
y1, y2 = max(y_offset, 0), min(y_offset + hat.shape[0], face_image.shape[0])
hat_x1 = max(0, -x_offset)
hat_x2 = hat_x1 + x2 - x1
hat_y1 = max(0, -y_offset)
hat_y2 = hat_y1 + y2 - y1 # 计算贴图位置
alpha_h = hat[hat_y1:hat_y2, hat_x1:hat_x2, 3] / 255 # 透明部分的处理
alpha = 1 - alpha_h
for c in range(0, 3):
face_image[y1:y2, x1:x2, c] = (alpha_h * hat[hat_y1:hat_y2, hat_x1:hat_x2, c] + alpha * face_image[y1:y2, x1:x2,c]) # 按3个通道合并图片
return face_image
if __name__ == '__main__':
img_file = ''
hat_file=''
faces=[]
demo = BaiduAI(img_file)
if(demo.get_AccessToken()):
demo.face_identification()
print(faces)
face_image = cv2.imread(img_file)
face_image=addhat(faces,face_image,hat_file)
cv2.imwrite('addhat_' + img_file, face_image)
说明:self.AK用你的应用API Key,self.SK用你的应用Secret Key。img_file用你的照片路径,hat_file用你的圣诞帽图片路径。
最终效果
原图:
戴上圣诞帽:
原图:
戴上圣诞帽:
这次的分享到此结束。
圣诞节要到了,送大家三千万。千万要开心,千万要快乐,千万要幸福!!!