蒲城鄉(xiāng)來(lái)看看你的顏值多高吧!基于Python開(kāi)發(fā)的公眾號(hào)

閱讀 31330  ·  發(fā)布日期 2020-08-24 17:26  ·  溫州優(yōu)光網(wǎng)絡(luò)科技有限公司|建站|APP小程序制作|做網(wǎng)站SEO推廣優(yōu)化
【摘要】 這是一個(gè)基于Python的微信公眾號(hào)開(kāi)發(fā)之顏值檢測(cè),今天我們把用戶的圖片通過(guò)騰訊的AI平臺(tái)分析后再返回給用戶。來(lái)一起體驗(yàn)下公眾號(hào)的顏值檢測(cè)吧效果圖一. 接入騰訊AI平臺(tái)我們先看一下官方人臉檢測(cè)與分析接口的描述:檢測(cè)給定圖片(Image)中的所有人臉(Face)的位置和相應(yīng)的面部屬性。位置包括(x, y, w, h),面... 【溫州小程序開(kāi)發(fā),溫州微信公眾號(hào),平陽(yáng)做網(wǎng)站,平陽(yáng)網(wǎng)站建設(shè)公司,平陽(yáng)小程序商城制作,昆陽(yáng)萬(wàn)全做網(wǎng)站,鰲江水頭小程序,蕭江騰蛟微信公眾號(hào),山門(mén)順溪南雁海西南麂鳳臥麻步懷溪網(wǎng)絡(luò)網(wǎng)店服務(wù),政采云網(wǎng)店管理服務(wù)】...

來(lái)看看你的顏值多高吧!基于Python開(kāi)發(fā)的公眾號(hào)

