모습 감지를 위한 Python 기반 WeChat 공개 계정 개발입니다. 오늘은 Tencent의 AI 플랫폼을 통해 사용자의 사진을 분석한 후 사용자에게 반환합니다. 공개 계정의 액면가 감지를 함께 경험해 보세요
먼저 공식 얼굴 감지 및 분석 인터페이스에 대한 설명을 살펴보겠습니다.
주어진 이미지에 있는 모든 얼굴의 위치와 해당 얼굴 특성을 감지합니다. 위치에는 (x, y, w, h)가 포함되며 얼굴 속성에는 성별, 나이, 표정, 아름다움, 안경 및 자세(피치, 롤, 요)가 포함됩니다.
요청 매개변수에는 다음이 포함됩니다.
app_id 애플리케이션 식별, AI 플랫폼
time_stamp 타임스탬프
nonce_str 무작위 문자열
서명 정보에 등록한 후 app_id를 얻을 수 있습니다. , 우리가 직접 계산해야 합니다
감지할 이미지 이미지(상한 1M)
모드 감지 모드
공식에서 계산 방법을 알려줬습니다. 인터페이스 인증.
목록 N의 매개변수 쌍을 URL 형식에 따라 문자로 연결합니다. 키-값 쌍 문자열을 사용하여 문자열 T(예: key1=value1&key2=value2)를 얻습니다. URL 키-값 접합 프로세스의 값 부분에는 URL 인코딩 알고리즘이 대신 %E8과 같은 대문자를 사용합니다. 소문자 %e8
애플리케이션 비밀번호는 다음과 같습니다. 키는 app_key를 키 이름으로 사용하고 URL 키 값은 문자열 T의 끝에 연결되어 문자열 S를 얻습니다(예: key1=value1&key2 =value2&app_key=key)
문자열 S에 대해 MD5 연산을 수행하고 MD5를 얻습니다. 값의 모든 문자를 대문자로 변환하고 인터페이스 요청 서명을 얻습니다.
를 요청하세요. 우리는 요청을 전송하기 위해 요청을 사용하며, pip install requests
Install Requests) 형식으로 반환된 이미지 정보를 받게 됩니다. pip install requests
安装requests。
处理返回的信息,把信息展示在图片上,再把处理后的图片保存。这里我们用到 opencv ,和 pillow 两个库pip install pillow
和pip install opencv-python
pip install Pillow
및 pip install opencv-python
를 사용합니다. 코드 작성을 시작합니다. AI 플랫폼에 연결하고 감지된 이미지 데이터를 반환하기 위해 새로운 Face_id.py 파일을 생성합니다. 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['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: # 检测到多个人脸,就把信息写入人脸框内 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: # 避免图片太窄,导致文字显示不完全 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 格式转换为 cv cv2.imwrite('faces/{}'.format(os.path.basename(img)), cv2img) # 保存图片到 face 文件夹下 return '检测成功' else: return '检测失败'
사진 업로드
감지 결과는 새로운 사진입니다. 사진을 사용자에게 보내려면 Media_ID를 얻으려면 먼저 사진을 임시 자료로 업로드해야 하므로 여기서는 img_upload 함수가 필요합니다. 사진을 업로드하려면 access_token이 필요하며, 우리는 함수를 통해 그것을 얻습니다.access_token을 얻으려면 우리 자신의 IP 주소를 화이트리스트에 추가해야 합니다. 그렇지 않으면 우리는 그것을 얻을 수 없습니다. "WeChat 공개 플랫폼 - 개발 - 기본 구성"에 로그인하여 서버 IP 주소를 IP 화이트리스트에 미리 추가하세요. http://ip.qq.com/...
에서 이 컴퓨터의 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)
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)
WeChat의 메커니즘을 사용하면 우리 프로그램은 5초 이내에 응답해야 합니다. 그렇지 않으면 '공식 계정에서 제공하는 서비스에 결함이 있습니다'라고 보고됩니다. 그러나 이미지 처리가 때로는 느려서 5초를 초과하는 경우도 있습니다. 따라서 이를 처리하는 올바른 방법은 사용자의 요청을 받은 후 즉시 빈 문자열을 반환하여 이를 수신했음을 표시한 다음 이미지를 처리할 별도의 스레드를 생성하여 이미지를 처리하는 것입니다. 고객 서비스 인터페이스를 통해 사용자. 아쉽게도 인증되지 않은 공개 계정은 고객 서비스 인터페이스가 없기 때문에 5초 이상 소요될 경우 오류가 발생합니다.
메뉴를 사용자 정의할 수 없습니다. 사용자 정의 개발이 활성화되면 메뉴도 사용자 정의해야 합니다. 그러나 인증되지 않은 공식 계정은 프로그램을 통해 메뉴를 구성할 수 있는 권한이 없으며 WeChat 백그라운드에서만 구성할 수 있습니다.
그래서 공식 계정에서는 이 프로그램을 활성화하지 않았지만, 인증된 공식 계정이 있다면 다양하고 재미있는 기능을 개발해 볼 수 있습니다.
관련 추천:
WeChat 공개 플랫폼 개발 원클릭 WeChat 공개 플랫폼 계정 팔로우
WeChat 공개 플랫폼 개발 시도, WeChat 공개 플랫폼
동영상: Chuanzhi, Dark Horse WeChat 공개 플랫폼 개발 동영상 튜토리얼
위 내용은 얼마나 잘 생겼는지 볼까요! Python 기반으로 개발된 공개 계정의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!