來看看你的顏值多高吧!基於Python開發的公眾號

php是最好的语言
發布: 2018-07-25 13:56:17
原創
2421 人瀏覽過

這是一個基於Python的微信公眾號開發之顏值檢測,今天我們把用戶的圖片通過騰訊的AI平台分析後再返回給用戶。來一起體驗下公眾號的顏值檢測吧

效果圖

來看看你的顏值多高吧!基於Python開發的公眾號

來看看你的顏值多高吧!基於Python開發的公眾號

來看看你的顏值多高吧!基於Python開發的公眾號

  • #一. 接入騰訊AI平台

  • 我們先看一下官方人臉偵測與分析介面的描述:
  • 偵測給定圖片(Image)中的所有人臉(Face)的位置和對應的臉部屬性。位置包括(x, y, w, h),臉部屬性包括性別(gender), 年齡(age), 表情(expression), 魅力(beauty), 眼鏡(glass)和姿態(pitch,roll,yaw)。

  • 請求參數包含下面幾個:
  • app_id 應用標識,我們在AI平台註冊後就可以得到app_id
  • time_stamp 時間戳記
  • nonce_str 隨機字串
  • sign 簽章訊息,需要我們自己去計算

#image 需要偵測的圖片(上限1M)

  1. mode 偵測模式

  2. 1.介面鑑權,建構請求參數

  3. 官方給了我們介面鑑權的計算方法。
  4. 請求參數對按key進行字典升序排序,得到有序的參數對列表N
  5. 將列表N中的參數對按URL鍵值對的格式拼接成字串,得到字串T(如:key1=value1&key2=value2),URL鍵值拼接過程value部分需要URL編碼,URL編碼演算法用大寫字母,例如�,而不是小寫�

將應用金鑰以app_key為鍵名,組成URL鍵值拼接到字串T結尾,得到字串S(如:key1=value1&key2 =value2&app_key=金鑰)

對字串S進行MD5運算,將得到的MD5值所有字元轉換成大寫,得到介面請求簽章

2.請求介面位址請求介面訊息,我們用requests 發送請求,會得到傳回的json 格式的映像資訊

pip install requests

安裝requests。

3.處理回傳的訊息

處理回傳的訊息,把訊息展示在圖片上,再把處理後的圖片儲存。這裡我們用到 opencv ,和 pillow 兩個函式庫

pip install pillow

pip install opencv-python

來安裝。

開始寫程式碼,我們新建一個face_id.py 檔案來對接AI平台,並且傳回偵測後的影像資料。

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


# 一.计算接口鉴权,构造请求参数

