Heim  >  Artikel  >  WeChat-Applet  >  Mal sehen, wie gut du aussiehst! Auf Python basierendes öffentliches Konto

Mal sehen, wie gut du aussiehst! Auf Python basierendes öffentliches Konto

php是最好的语言
php是最好的语言Original
2018-07-25 13:56:172380Durchsuche

Dies ist eine Python-basierte Entwicklung eines öffentlichen WeChat-Kontos zur Erkennung des Erscheinungsbilds. Heute analysieren wir die Bilder des Benutzers über die KI-Plattform von Tencent und geben sie dann an den Benutzer zurück. Lassen Sie uns gemeinsam den Schönheitstest öffentlicher Konten erleben

Rendering

Mal sehen, wie gut du aussiehst! Auf Python basierendes öffentliches Konto

Mal sehen, wie gut du aussiehst! Auf Python basierendes öffentliches Konto

Mal sehen, wie gut du aussiehst! Auf Python basierendes öffentliches Konto

1 . Greifen Sie auf die KI-Plattform von Tencent zu

Schauen wir uns zunächst die Beschreibung der offiziellen Gesichtserkennungs- und Analyseschnittstelle an:

Erkennen Sie alle Gesichter (Gesicht) an einem bestimmten Bildort (Bild) und entsprechend Gesichtsattribute. Die Position umfasst (x, y, w, h) und die Gesichtsattribute umfassen Geschlecht, Alter, Ausdruck, Schönheit, Brille und Körperhaltung (Nicken, Rollen, Gieren).

Die Anforderungsparameter umfassen Folgendes:

  • app_id Anwendungsidentifikation, wir können die app_id nach der Registrierung auf der KI-Plattform erhalten

  • Zeitstempel Zeitstempel

  • nonce_str Zufallszeichenfolge

  • Signaturinformationen, wir müssen sie selbst berechnen

  • Bild Zu erkennendes Bild (Obergrenze 1M)

  • Modus Erkennungsmodus

1. Schnittstellenauthentifizierung, Anforderungsparameter erstellen

Der Beamte gab uns die Berechnungsmethode für die Schnittstellenauthentifizierung.

  1. Sortieren Sie die -Anforderungsparameterpaare in aufsteigender Wörterbuchreihenfolge nach Schlüssel, um eine geordnete Liste von Parameterpaaren N zu erhalten

  2. Die Parameterpaare in Liste N werden in Zeichenfolgen im Format von URL-Schlüssel-Wert-Paaren gespleißt, um die Zeichenfolge T zu erhalten (zum Beispiel: Schlüssel1=Wert1&Schlüssel2=Wert2). Der Wertteil des URL-Schlüssel-Wert-Spleißprozesses erfordert eine URL-Codierung . Der URL-Kodierungsalgorithmus verwendet Großbuchstaben anstelle von Kleinbuchstaben %e8

  3. , verwenden Sie app_key als Schlüsselnamen, um den URL-Schlüsselwert zu bilden und ihn mit dem zu verbinden Ende der Zeichenfolge T, um die Zeichenfolge S zu erhalten (z. B.: key1 =value1&key2=value2&app_key=Key)

  4. Führen Sie eine MD5-Operation für die Zeichenfolge S aus und konvertieren Sie alle Zeichen des erhaltenen MD5-Werts in Großbuchstaben umwandeln und die Schnittstellenanforderungssignatur abrufen

2. Fordern Sie die Schnittstellenadresse an

Anfragen verwenden, um die Anfrage zu senden die zurückgegebenen Bildinformationen im JSON-Format pip install requestsInstallationsanfragen.

3. Verarbeiten Sie die zurückgegebenen Informationen

Verarbeiten Sie die zurückgegebenen Informationen, zeigen Sie die Informationen auf dem Bild an und speichern Sie dann das verarbeitete Bild. Hier verwenden wir zur Installation die OpenCV- und Pillow-Bibliotheken pip install pillow und pip install opencv-python.

Beginnen Sie mit dem Schreiben von Code. Wir erstellen eine neue face_id.py-Datei, um eine Verbindung zur KI-Plattform herzustellen und die erkannten Bilddaten zurückzugeben.

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;

An diesem Punkt sind unser Zugriff auf die Gesichtserkennungsschnittstelle und die Bildverarbeitung abgeschlossen. Rufen Sie nach Erhalt der vom Benutzer gesendeten Bildinformationen diese Funktion auf und geben Sie das verarbeitete Bild an den Benutzer zurück.

Bild an den Benutzer zurückgeben

Beim Empfang des Benutzerbildes sind folgende Schritte erforderlich:

Bild speichern

Nach Erhalt des Benutzerbildes , Wir müssen das Bild zuerst speichern, dann können wir die Gesichtsanalyseschnittstelle aufrufen und die Bildinformationen übergeben. Wir müssen eine img_download-Funktion schreiben, um das Bild herunterzuladen. Einzelheiten finden Sie im folgenden Code.

Aufrufen der Gesichtsanalyseschnittstelle

