目标:
1.学习使用百度AI开放平台进行语音识别与语音合成
百度AI有两种开发方式:REST, SDK; 本文使用的是SDK python进行开发
文档地址:https://ai.baidu.com/docs#/Face-Detect-V3/top
2.将学到的内容:异常捕获,tkinter显示图像
异常捕获十分方便程序开发时,当未每一个函数添加抛出异常时,可以方便判定错误出现的函数
3.生成exe格式可执行文件
pyinstaller -F xxx.py 参考文档 https://blog.csdn.net/qq_35203425/article/details/78568141
解决pyinstaller打包发布后的exe文件打开控制台闪退的问题
1)先打开一个cmd
2)cd到你的exe文件目录
3)输入 .\***.exe
4.python-Tkinter图形界面开发
1.按钮Button 2.文本框 Text
5.cv2读取/写入 图像的中文路径问题
问题点:
1.文本框显示图像位置,无法进行调整
2.未使用多线程进行开发
3.开发界面后,文件保存路径要使用os创建路径,不能使用相对路径,也不能使用+路径+文件名(路径不存在时)(注意pycharm开发时可以使用)
界面:
代码:
from tkinter import *
from tkinter.filedialog import askopenfilename,askdirectory #加载文件路径
import base64
import time,os
import numpy as np
from PIL import Image, ImageTk
import cv2
import math
import threading
import matplotlib.pyplot as plt
from aip import AipFace #导入百度人脸识别SDK接口
class Face_Recognition():
"""
开发人脸识别,SDK开发
"""
def __init__(self):
""" 你的 APPID AK SK """
self.APP_ID = '17790554'
self.API_KEY = 'OHa7m2I8i9sEzjAO7GTxr2p8'
self.SECRET_KEY = 'cPkNxo5O0tOND97LjuDTAjRdHm0FCFRx'
self.client = AipFace(self.APP_ID, self.API_KEY, self.SECRET_KEY)
self.myWindow = Tk()
self.expression={"none":"不笑","smile":"微笑","laugh":"大笑"}
self.faceshape={"square": "正方形", "triangle":"三角形", "oval": "椭圆", "heart": "心形", "round": "圆形"}
self.gender={ "male":"男性", "female":"女性"}
self.race={ 'yellow': '黄种人', 'white': '白种人', 'black':'黑种人', 'arabs': '阿拉伯人'}
self.tag_l=0
self.tag_r=0
# self.threadlock=threading.Lock()
def get_img(self):
"加载图像"
image=""
path_name=""
try:
# 路径搜索
self.path_name = askopenfilename(title="查找文件的路径", filetypes=[("图片格式", "*.jpg;*.jpeg;*.png;*.bmp")])
with open(self.path_name, mode="rb") as f:
img = f.read()
self.image = str(base64.b64encode(img), encoding="utf-8")
except:
print("文件打开错误-1")
else:
print("图像打开成功")
finally:
print("加载图片程序结束")
def result_analysis(self,result):
"分析结果"
my_string=[]
position=[]
if result['error_code']==0:
for i in range(result['result']['face_num']):
img_infor=result['result']['face_list'][i]
string="估算年龄:{}\n样貌评分:{}\n表情:{},置信度:{}\n脸型:{},置信度:{}\n性别:{},置信度:{}\n人种:{},置信度:{}\n".format(
img_infor['age'],img_infor['beauty'],self.expression[img_infor['expression']['type']],img_infor['expression']['probability'],
self.faceshape[img_infor['face_shape']['type']],img_infor['face_shape']['probability'],
self.gender[img_infor['gender']['type']],img_infor['gender']['probability'],
self.race[img_infor['race']['type']],img_infor['race']['probability'])
my_string.append(string)
position.append([img_infor['location']])
return my_string,position
def img_show(self,path_name,imgname,analy_result,*position):
#img=cv2.imread(path_name,0) #无法读取中文路径的图像
img = cv2.imdecode(np.fromfile(path_name, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
# print(img)
#print(position[0][0])
if analy_result=='TRUE':
position=position[0]
x0, y0, w, h, r = position[0][0]['left'], position[0][0]['top'], position[0][0]['width'], position[0][0][
'height'], position[0][0]['rotation'] * math.pi / 180
x0, y0 = int(x0), int(y0)
x1, y1 = int(x0 - h * math.sin(r)), int(y0 + h * math.cos(r))
x2, y2 = int(x1 + w * math.cos(r)), int(y1 + w * math.sin(r))
x3, y3 = int(x0 + w * math.cos(r)), int(y0 + w * math.sin(r))
rect = [[x0, y0, x1, y1], [x1, y1, x2, y2], [x2, y2, x3, y3], [x0, y0, x3, y3]]
#print(rect)
for x_1, y_1, x_2, y_2 in rect:
cv2.line(img, (x_1, y_1), (x_2, y_2), (0, 255, 0), 3)
h,w=img.shape[:2]
#print(h,w)
if w<h:
img=cv2.resize(img,(int(w*310/h),320))
else:
img = cv2.resize(img, ( 350,int(h * 350 / w)))
path=os.path.join(os.getcwd(),'{}.png'.format(imgname))
#cv2.imwrite(path, img)
# cv2.imencode(".png", img)返回的是(True/False,图像数组)
cv2.imencode(".png",img)[1].tofile(path)
def face_detect(self,img):
# 调用接口实现人脸识别
imageType = "BASE64"
options = {}
options["face_field"] = "age,beauty,expression,face_shape,gender,race"
options["max_face_num"] = 1
options["face_type"] = "LIVE"
options["liveness_control"] = "LOW"
""" 带参数调用人脸检测 """
# self.threadlock.acquire()
self.result = self.client.detect(img, imageType, options)
# self.threadlock.release()
def face_reg(self):
"人脸识别"
self.get_img()
try:
# 线程调用导致线程中的变量不能直接访问
# thread_1 = threading.Thread(target=self.face_detect, args=[self.image])
# thread_1.start()
self.face_detect(self.image)
except:
print("人脸识别错误")
else:
print("人脸识别调用成功")
#print(self.result)
if self.result['error_code']!=0:
raise Exception(self.result['error_msg'])
def face_inf_display1(self):
"显示左侧人脸识别结果"
self.tag_l = 0
path = os.getcwd() + '/img_1.png'
if os.path.exists(path):
os.remove(path)
self.text_lh.delete(1.0,END)
self.text_ld.delete(1.0, END)
#print("显示左侧人脸识别结果")
try:
self.face_reg()
result_analysis, position = self.result_analysis(self.result)
# 显示识别信息
self.img_show(self.path_name, "img_1", "TRUE", position)
img = Image.open(path)
img = ImageTk.PhotoImage(img)
# 显示图像时必须同时指定两个属性
self.text_lh.image = img
self.text_lh.image_create(END, image=img)
self.tag_l = 1
except Exception as errors:
print("错误",errors)
self.img_show(self.path_name, "img_1", "FALSE")
img = Image.open(path)
img = ImageTk.PhotoImage(img)
# 显示图像时必须同时指定两个属性
self.text_lh.image = img
self.text_lh.image_create(END, image=img)
self.tag_l = 0
self.text_ld.insert('insert', "未检测到人脸!")
else:
print("左侧图像识别成功")
self.text_ld.insert('insert', result_analysis[0])
def face_inf_display2(self):
"显示右侧人脸识别结果"
#print("显示右侧人脸识别结果")
path = os.getcwd() + '/img_2.png'
if os.path.exists(path):
os.remove(path)
self.text_rh.delete(1.0, END)
self.text_rd.delete(1.0, END)
self.tag_r = 0
try:
self.face_reg()
result_analysis, position = self.result_analysis(self.result)
# 显示识别信息
self.img_show(self.path_name, "img_2","TRUE", position)
img = Image.open(path)
img = ImageTk.PhotoImage(img)
# 显示图像时必须同时指定两个属性
self.text_rh.image = img
self.text_rh.image_create(END, image=img)
self.tag_r = 1
except Exception as errors:
print("错误",errors)
self.img_show(self.path_name, "img_2","FALSE")
img = Image.open(path)
img = ImageTk.PhotoImage(img)
# 显示图像时必须同时指定两个属性
self.text_rh.image = img
self.text_rh.image_create(END, image=img)
self.tag_r = 0
self.text_rd.insert('insert', "未检测到人脸!")
else:
print("右侧图像识别成功")
self.text_rd.insert('insert', result_analysis[0])
def result_comparison(self):
"进行图像相似度对比"
#print("进行图像相似度对比")
self.text_m.delete(1.0, END)
path1=os.getcwd() + '/img_1.png'
path2 = os.getcwd() + '/img_2.png'
if self.tag_r==1 and self.tag_l==1:
result = self.client.match([
{
'image': str(base64.b64encode(open(path1, 'rb').read()),encoding='utf-8'),
'image_type': 'BASE64',
},
{
'image': str(base64.b64encode(open(path2, 'rb').read()),encoding='utf-8'),
'image_type': 'BASE64',
}
])
if result['error_code']==0:
score=result['result']['score']
if score>80:
string="同一个人\n得分:{}".format(score)
elif score<20:
string = "不是同一个人\n得分:{}".format(score)
else:
string = "两个人相似\n得分:{}".format(score)
#print(result)
self.text_m.insert('insert',string)
elif self.tag_r==0:
print("右侧图像识别错误")
elif self.tag_l==0:
print("左侧图像识别错误")
def interfacce(self):
"绘制图像界面"
"1.修改主界面标题,大小"
self.myWindow.title('人脸识别演示程序') # 修改窗口标题
self.myWindow.geometry("950x600+350+100") # 修改窗口大小 width*height+xoffset+yoffset
"1.1左侧界面"
self.text_lh = Text(self.myWindow, width=50, height=25)
self.text_lh.anchor=CENTER
self.text_lh.grid(row=0, column=0, rowspan=6, columnspan=6, sticky='EW', pady=5, padx=5)
button1 = Button(self.myWindow, text='载入图像', command=self.face_inf_display1, width=10, height=1)
button1.grid(row=6, column=5,sticky='EW', pady=5, padx=5)
self.text_ld = Text(self.myWindow, width=50, height=10)
self.text_ld.grid(row=7, column=0, rowspan=6, columnspan=6, sticky='EW', pady=5, padx=5)
"1.2中间界面"
button2 = Button(self.myWindow, text='人脸比对', command=self.result_comparison, width=8, height=1)
button2.grid(row=0, column=6, sticky='EW', pady=1, padx=1)
Label(self.myWindow, text='对比结果').grid(row=1, column=6, sticky='EW', pady=1, padx=1)
self.text_m = Text(self.myWindow, width=30, height=4)
self.text_m.grid(row=2, column=6, rowspan=1, columnspan=3, sticky='EW', pady=1, padx=1)
"1.3右侧界面"
self.text_rh = Text(self.myWindow, width=50, height=25)
self.text_rh.grid(row=0, column=10, rowspan=6, columnspan=6, sticky='EW', pady=5, padx=5)
button3 = Button(self.myWindow, text='载入图像', command=self.face_inf_display2, width=10, height=1)
button3.grid(row=6, column=15, sticky='EW', pady=5, padx=5)
self.text_rd = Text(self.myWindow, width=50, height=10)
self.text_rd.grid(row=7, column=10, rowspan=6, columnspan=6, sticky='EW', pady=5, padx=5, ipady=15)
# 启动主窗口的消息循环
self.myWindow.mainloop()
if __name__ == '__main__':
face=Face_Recognition()
face.interfacce()