Skip to content

Commit a5b61dd

Browse files
committedJun 16, 2018
face_id
1 parent 3568adb commit a5b61dd

File tree

6 files changed

+197
-3
lines changed

6 files changed

+197
-3
lines changed
 

‎wechat/README.MD

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# 详细使用请看文章
2+
3+
[Python微信公众号开发—小白篇(一)](https://mp.weixin.qq.com/s/iMPUC0yxI-zuf4AjtyAu6g)
4+
[Python公众号开发—颜值检测]

‎wechat/connect.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import falcon
2+
from falcon import uri
23
from wechatpy.utils import check_signature
34
from wechatpy.exceptions import InvalidSignatureException
45
from wechatpy import parse_message
56
from wechatpy.replies import TextReply, ImageReply
67

8+
from utils import img_download, img_upload
9+
from face_id import access_api
10+
711

812
class Connect(object):
913

@@ -25,18 +29,24 @@ def on_post(self, req, resp):
2529
xml = req.stream.read()
2630
msg = parse_message(xml)
2731
if msg.type == 'text':
32+
print('hello')
2833
reply = TextReply(content=msg.content, message=msg)
2934
xml = reply.render()
3035
resp.body = (xml)
3136
resp.status = falcon.HTTP_200
3237
elif msg.type == 'image':
33-
reply = ImageReply(media_id=msg.media_id, message=msg)
38+
name = img_download(msg.image, msg.source) # 下载图片
39+
print(name)
40+
r = access_api('images/' + name)
41+
if r == '检测成功':
42+
media_id = img_upload('image', 'faces/' + name) # 上传图片,得到 media_id
43+
reply = ImageReply(media_id=media_id, message=msg)
44+
else:
45+
reply = TextReply(content='人脸检测失败,请上传1M以下人脸清晰的照片', message=msg)
3446
xml = reply.render()
3547
resp.body = (xml)
3648
resp.status = falcon.HTTP_200
3749

38-
3950
app = falcon.API()
4051
connect = Connect()
4152
app.add_route('/connect', connect)
42-

‎wechat/face_id.py

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import time
2+
import random
3+
import base64
4+
import hashlib
5+
import requests
6+
from urllib.parse import urlencode
7+
import cv2
8+
import numpy as np
9+
from PIL import Image, ImageDraw, ImageFont
10+
import os
11+
12+
13+
# 一.计算接口鉴权,构造请求参数
14+
15+
def random_str():
16+
'''得到随机字符串nonce_str'''
17+
str = 'abcdefghijklmnopqrstuvwxyz'
18+
r = ''
19+
for i in range(15):
20+
index = random.randint(0,25)
21+
r += str[index]
22+
return r
23+
24+
25+
def image(name):
26+
with open(name, 'rb') as f:
27+
content = f.read()
28+
return base64.b64encode(content)
29+
30+
31+
def get_params(img):
32+
'''组织接口请求的参数形式,并且计算sign接口鉴权信息,
33+
最终返回接口请求所需要的参数字典'''
34+
params = {
35+
'app_id': '1106860829',
36+
'time_stamp': str(int(time.time())),
37+
'nonce_str': random_str(),
38+
'image': img,
39+
'mode': '0'
40+
41+
}
42+
43+
sort_dict = sorted(params.items(), key=lambda item: item[0], reverse=False) # 排序
44+
sort_dict.append(('app_key', 'P8Gt8nxi6k8vLKbS')) # 添加app_key
45+
rawtext = urlencode(sort_dict).encode() # URL编码
46+
sha = hashlib.md5()
47+
sha.update(rawtext)
48+
md5text = sha.hexdigest().upper() # 计算出sign,接口鉴权
49+
params['sign'] = md5text # 添加到请求参数列表中
50+
return params
51+
52+
# 二.请求接口URL
53+
54+
55+
def access_api(img):
56+
print(img)
57+
frame = cv2.imread(img)
58+
nparry_encode = cv2.imencode('.jpg', frame)[1]
59+
data_encode = np.array(nparry_encode)
60+
img_encode = base64.b64encode(data_encode) # 图片转为base64编码格式
61+
url = 'https://api.ai.qq.com/fcgi-bin/face/face_detectface'
62+
res = requests.post(url, get_params(img_encode)).json() # 请求URL,得到json信息
63+
# 把信息显示到图片上
64+
if res['ret'] == 0: # 0代表请求成功
65+
pil_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) # 把opencv格式转换为PIL格式,方便写汉字
66+
draw = ImageDraw.Draw(pil_img)
67+
for obj in res['data']['face_list']:
68+
img_width = res['data']['image_width'] # 图像宽度
69+
img_height = res['data']['image_height'] # 图像高度
70+
# print(obj)
71+
x = obj['x'] # 人脸框左上角x坐标
72+
y = obj['y'] # 人脸框左上角y坐标
73+
w = obj['width'] # 人脸框宽度
74+
h = obj['height'] # 人脸框高度
75+
# 根据返回的值,自定义一下显示的文字内容
76+
if obj['glass'] == 1: # 眼镜
77+
glass = '有'
78+
else:
79+
glass = '无'
80+
if obj['gender'] >= 70: # 性别值从0-100表示从女性到男性
81+
gender = '男'
82+
elif 50 <= obj['gender'] < 70:
83+
gender = "娘"
84+
elif obj['gender'] < 30:
85+
gender = '女'
86+
else:
87+
gender = '女汉子'
88+
if 90 < obj['expression'] <= 100: # 表情从0-100,表示笑的程度
89+
expression = '一笑倾城'
90+
elif 80 < obj['expression'] <= 90:
91+
expression = '心花怒放'
92+
elif 70 < obj['expression'] <= 80:
93+
expression = '兴高采烈'
94+
elif 60 < obj['expression'] <= 70:
95+
expression = '眉开眼笑'
96+
elif 50 < obj['expression'] <= 60:
97+
expression = '喜上眉梢'
98+
elif 40 < obj['expression'] <= 50:
99+
expression = '喜气洋洋'
100+
elif 30 < obj['expression'] <= 40:
101+
expression = '笑逐颜开'
102+
elif 20 < obj['expression'] <= 30:
103+
expression = '似笑非笑'
104+
elif 10 < obj['expression'] <= 20:
105+
expression = '半嗔半喜'
106+
elif 0 <= obj['expression'] <= 10:
107+
expression = '黯然伤神'
108+
delt = h // 5 # 确定文字垂直距离
109+
# 写入图片
110+
if len(res['data']['face_list']) > 1: # 检测到多个人脸,就把信息写入人脸框内
111+
font = ImageFont.truetype('yahei.ttf', w // 8, encoding='utf-8') # 提前把字体文件下载好
112+
draw.text((x + 10, y + 10), '性别 :' + gender, (76, 176, 80), font=font)
113+
draw.text((x + 10, y + 10 + delt * 1), '年龄 :' + str(obj['age']), (76, 176, 80), font=font)
114+
draw.text((x + 10, y + 10 + delt * 2), '表情 :' + expression, (76, 176, 80), font=font)
115+
draw.text((x + 10, y + 10 + delt * 3), '魅力 :' + str(obj['beauty']), (76, 176, 80), font=font)
116+
draw.text((x + 10, y + 10 + delt * 4), '眼镜 :' + glass, (76, 176, 80), font=font)
117+
elif img_width - x - w < 170: # 避免图片太窄,导致文字显示不完全
118+
font = ImageFont.truetype('yahei.ttf', w // 8, encoding='utf-8')
119+
draw.text((x + 10, y + 10), '性别 :' + gender, (76, 176, 80), font=font)
120+
draw.text((x + 10, y + 10 + delt * 1), '年龄 :' + str(obj['age']), (76, 176, 80), font=font)
121+
draw.text((x + 10, y + 10 + delt * 2), '表情 :' + expression, (76, 176, 80), font=font)
122+
draw.text((x + 10, y + 10 + delt * 3), '魅力 :' + str(obj['beauty']), (76, 176, 80), font=font)
123+
draw.text((x + 10, y + 10 + delt * 4), '眼镜 :' + glass, (76, 176, 80), font=font)
124+
else:
125+
font = ImageFont.truetype('yahei.ttf', 20, encoding='utf-8')
126+
draw.text((x + w + 10, y + 10), '性别 :' + gender, (76, 176, 80), font=font)
127+
draw.text((x + w + 10, y + 10 + delt * 1), '年龄 :' + str(obj['age']), (76, 176, 80), font=font)
128+
draw.text((x + w + 10, y + 10 + delt * 2), '表情 :' + expression, (76, 176, 80), font=font)
129+
draw.text((x + w + 10, y + 10 + delt * 3), '魅力 :' + str(obj['beauty']), (76, 176, 80), font=font)
130+
draw.text((x + w + 10, y + 10 + delt * 4), '眼镜 :' + glass, (76, 176, 80), font=font)
131+
132+
draw.rectangle((x, y, x + w, y + h), outline="#4CB050") # 画出人脸方框
133+
cv2img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR) # 把 pil 格式转换为 cv
134+
cv2.imwrite('faces/{}'.format(os.path.basename(img)), cv2img) # 保存图片到 face 文件夹下
135+
return '检测成功'
136+
else:
137+
return '检测失败'

‎wechat/requirements.txt

-195 Bytes
Binary file not shown.

‎wechat/utils.py

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import requests
2+
import json
3+
import threading
4+
import time
5+
import os
6+
7+
token = ''
8+
app_id = 'wxfc6adcdd7593a712'
9+
secret = '429d85da0244792be19e0deb29615128'
10+
11+
12+
def img_download(url, name):
13+
r = requests.get(url)
14+
with open('images/{}-{}.jpg'.format(name, time.strftime("%Y_%m_%d%H_%M_%S", time.localtime())), 'wb') as fd:
15+
fd.write(r.content)
16+
if os.path.getsize(fd.name) >= 1048576:
17+
return 'large'
18+
# print('namename', os.path.basename(fd.name))
19+
return os.path.basename(fd.name)
20+
21+
22+
def get_access_token(appid, secret):
23+
'''获取access_token,100分钟刷新一次'''
24+
25+
url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}'.format(appid, secret)
26+
r = requests.get(url)
27+
parse_json = json.loads(r.text)
28+
global token
29+
token = parse_json['access_token']
30+
global timer
31+
timer = threading.Timer(6000, get_access_token)
32+
timer.start()
33+
34+
35+
def img_upload(mediaType, name):
36+
global token
37+
url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s" % (token, mediaType)
38+
files = {'media': open('{}'.format(name), 'rb')}
39+
r = requests.post(url, files=files)
40+
parse_json = json.loads(r.text)
41+
return parse_json['media_id']
42+
43+
get_access_token(app_id, secret)

‎wechat/yahei.ttf

12.2 MB
Binary file not shown.

0 commit comments

Comments
 (0)
Please sign in to comment.