def random_str():
    '''得到随机字符串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):
    '''组织接口请求的参数形式,并且计算sign接口鉴权信息,
    最终返回接口请求所需要的参数字典'''
    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,接口鉴权
    params['sign'] = md5text  # 添加到请求参数列表中
    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)  # 图片转为base64编码格式
    url = 'https://api.ai.qq.com/fcgi-bin/face/face_detectface'
    res = requests.post(url, get_params(img_encode)).json()  # 请求URL,得到json信息
    # 把信息显示到图片上
    if res['ret'] == 0:  # 0代表请求成功
        pil_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))  # 把opencv格式转换为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坐标
            y = obj['y']  # 人脸框左上角y坐标
            w = obj['width']  # 人脸框宽度
            h = obj['height']  # 人脸框高度
            # 根据返回的值,自定义一下显示的文字内容
            if obj['glass'] == 1:  # 眼镜
                glass = '有'
            else:
                glass = '无'
            if obj['gender'] >= 70:  # 性别值从0-100表示从女性到男性
                gender = '男'
            elif 50 <= obj[&#39;gender&#39;] < 70:
                gender = "娘"
            elif obj[&#39;gender&#39;] < 30:
                gender = &#39;女&#39;
            else:
                gender = &#39;女汉子&#39;
            if 90 < obj[&#39;expression&#39;] <= 100:  # 表情从0-100,表示笑的程度
                expression = &#39;一笑倾城&#39;
            elif 80 < obj[&#39;expression&#39;] <= 90:
                expression = &#39;心花怒放&#39;
            elif 70 < obj[&#39;expression&#39;] <= 80:
                expression = &#39;兴高采烈&#39;
            elif 60 < obj[&#39;expression&#39;] <= 70:
                expression = &#39;眉开眼笑&#39;
            elif 50 < obj[&#39;expression&#39;] <= 60:
                expression = &#39;喜上眉梢&#39;
            elif 40 < obj[&#39;expression&#39;] <= 50:
                expression = &#39;喜气洋洋&#39;
            elif 30 < obj[&#39;expression&#39;] <= 40:
                expression = &#39;笑逐颜开&#39;
            elif 20 < obj[&#39;expression&#39;] <= 30:
                expression = &#39;似笑非笑&#39;
            elif 10 < obj[&#39;expression&#39;] <= 20:
                expression = &#39;半嗔半喜&#39;
            elif 0 <= obj[&#39;expression&#39;] <= 10:
                expression = &#39;黯然伤神&#39;
            delt = h // 5  # 确定文字垂直距离
            # 写入图片
            if len(res[&#39;data&#39;][&#39;face_list&#39;]) > 1:  # 检测到多个人脸,就把信息写入人脸框内
                font = ImageFont.truetype(&#39;yahei.ttf&#39;, w // 8, encoding=&#39;utf-8&#39;)  # 提前把字体文件下载好
                draw.text((x + 10, y + 10), &#39;性别 :&#39; + gender, (76, 176, 80), font=font)
                draw.text((x + 10, y + 10 + delt * 1), &#39;年龄 :&#39; + str(obj[&#39;age&#39;]), (76, 176, 80), font=font)
                draw.text((x + 10, y + 10 + delt * 2), &#39;表情 :&#39; + expression, (76, 176, 80), font=font)
                draw.text((x + 10, y + 10 + delt * 3), &#39;魅力 :&#39; + str(obj[&#39;beauty&#39;]), (76, 176, 80), font=font)
                draw.text((x + 10, y + 10 + delt * 4), &#39;眼镜 :&#39; + glass, (76, 176, 80), font=font)
            elif img_width - x - w < 170:  # 避免图片太窄,导致文字显示不完全
                font = ImageFont.truetype(&#39;yahei.ttf&#39;, w // 8, encoding=&#39;utf-8&#39;)
                draw.text((x + 10, y + 10), &#39;性别 :&#39; + gender, (76, 176, 80), font=font)
                draw.text((x + 10, y + 10 + delt * 1), &#39;年龄 :&#39; + str(obj[&#39;age&#39;]), (76, 176, 80), font=font)
                draw.text((x + 10, y + 10 + delt * 2), &#39;表情 :&#39; + expression, (76, 176, 80), font=font)
                draw.text((x + 10, y + 10 + delt * 3), &#39;魅力 :&#39; + str(obj[&#39;beauty&#39;]), (76, 176, 80), font=font)
                draw.text((x + 10, y + 10 + delt * 4), &#39;眼镜 :&#39; + glass, (76, 176, 80), font=font)
            else:
                font = ImageFont.truetype(&#39;yahei.ttf&#39;, 20, encoding=&#39;utf-8&#39;)
                draw.text((x + w + 10, y + 10), &#39;性别 :&#39; + gender, (76, 176, 80), font=font)
                draw.text((x + w + 10, y + 10 + delt * 1), &#39;年龄 :&#39; + str(obj[&#39;age&#39;]), (76, 176, 80), font=font)
                draw.text((x + w + 10, y + 10 + delt * 2), &#39;表情 :&#39; + expression, (76, 176, 80), font=font)
                draw.text((x + w + 10, y + 10 + delt * 3), &#39;魅力 :&#39; + str(obj[&#39;beauty&#39;]), (76, 176, 80), font=font)
                draw.text((x + w + 10, y + 10 + delt * 4), &#39;眼镜 :&#39; + 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 格式转换为 cv
            cv2.imwrite(&#39;faces/{}&#39;.format(os.path.basename(img)), cv2img)  # 保存图片到 face 文件夹下
            return &#39;检测成功&#39;
    else:
        return &#39;检测失败&#39;
登入後複製

到這裡我們的人臉偵測介面存取及圖片處理就完成了。之後在收到用戶傳送的圖片訊息後,呼叫這個函數,把處理後的圖片回傳給用戶就可以。

返回圖片給使用者

當收到使用者圖片時,需要以下步驟:

#儲存圖片#當接收到使用者圖片後,我們要先把圖片保存起來,之後才能去調用人臉分析接口,把圖片資訊傳遞過去,我們需要編寫一個img_download 函數來下載圖片。詳見下方程式碼

呼叫人臉分析介面

圖片下載後,呼叫 face_id.py 檔案裡的介面函數,得到處理後的圖片。

上傳圖片

偵測結果是新的圖片,要把圖片傳送給使用者我們需要一個Media_ID,要取得Media_ID必須先把圖片上傳為暫存素材,所以這裡我們需要一個img_upload函數來上傳圖片,並且在上傳時需要用到一個access_token,我們通過一個函數來獲取.

獲取access_token必須要把我們自己的IP地址加入白名單,否則是獲取不到的。請登入「微信公眾平台-開發-基本配置」提前將伺服器IP位址加入IP白名單中,可以在http://ip.qq.com/查看本機的IP...####### ###開始寫程式碼,我們新建一個utils.py 來下載、上傳圖片###r​​rreee###回傳給使用者######我們簡單修改收到圖片後的邏輯,收到圖片後經過臉部偵測,上傳獲得Media_ID,我們要做的就是把圖片回傳給使用者即可。直接看connect.py的程式碼###
import requests
import json
import threading
import time
import os

token = &#39;&#39;
app_id = &#39;wxfc6adcdd7593a712&#39;
secret = &#39;429d85da0244792be19e0deb29615128&#39;


def img_download(url, name):
    r = requests.get(url)
    with open(&#39;images/{}-{}.jpg&#39;.format(name, time.strftime("%Y_%m_%d%H_%M_%S", time.localtime())), &#39;wb&#39;) as fd:
        fd.write(r.content)
    if os.path.getsize(fd.name) >= 1048576:
        return &#39;large&#39;
    # print(&#39;namename&#39;, os.path.basename(fd.name))
    return os.path.basename(fd.name)


def get_access_token(appid, secret):
    &#39;&#39;&#39;获取access_token,100分钟刷新一次&#39;&#39;&#39;

    url = &#39;https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}&#39;.format(appid, secret)
    r = requests.get(url)
    parse_json = json.loads(r.text)
    global token
    token = parse_json[&#39;access_token&#39;]
    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 = {&#39;media&#39;: open(&#39;{}&#39;.format(name), &#39;rb&#39;)}
    r = requests.post(url, files=files)
    parse_json = json.loads(r.text)
    return parse_json[&#39;media_id&#39;]

get_access_token(app_id, secret)
登入後複製
###至此我們的工作就做完了,我們的公眾號可以進行顏值偵測了。本來打算用在自己公眾號上的,但是還存在下面幾個問題,所以沒有使用。 ###
  1. 微信的機制,我們的程式必須在5s內給予回應。不然就會報'公眾號提供的服務故障'。然而處理圖片有時會比較慢,常常會超過5s。所以正確的處理方式應該是拿到用戶的請求後立即返回一個空字符串表示我們收到了,之後單獨創建一個線程去處理圖片,當圖片處理完後通過客服接口發送給用戶。可惜的是未認證的公眾號沒有客服接口,所以沒辦法,超過5s就會報錯。

  2. 無法自訂選單,一旦啟用了自訂開發,選單也需要自訂配置,但是未認證的公眾號沒有權限通過程式來配置選單,只能在微信後台配置。

所以,我並沒有在我的公眾號上啟用這個程序,但是如果有認證的公眾號,可以嘗試開發各種好玩的功能。

相關推薦:

微信公眾平台開發一鍵關注微信公眾平台帳號

微信公眾平台開發嘗試,微信公眾平台

影片:傳智、黑馬微信大眾平台開發影片教學

以上是來看看你的顏值多高吧!基於Python開發的公眾號的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板