Rufen Sie nach dem Herunterladen des Bildes die Schnittstellenfunktion in der Datei face_id.py auf, um das verarbeitete Bild zu erhalten.

Ein Bild hochladen

Um das Bild an den Benutzer zu senden, benötigen wir eine Media_ID. Um die Media_ID zu erhalten, müssen wir das Bild zunächst als temporäres Material hochladen , also brauchen wir hier eine img_upload-Funktion zum Hochladen von Bildern, und beim Hochladen ist ein access_token erforderlich. Wir erhalten es über eine Funktion. Um das access_token zu erhalten, müssen wir unsere eigene IP-Adresse zur Whitelist hinzufügen wird nicht erhalten. Bitte melden Sie sich bei „WeChat Public Platform-Development-Basic Configuration“ an, um die Server-IP-Adresse vorab zur IP-Whitelist hinzuzufügen. Sie können die IP dieses Geräts unter http://ip.qq.com/...

Beginnen Sie mit dem Schreiben des Codes, wir erstellen eine neue utils.py zum Herunterladen und Hochladen von Bildern

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)

Zurück zum Benutzer

Wir ändern einfach die Logik, nachdem wir das Bild erhalten haben Nach Erhalt des Bildes, Gesichtserkennung und Hochladen, um Media_ID zu erhalten, müssen wir das Bild nur noch an den Benutzer zurücksenden. Schauen Sie sich direkt den Code von connect.py an

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(&#39;&&#39;)
        b = {}
        for i in query_list:
            b[i.split(&#39;=&#39;)[0]] = i.split(&#39;=&#39;)[1]

        try:
            check_signature(token=&#39;lengxiao&#39;, signature=b[&#39;signature&#39;], timestamp=b[&#39;timestamp&#39;], nonce=b[&#39;nonce&#39;])
            resp.body = (b[&#39;echostr&#39;])
        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 == &#39;text&#39;:
            reply = TextReply(content=msg.content, message=msg)
            xml = reply.render()
            resp.body = (xml)
            resp.status = falcon.HTTP_200
        elif msg.type == &#39;image&#39;:
            name = img_download(msg.image, msg.source)  # 下载图片
            r = access_api(&#39;images/&#39; + name)
            if r == &#39;检测成功&#39;:
                media_id = img_upload(&#39;image&#39;, &#39;faces/&#39; + name)  # 上传图片,得到 media_id
                reply = ImageReply(media_id=media_id, message=msg)
            else:
                reply = TextReply(content=&#39;人脸检测失败,请上传1M以下人脸清晰的照片&#39;, message=msg)
            xml = reply.render()
            resp.body = (xml)
            resp.status = falcon.HTTP_200

app = falcon.API()
connect = Connect()
app.add_route(&#39;/connect&#39;, connect)

An diesem Punkt ist unsere Arbeit abgeschlossen und unser offizielles Konto kann auf Aussehen getestet werden. Ich hatte ursprünglich geplant, es auf meinem offiziellen Konto zu verwenden, aber es gab immer noch einige Probleme, also habe ich es nicht verwendet.

  1. Mit dem WeChat-Mechanismus muss unser Programm innerhalb von 5 Sekunden reagieren. Andernfalls wird die Meldung „Der vom offiziellen Konto bereitgestellte Dienst ist fehlerhaft“ angezeigt. Allerdings ist die Bildverarbeitung manchmal langsam und dauert oft länger als 5 Sekunden. Daher sollte die richtige Vorgehensweise darin bestehen, nach Erhalt der Benutzeranforderung sofort eine leere Zeichenfolge zurückzugeben, um anzugeben, dass wir sie erhalten haben, und dann einen separaten Thread zum Verarbeiten des Bildes zu erstellen der Benutzer über die Kundendienstschnittstelle. Leider verfügen nicht zertifizierte öffentliche Konten nicht über eine Kundendienstschnittstelle, daher können Sie nichts dagegen tun. Wenn der Vorgang länger als 5 Sekunden dauert, wird ein Fehler gemeldet.

  2. Das Menü kann nicht angepasst werden. Sobald die benutzerdefinierte Entwicklung aktiviert ist, muss auch das Menü angepasst werden. Nicht zertifizierte offizielle Konten haben jedoch keine Berechtigung, das Menü über das Programm zu konfigurieren Konfigurieren Sie es nur in der WeChat-Backend-Konfiguration.

Ich habe dieses Programm also nicht auf meinem offiziellen Konto aktiviert, aber wenn Sie ein zertifiziertes offizielles Konto haben, können Sie versuchen, verschiedene unterhaltsame Funktionen zu entwickeln.

Verwandte Empfehlungen:

Entwicklung der öffentlichen WeChat-Plattform Mit einem Klick dem Konto der öffentlichen WeChat-Plattform folgen

Versuch der Entwicklung einer öffentlichen WeChat-Plattform , Öffentliche WeChat-Plattform

Video: Video-Tutorial zur Entwicklung der öffentlichen WeChat-Plattform von Chuanzhi und Dark Horse

Das obige ist der detaillierte Inhalt vonMal sehen, wie gut du aussiehst! Auf Python basierendes öffentliches Konto. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn