使用谷歌Vision API做人脸检测时如何在Python中通过GUI展示图像
完整可运行修改代码
import tkinter as tk from PIL import Image, ImageTk from tkinter.filedialog import askopenfile import io import os from google.cloud import vision root = tk.Tk() root.title("人脸情绪识别") canvas = tk.Canvas(root, width=600, height=300) canvas.grid(columnspan=3, rowspan=3) os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = r'crack-producer-313920-5e16fbab8c24.json' client = vision.ImageAnnotatorClient() file_name = os.path.abspath('picture.jpg') with io.open(file_name, 'rb') as image_file: content = image_file.read() image = vision.Image(content=content) response = client.face_detection(image=image) faces = response.face_annotations likelihood_name = ('UNKNOWN', 'VERY_UNLIKELY', 'UNLIKELY', 'POSSIBLE', 'LIKELY', 'VERY_LIKELY') print('Faces:') for face in faces: print('anger: {}'.format(likelihood_name[face.anger_likelihood])) print('joy: {}'.format(likelihood_name[face.joy_likelihood])) print('surprise: {}'.format(likelihood_name[face.surprise_likelihood])) vertices = (['({},{})'.format(vertex.x, vertex.y) for vertex in face.bounding_poly.vertices]) print('face bounds: {}'.format(','.join(vertices))) if response.error.message: raise Exception( '{}\nFor more info on error messages, check: ' 'https://cloud.google.com/apis/design/errors'.format( response.error.message)) # ------------------- 新增GUI图片渲染逻辑 ------------------- # 加载原始图片 pil_img_raw = Image.open(file_name) orig_w, orig_h = pil_img_raw.size # 缩放图片适配画布尺寸,保持原始比例 pil_img = pil_img_raw.copy() pil_img.thumbnail((600, 300)) new_w, new_h = pil_img.size # 计算坐标缩放比例 x_ratio = new_w / orig_w y_ratio = new_h / orig_h # 转换为Tkinter支持的图片格式 tk_img = ImageTk.PhotoImage(pil_img) # 绑定到canvas属性,避免图片被Python垃圾回收导致不显示 canvas.tk_img = tk_img # 绘制图片到画布左上角 canvas.create_image(0, 0, anchor=tk.NW, image=tk_img) # 可选:绘制人脸框和情绪结果到GUI for idx, face in enumerate(faces): v = face.bounding_poly.vertices # 转换原始坐标为适配缩放后图片的坐标 x1, y1 = int(v[0].x * x_ratio), int(v[0].y * y_ratio) x2, y2 = int(v[2].x * x_ratio), int(v[2].y * y_ratio) # 画红色人脸边框 canvas.create_rectangle(x1, y1, x2, y2, outline='red', width=2) # 拼接情绪文本 emotion_info = f"#{idx+1} 喜:{likelihood_name[face.joy_likelihood]} 怒:{likelihood_name[face.anger_likelihood]} 惊:{likelihood_name[face.surprise_likelihood]}" # 文本绘制在人脸框上方 canvas.create_text(x1, y1-8, anchor=tk.SW, text=emotion_info, fill='red', font=('黑体',9)) root.mainloop()
关键改动说明
grid()是Tkinter的布局方法,仅负责控制组件在父容器中的位置,本身不需要绑定额外变量,之前无法显示是因为没有把图片内容渲染到已布局好的Canvas组件上- 必须将
ImageTk.PhotoImage生成的图片对象绑定到一个长期存在的变量/实例属性上,否则会被Python垃圾回收机制清理,导致界面看不到图片 - 新增的坐标缩放逻辑适配了图片缩放后的尺寸,保证人脸框位置和实际人脸位置对齐
- 可选的人脸框和情绪文本绘制逻辑可以直接在GUI上展示识别结果,无需再查看终端输出
内容的提问来源于stack exchange,提问作者Filzo
相关产品推荐
相关产品推荐