這是一個(gè)基于Python的微信公眾號(hào)開(kāi)發(fā)之顏值檢測(cè),今天我們把用戶的圖片通過(guò)騰訊的AI平臺(tái)分析后再返回給用戶。
來(lái)一起體驗(yàn)下公眾號(hào)的顏值檢測(cè)吧效果圖一. 接入騰訊AI平臺(tái)我們先看一下官方人臉檢測(cè)與分析接口的描述:
檢測(cè)給定圖片(Image)中的所有人臉(Face)的位置和相應(yīng)的面部屬性。
位置包括(x, y, w, h),面部屬性包括性別(gender), 年齡(age), 表情(expression), 魅力(beauty), 眼鏡(glass)和姿態(tài)(pitch,roll,yaw)。
請(qǐng)求參數(shù)包括下面幾個(gè):
app_id 應(yīng)用標(biāo)識(shí),我們?cè)贏I平臺(tái)注冊(cè)后就可以得到app_idtime_stamp 時(shí)間戳nonce_str 隨機(jī)字符串sign 簽名信息,需要我們自己去計(jì)算image 需要檢測(cè)的圖片(上限1M)mode 檢測(cè)模式1.接口鑒權(quán),構(gòu)造請(qǐng)求參數(shù)官方給了我們接口鑒權(quán)的計(jì)算方法。
請(qǐng)求參數(shù)對(duì)按key進(jìn)行字典升序排序,得到有序的參數(shù)對(duì)列表N將列表N中的參數(shù)對(duì)按URL鍵值對(duì)的格式拼接成字符串,得到字符串T(如:
key1=value1&key2=value2),URL鍵值拼接過(guò)程value部分需要URL編碼,URL編碼算法用大寫(xiě)字母,例如%E8,而不是小寫(xiě)%e8將應(yīng)用密鑰以app_key為鍵名,組成URL鍵值拼接到字符串T末尾,得到字符串S(如:
key1=value1&key2=value2&app_key=密鑰)對(duì)字符串S進(jìn)行MD5運(yùn)算,將得到的MD5值所有字符轉(zhuǎn)換成大寫(xiě),得到接口請(qǐng)求簽名2.請(qǐng)求接口地址請(qǐng)求接口信息,我們用 requests 發(fā)送請(qǐng)求,會(huì)得到返回的 json 格式的圖像信息pip install requests安裝requests。
3.處理返回的信息處理返回的信息,把信息展示在圖片上,再把處理后的圖片保存。
這里我們用到 opencv ,和 pillow 兩個(gè)庫(kù)pip install pillow和pip install opencv-python來(lái)安裝。
開(kāi)始編寫(xiě)代碼,我們新建一個(gè)face_id.py 文件來(lái)對(duì)接AI平臺(tái),并且返回檢測(cè)后的圖像數(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 # 一.計(jì)算接口鑒權(quán),構(gòu)造請(qǐng)求參數(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): '
'
'
組織接口請(qǐng)求的參數(shù)形式,并且計(jì)算sign接口鑒權(quán)信息, 最終返回接口請(qǐng)求所需要的參數(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() # 計(jì)算出sign,接口鑒權(quán) params['
sign'
] = md5text # 添加到請(qǐng)求參數(shù)列表中 return params # 二.請(qǐng)求接口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() # 請(qǐng)求URL,得到j(luò)son信息 # 把信息顯示到圖片上 if res['
ret'
] == 0: # 0代表請(qǐng)求成功 pil_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) # 把opencv格式轉(zhuǎn)換為PIL格式,方便寫(xiě)漢字 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 = '
無(wú)'
if obj['
gender'
] >= 70: # 性別值從0-100表示從女性到男性 gender = '
男'
elif 50 gender'
] gender'
] 女'
else: gender = '
女漢子'
if 90 expression'
] 一笑傾城'
elif 80 expression'
] 心花怒放'
elif 70 expression'
] 興高采烈'
elif 60 expression'
] 眉開(kāi)眼笑'
elif 50 expression'
] 喜上眉梢'
elif 40 expression'
] 喜氣洋洋'
elif 30 expression'
] 笑逐顏開(kāi)'
elif 20 expression'
] 似笑非笑'
elif 10 expression'
] 半嗔半喜'
elif 0 expression'
] 黯然傷神'
delt = h // 5 # 確定文字垂直距離 # 寫(xiě)入圖片 if len(res['
data'
]['
face_list'
]) > 1: # 檢測(cè)到多個(gè)人臉,就把信息寫(xiě)入人臉框內(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 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") # 畫(huà)出人臉?lè)娇? 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 '
檢測(cè)成功'
else: return '
檢測(cè)失敗'
到這里我們的人臉檢測(cè)接口接入及圖片處理就完成了。
之后在收到用戶發(fā)送的圖片信息后,調(diào)用這個(gè)函數(shù),把處理后的圖片返回給用戶就可以。
返回圖片給用戶當(dāng)收到用戶圖片時(shí),需要以下幾個(gè)步驟:
保存圖片當(dāng)接收到用戶圖片后,我們要先把圖片保存起來(lái),之后才能去調(diào)用人臉?lè)治鼋涌?,把圖片信息傳遞過(guò)去,我們需要編寫(xiě)一個(gè) img_download 函數(shù)來(lái)下載圖片。
詳見(jiàn)下方代碼調(diào)用人臉?lè)治鼋涌趫D片下載后,調(diào)用 face_id.py 文件里的接口函數(shù),得到處理后的圖片。
上傳圖片檢測(cè)結(jié)果是一張新的圖片,要把圖片發(fā)送給用戶我們需要一個(gè) Media_ID,要獲取Media_ID必須先把圖片上傳為臨時(shí)素材,所以這里我們需要一個(gè)img_upload函數(shù)來(lái)上傳圖片,并且在上傳時(shí)需要用到一個(gè)access_token,我們通過(guò)一個(gè)函數(shù)來(lái)獲取. 獲取access_token必須要把我們自己的IP地址加入白名單,否則是獲取不到的。
請(qǐng)登錄“微信公眾平臺(tái)-開(kāi)發(fā)-基本配置”提前將服務(wù)器IP地址添加到IP白名單中,可以在http://ip.qq.com/查看本機(jī)的IP...開(kāi)始編寫(xiě)代碼,我們新建一個(gè) utils.py 來(lái)下載、上傳圖片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)返回給用戶我們簡(jiǎn)單修改下收到圖片后的邏輯,收到圖片后經(jīng)過(guò)人臉檢測(cè),上傳獲得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 == '
檢測(cè)成功'
: media_id = img_upload('
image'
, '
faces/'
+ name) # 上傳圖片,得到 media_id reply = ImageReply(media_id=media_id, message=msg) else: reply = TextReply(content='
人臉檢測(cè)失敗,請(qǐng)上傳1M以下人臉清晰的照片'
, message=msg) xml = reply.render() resp.body = (xml) resp.status = falcon.HTTP_200 app = falcon.API() connect = Connect() app.add_route('
/connect'
, connect)至此我們的工作就做完了,我們的公眾號(hào)可以進(jìn)行顏值檢測(cè)了。
本來(lái)我打算用在自己公眾號(hào)上的,但是還存在下面幾個(gè)問(wèn)題,所以沒(méi)有使用。
微信的機(jī)制,我們的程序必須在5s內(nèi)給出響應(yīng)。
不然就會(huì)報(bào)'
公眾號(hào)提供的服務(wù)出現(xiàn)故障'
。
然而處理圖片有時(shí)會(huì)比較慢,經(jīng)常會(huì)超過(guò)5s。
所以正確的處理方式應(yīng)該是拿到用戶的請(qǐng)求后立即返回一個(gè)空字符串表示我們收到了,之后單獨(dú)創(chuàng)建一個(gè)線程去處理圖片,當(dāng)圖片處理完后通過(guò)客服接口發(fā)送給用戶。
可惜的是未認(rèn)證的公眾號(hào)沒(méi)有客服接口,所以沒(méi)辦法,超過(guò)5s就會(huì)報(bào)錯(cuò)。
無(wú)法自定義菜單,一旦啟用了自定義開(kāi)發(fā),菜單也需要自定義配置,但是未認(rèn)證的公眾號(hào)沒(méi)有權(quán)限通過(guò)程序來(lái)配置菜單,只能在微信后臺(tái)配置。
所以,我并沒(méi)有在我的公眾號(hào)上啟用這個(gè)程序,但是如果有認(rèn)證的公眾號(hào),可以嘗試開(kāi)發(fā)各種好玩的功能。
相關(guān)推薦:
微信公眾平臺(tái)開(kāi)發(fā)一鍵關(guān)注微信公眾平臺(tái)賬號(hào)微信公眾平臺(tái)開(kāi)發(fā)嘗試,微信公眾平臺(tái)視頻:
傳智、黑馬微信公眾平臺(tái)開(kāi)發(fā)視頻教程以上就是來(lái)看看你的顏值多高吧!基于Python開(kāi)發(fā)的公眾號(hào)的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!
微信
分享相關(guān)標(biāo)簽:
人工智能 微信公眾平臺(tái) 微信 公眾號(hào) python本文原創(chuàng)發(fā)布php中文網(wǎng),轉(zhuǎn)載請(qǐng)注明出處,感謝您的尊重!
上一篇:
關(guān)于微信小程序上傳word、txt、Excel、PPT等文件的詳解
下一篇:
終于整理出來(lái)了,用微信第三方平臺(tái)授權(quán)小程序業(yè)務(wù)相關(guān)文章相關(guān)視頻修改微信號(hào)有什么影響嗎?微信中共享實(shí)時(shí)位置什么意思數(shù)據(jù)庫(kù)設(shè)計(jì)的基本原則是什么?微信小程序調(diào)用圖片安全API來(lái)看看你的顏值多高吧!基于Python開(kāi)發(fā)的公眾號(hào)微信公眾平臺(tái)概述微信公眾平臺(tái)開(kāi)發(fā)概述微信公眾平臺(tái) 接口域名說(shuō)明微信公眾平臺(tái) 獲取access_token注冊(cè)屬于自己的微信公眾平臺(tái)
[溫州做微信公眾號(hào)]