|
導(dǎo)讀微信(WeChat)是騰訊公司于2011年1月21日推出的一個為智能終端提供即時通訊服務(wù)的免費(fèi)應(yīng)用程序,由張小龍所帶領(lǐng)的騰訊廣州研發(fā)中心產(chǎn)品團(tuán)隊(duì)打造 [2] 。微信支持跨通信運(yùn)營商、跨操作系統(tǒng)平臺... 微信(WeChat)是騰訊公司于2011年1月21日推出的一個為智能終端提供即時通訊服務(wù)的免費(fèi)應(yīng)用程序,由張小龍所帶領(lǐng)的騰訊廣州研發(fā)中心產(chǎn)品團(tuán)隊(duì)打造 [2] 。微信支持跨通信運(yùn)營商、跨操作系統(tǒng)平臺通過網(wǎng)絡(luò)快速發(fā)送免費(fèi)(需消耗少量網(wǎng)絡(luò)流量)語音短信、視頻、圖片和文字,同時,也可以使用通過共享流媒體內(nèi)容的資料和基于位置的社交插件“搖一搖”、“漂流瓶”、“朋友圈”、”公眾平臺“、”語音記事本“等服務(wù)插件。 這是一個基于Python的微信公眾號開發(fā)之顏值檢測,今天我們把用戶的圖片通過騰訊的AI平臺分析后再返回給用戶。來一起體驗(yàn)下公眾號的顏值檢測吧效果圖
一. 接入騰訊AI平臺我們先看一下官方人臉檢測與分析接口的描述: 檢測給定圖片(Image)中的所有人臉(Face)的位置和相應(yīng)的面部屬性。位置包括(x, y, w, h),面部屬性包括性別(gender), 年齡(age), 表情(expression), 魅力(beauty), 眼鏡(glass)和姿態(tài)(pitch,roll,yaw)。 請求參數(shù)包括下面幾個:
1.接口鑒權(quán),構(gòu)造請求參數(shù)官方給了我們接口鑒權(quán)的計算方法。
2.請求接口地址請求接口信息,我們用 requests 發(fā)送請求,會得到返回的 json 格式的圖像信息 3.處理返回的信息處理返回的信息,把信息展示在圖片上,再把處理后的圖片保存。這里我們用到 opencv ,和 pillow 兩個庫 開始編寫代碼,我們新建一個face_id.py 文件來對接AI平臺,并且返回檢測后的圖像數(shù)據(jù)。 import time
import random
import base64
import hashlib
import requests
from urllib.parse import urlencode
import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import os
# 一.計算接口鑒權(quán),構(gòu)造請求參數(shù)
def random_str():
'''得到隨機(jī)字符串nonce_str'''
str = 'abcdefghijklmnopqrstuvwxyz'
r = ''
for i in range(15):
index = random.randint(0,25)
r += str[index]
return r
def image(name):
with open(name, 'rb') as f:
content = f.read()
return base64.b64encode(content)
def get_params(img):
'''組織接口請求的參數(shù)形式,并且計算sign接口鑒權(quán)信息,
最終返回接口請求所需要的參數(shù)字典'''
params = {
'app_id': '1106860829',
'time_stamp': str(int(time.time())),
'nonce_str': random_str(),
'image': img,
'mode': '0'
}
sort_dict = sorted(params.items(), key=lambda item: item[0], reverse=False) # 排序
sort_dict.append(('app_key', 'P8Gt8nxi6k8vLKbS')) # 添加app_key
rawtext = urlencode(sort_dict).encode() # URL編碼
sha = hashlib.md5()
sha.update(rawtext)
md5text = sha.hexdigest().upper() # 計算出sign,接口鑒權(quán)
params['sign'] = md5text # 添加到請求參數(shù)列表中
return params
# 二.請求接口URL
def access_api(img):
frame = cv2.imread(img)
nparry_encode = cv2.imencode('.jpg', frame)[1]
data_encode = np.array(nparry_encode)
img_encode = base64.b64encode(data_encode) # 圖片轉(zhuǎn)為base64編碼格式
url = 'https://api.ai.qq.com/fcgi-bin/face/face_detectface'
res = requests.post(url, get_params(img_encode)).json() # 請求URL,得到j(luò)son信息
# 把信息顯示到圖片上
if res['ret'] == 0: # 0代表請求成功
pil_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) # 把opencv格式轉(zhuǎn)換為PIL格式,方便寫漢字
draw = ImageDraw.Draw(pil_img)
for obj in res['data']['face_list']:
img_width = res['data']['image_width'] # 圖像寬度
img_height = res['data']['image_height'] # 圖像高度
# print(obj)
x = obj['x'] # 人臉框左上角x坐標(biāo)
y = obj['y'] # 人臉框左上角y坐標(biāo)
w = obj['width'] # 人臉框?qū)挾? h = obj['height'] # 人臉框高度
# 根據(jù)返回的值,自定義一下顯示的文字內(nèi)容
if obj['glass'] == 1: # 眼鏡
glass = '有'
else:
glass = '無'
if obj['gender'] >= 70: # 性別值從0-100表示從女性到男性
gender = '男'
elif 50 <= obj['gender'] < 70:
gender = "娘"
elif obj['gender'] < 30:
gender = '女'
else:
gender = '女漢子'
if 90 < obj['expression'] <= 100: # 表情從0-100,表示笑的程度
expression = '一笑傾城'
elif 80 < obj['expression'] <= 90:
expression = '心花怒放'
elif 70 < obj['expression'] <= 80:
expression = '興高采烈'
elif 60 < obj['expression'] <= 70:
expression = '眉開眼笑'
elif 50 < obj['expression'] <= 60:
expression = '喜上眉梢'
elif 40 < obj['expression'] <= 50:
expression = '喜氣洋洋'
elif 30 < obj['expression'] <= 40:
expression = '笑逐顏開'
elif 20 < obj['expression'] <= 30:
expression = '似笑非笑'
elif 10 < obj['expression'] <= 20:
expression = '半嗔半喜'
elif 0 <= obj['expression'] <= 10:
expression = '黯然傷神'
delt = h // 5 # 確定文字垂直距離
# 寫入圖片
if len(res['data']['face_list']) > 1: # 檢測到多個人臉,就把信息寫入人臉框內(nèi)
font = ImageFont.truetype('yahei.ttf', w // 8, encoding='utf-8') # 提前把字體文件下載好
draw.text((x + 10, y + 10), '性別 :' + gender, (76, 176, 80), font=font)
draw.text((x + 10, y + 10 + delt * 1), '年齡 :' + str(obj['age']), (76, 176, 80), font=font)
draw.text((x + 10, y + 10 + delt * 2), '表情 :' + expression, (76, 176, 80), font=font)
draw.text((x + 10, y + 10 + delt * 3), '魅力 :' + str(obj['beauty']), (76, 176, 80), font=font)
draw.text((x + 10, y + 10 + delt * 4), '眼鏡 :' + glass, (76, 176, 80), font=font)
elif img_width - x - w < 170: # 避免圖片太窄,導(dǎo)致文字顯示不完全
font = ImageFont.truetype('yahei.ttf', w // 8, encoding='utf-8')
draw.text((x + 10, y + 10), '性別 :' + gender, (76, 176, 80), font=font)
draw.text((x + 10, y + 10 + delt * 1), '年齡 :' + str(obj['age']), (76, 176, 80), font=font)
draw.text((x + 10, y + 10 + delt * 2), '表情 :' + expression, (76, 176, 80), font=font)
draw.text((x + 10, y + 10 + delt * 3), '魅力 :' + str(obj['beauty']), (76, 176, 80), font=font)
draw.text((x + 10, y + 10 + delt * 4), '眼鏡 :' + glass, (76, 176, 80), font=font)
else:
font = ImageFont.truetype('yahei.ttf', 20, encoding='utf-8')
draw.text((x + w + 10, y + 10), '性別 :' + gender, (76, 176, 80), font=font)
draw.text((x + w + 10, y + 10 + delt * 1), '年齡 :' + str(obj['age']), (76, 176, 80), font=font)
draw.text((x + w + 10, y + 10 + delt * 2), '表情 :' + expression, (76, 176, 80), font=font)
draw.text((x + w + 10, y + 10 + delt * 3), '魅力 :' + str(obj['beauty']), (76, 176, 80), font=font)
draw.text((x + w + 10, y + 10 + delt * 4), '眼鏡 :' + glass, (76, 176, 80), font=font)
draw.rectangle((x, y, x + w, y + h), outline="#4CB050") # 畫出人臉方框
cv2img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR) # 把 pil 格式轉(zhuǎn)換為 cv
cv2.imwrite('faces/{}'.format(os.path.basename(img)), cv2img) # 保存圖片到 face 文件夾下
return '檢測成功'
else:
return '檢測失敗'到這里我們的人臉檢測接口接入及圖片處理就完成了。之后在收到用戶發(fā)送的圖片信息后,調(diào)用這個函數(shù),把處理后的圖片返回給用戶就可以。 返回圖片給用戶當(dāng)收到用戶圖片時,需要以下幾個步驟: 保存圖片當(dāng)接收到用戶圖片后,我們要先把圖片保存起來,之后才能去調(diào)用人臉分析接口,把圖片信息傳遞過去,我們需要編寫一個 img_download 函數(shù)來下載圖片。詳見下方代碼 調(diào)用人臉分析接口圖片下載后,調(diào)用 face_id.py 文件里的接口函數(shù),得到處理后的圖片。 上傳圖片檢測結(jié)果是一張新的圖片,要把圖片發(fā)送給用戶我們需要一個 Media_ID,要獲取Media_ID必須先把圖片上傳為臨時素材,所以這里我們需要一個img_upload函數(shù)來上傳圖片,并且在上傳時需要用到一個access_token,我們通過一個函數(shù)來獲取. 獲取access_token必須要把我們自己的IP地址加入白名單,否則是獲取不到的。請登錄“微信公眾平臺-開發(fā)-基本配置”提前將服務(wù)器IP地址添加到IP白名單中,可以在http://ip.qq.com/查看本機(jī)的IP... 開始編寫代碼,我們新建一個 utils.py 來下載、上傳圖片 import requests
import json
import threading
import time
import os
token = ''
app_id = 'wxfc6adcdd7593a712'
secret = '429d85da0244792be19e0deb29615128'
def img_download(url, name):
r = requests.get(url)
with open('images/{}-{}.jpg'.format(name, time.strftime("%Y_%m_%d%H_%M_%S", time.localtime())), 'wb') as fd:
fd.write(r.content)
if os.path.getsize(fd.name) >= 1048576:
return 'large'
# print('namename', os.path.basename(fd.name))
return os.path.basename(fd.name)
def get_access_token(appid, secret):
'''獲取access_token,100分鐘刷新一次'''
url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}'.format(appid, secret)
r = requests.get(url)
parse_json = json.loads(r.text)
global token
token = parse_json['access_token']
global timer
timer = threading.Timer(6000, get_access_token)
timer.start()
def img_upload(mediaType, name):
global token
url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s" % (token, mediaType)
files = {'media': open('{}'.format(name), 'rb')}
r = requests.post(url, files=files)
parse_json = json.loads(r.text)
return parse_json['media_id']
get_access_token(app_id, secret)返回給用戶我們簡單修改下收到圖片后的邏輯,收到圖片后經(jīng)過人臉檢測,上傳獲得Media_ID,我們要做的就是把圖片返回給用戶即可。直接看connect.py的代碼 import falcon
from falcon import uri
from wechatpy.utils import check_signature
from wechatpy.exceptions import InvalidSignatureException
from wechatpy import parse_message
from wechatpy.replies import TextReply, ImageReply
from utils import img_download, img_upload
from face_id import access_api
class Connect(object):
def on_get(self, req, resp):
query_string = req.query_string
query_list = query_string.split('&')
b = {}
for i in query_list:
b[i.split('=')[0]] = i.split('=')[1]
try:
check_signature(token='lengxiao', signature=b['signature'], timestamp=b['timestamp'], nonce=b['nonce'])
resp.body = (b['echostr'])
except InvalidSignatureException:
pass
resp.status = falcon.HTTP_200
def on_post(self, req, resp):
xml = req.stream.read()
msg = parse_message(xml)
if msg.type == 'text':
reply = TextReply(content=msg.content, message=msg)
xml = reply.render()
resp.body = (xml)
resp.status = falcon.HTTP_200
elif msg.type == 'image':
name = img_download(msg.image, msg.source) # 下載圖片
r = access_api('images/' + name)
if r == '檢測成功':
media_id = img_upload('image', 'faces/' + name) # 上傳圖片,得到 media_id
reply = ImageReply(media_id=media_id, message=msg)
else:
reply = TextReply(content='人臉檢測失敗,請上傳1M以下人臉清晰的照片', message=msg)
xml = reply.render()
resp.body = (xml)
resp.status = falcon.HTTP_200
app = falcon.API()
connect = Connect()
app.add_route('/connect', connect)至此我們的工作就做完了,我們的公眾號可以進(jìn)行顏值檢測了。本來我打算用在自己公眾號上的,但是還存在下面幾個問題,所以沒有使用。
所以,我并沒有在我的公眾號上啟用這個程序,但是如果有認(rèn)證的公眾號,可以嘗試開發(fā)各種好玩的功能。 相關(guān)推薦: 微信公眾平臺開發(fā)一鍵關(guān)注微信公眾平臺賬號 以上就是來看看你的顏值多高吧!基于Python開發(fā)的公眾號的詳細(xì)內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章! 微信提供公眾平臺、朋友圈、消息推送等功能,用戶可以通過“搖一搖”、“搜索號碼”、“附近的人”、掃二維碼方式添加好友和關(guān)注公眾平臺,同時微信將內(nèi)容分享給好友以及將用戶看到的精彩內(nèi)容分享到微信朋友圈。 |
溫馨提示:喜歡本站的話,請收藏一下本站!