Update face_recog.py

main
pos97em56 5 months ago
parent a703526ef5
commit bc48aac6c6

@ -1,165 +1,155 @@
import tkinter as tk import tkinter as tk
from tkinter import filedialog, messagebox from tkinter import filedialog, messagebox
from tkinter import Toplevel from tkinter import Toplevel
from PIL import Image, ImageTk from PIL import Image, ImageTk
import numpy as np import numpy as np
import cv2 import cv2
import os import os
img_path = "" # 全局变量,用于存储图像路径 img_path = "" # 全局变量,用于存储图像路径
src = None # 全局变量,用于存储已选择的图像 src = None # 全局变量,用于存储已选择的图像
X = None # 用于存储第一张图像 X = None # 用于存储第一张图像
Y = None # 用于存储第二张图像 Y = None # 用于存储第二张图像
img_label = None # 全局变量,用于存储显示选择的图片的标签 img_label = None # 全局变量,用于存储显示选择的图片的标签
edge = None edge = None
FaceWin = None FaceWin = None
# 获取当前脚本文件的目录 # 获取当前脚本文件的目录
base_path = os.path.dirname(os.path.abspath(__file__)) base_path = os.path.dirname(os.path.abspath(__file__))
def select_image(root): def select_image(root):
global img_path, src, img_label, edge global img_path, src, img_label, edge
img_path = filedialog.askopenfilename(filetypes=[("Image files", "*.jpg;*.png;*.jpeg;*.bmp")]) img_path = filedialog.askopenfilename(filetypes=[("Image files", "*.jpg;*.png;*.jpeg;*.bmp")])
if img_path: if img_path:
# 确保路径中的反斜杠正确处理,并使用 UTF-8 编码处理中文路径 # 确保路径中的反斜杠正确处理,并使用 UTF-8 编码处理中文路径
img_path_fixed = os.path.normpath(img_path) img_path_fixed = os.path.normpath(img_path)
# 图像输入 # 图像输入
src_temp = cv2.imdecode(np.fromfile(img_path_fixed, dtype=np.uint8), cv2.IMREAD_UNCHANGED) src_temp = cv2.imdecode(np.fromfile(img_path_fixed, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
if src_temp is None: if src_temp is None:
messagebox.showerror("错误", "无法读取图片,请选择有效的图片路径") messagebox.showerror("错误", "无法读取图片,请选择有效的图片路径")
return return
src = cv2.cvtColor(src_temp, cv2.COLOR_BGR2RGB) src = cv2.cvtColor(src_temp, cv2.COLOR_BGR2RGB)
# 检查 img_label 是否存在且有效 # 检查 img_label 是否存在且有效
if img_label is None or not img_label.winfo_exists(): if img_label is None or not img_label.winfo_exists():
img_label = tk.Label(root) img_label = tk.Label(root)
img_label.pack(side=tk.TOP, pady=10) img_label.pack(side=tk.TOP, pady=10)
img = Image.open(img_path) img = Image.open(img_path)
img.thumbnail((160, 160)) img.thumbnail((160, 160))
img_tk = ImageTk.PhotoImage(img) img_tk = ImageTk.PhotoImage(img)
img_label.configure(image=img_tk) img_label.configure(image=img_tk)
img_label.image = img_tk img_label.image = img_tk
# 定义 edge 变量为 PIL.Image 对象,以便稍后保存 # 定义 edge 变量为 PIL.Image 对象,以便稍后保存
edge = Image.fromarray(src) edge = Image.fromarray(src)
else: else:
messagebox.showerror("错误", "没有选择图片路径") messagebox.showerror("错误", "没有选择图片路径")
def show_selected_image(root): def changeSize(event, img, LabelPic):
global img_label img_aspect = img.shape[1] / img.shape[0]
img_label = tk.Label(root) new_aspect = event.width / event.height
img_label.pack(side=tk.TOP, pady=10)
img = Image.open(img_path) if new_aspect > img_aspect:
img.thumbnail((160, 160)) new_width = int(event.height * img_aspect)
img_tk = ImageTk.PhotoImage(img) new_height = event.height
img_label.configure(image=img_tk) else:
img_label.image = img_tk new_width = event.width
new_height = int(event.width / img_aspect)
def changeSize(event, img, LabelPic):
img_aspect = img.shape[1] / img.shape[0] resized_image = cv2.resize(img, (new_width, new_height))
new_aspect = event.width / event.height image1 = ImageTk.PhotoImage(Image.fromarray(resized_image))
LabelPic.image = image1
if new_aspect > img_aspect: LabelPic['image'] = image1
new_width = int(event.height * img_aspect)
new_height = event.height def savefile():
else: global edge
new_width = event.width
new_height = int(event.width / img_aspect) filename = filedialog.asksaveasfilename(defaultextension=".jpg", filetypes=[("JPEG files", "*.jpg"), ("PNG files", "*.png"), ("BMP files", "*.bmp")])
if not filename:
resized_image = cv2.resize(img, (new_width, new_height)) return
image1 = ImageTk.PhotoImage(Image.fromarray(resized_image)) # 确保 edge 变量已定义
LabelPic.image = image1 if edge is not None:
LabelPic['image'] = image1 try:
edge.save(filename)
def savefile(): messagebox.showinfo("保存成功", "图片保存成功!")
global edge except Exception as e:
messagebox.showerror("保存失败", f"无法保存图片: {e}")
filename = filedialog.asksaveasfilename(defaultextension=".jpg", filetypes=[("JPEG files", "*.jpg"), ("PNG files", "*.png"), ("BMP files", "*.bmp")]) else:
if not filename: messagebox.showerror("保存失败", "没有图像可保存")
return
# 确保 edge 变量已定义 def face_recog(root):
if edge is not None: global src, FaceWin, edge
try:
edge.save(filename) # 判断是否已经选取图片
messagebox.showinfo("保存成功", "图片保存成功!") if src is None:
except Exception as e: messagebox.showerror("错误", "没有选择图片!")
messagebox.showerror("保存失败", f"无法保存图片: {e}") return
else:
messagebox.showerror("保存失败", "没有图像可保存") # 转换为灰度图片
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
def face_recog(root):
global src, FaceWin, edge # 人脸检测器
model_path = os.path.join(base_path, 'haarcascade_frontalface_default.xml')
# 判断是否已经选取图片 face_cascade = cv2.CascadeClassifier(model_path)
if src is None:
messagebox.showerror("错误", "没有选择图片!") # 检查模型文件是否成功加载
return if face_cascade.empty():
messagebox.showerror("错误", "无法加载人脸检测模型,请检查文件路径")
# 转换为灰度图片 return
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
# 识别人脸
# 人脸检测器 faces = face_cascade.detectMultiScale(gray, 1.3, 5)
model_path = os.path.join(base_path, 'haarcascade_frontalface_default.xml')
face_cascade = cv2.CascadeClassifier(model_path) # 显示检测结果
for (x, y, w, h) in faces:
# 检查模型文件是否成功加载 # 在人脸区域添加矩形框
if face_cascade.empty(): cv2.rectangle(src, (x, y), (x + w, y + h), (255, 0, 0), 2)
messagebox.showerror("错误", "无法加载人脸检测模型,请检查文件路径")
return # 提取人脸区域的灰度图像
face_gray = gray[y:y + h, x:x + w]
# 识别人脸
faces = face_cascade.detectMultiScale(gray, 1.3, 5) # 眼睛检测器
eye_model_path = os.path.join(base_path, 'haarcascade_eye.xml')
# 显示检测结果 eye_cascade = cv2.CascadeClassifier(eye_model_path)
for (x, y, w, h) in faces:
# 在人脸区域添加矩形框 # 识别人眼
cv2.rectangle(src, (x, y), (x + w, y + h), (255, 0, 0), 2) eyes = eye_cascade.detectMultiScale(face_gray)
# 提取人脸区域的灰度图像 # 在眼睛区域添加矩形框
face_gray = gray[y:y + h, x:x + w] for (ex, ey, ew, eh) in eyes:
cv2.rectangle(src, (x + ex, y + ey), (x + ex + ew, y + ey + eh), (0, 255, 0), 2)
# 眼睛检测器
eye_model_path = os.path.join(base_path, 'haarcascade_eye.xml') # 更新 edge 变量
eye_cascade = cv2.CascadeClassifier(eye_model_path) edge = Image.fromarray(src)
# 识别人眼 # 创建Toplevel窗口
eyes = eye_cascade.detectMultiScale(face_gray) try:
FaceWin.destroy()
# 在眼睛区域添加矩形框 except Exception:
for (ex, ey, ew, eh) in eyes: print("NVM")
cv2.rectangle(src, (x + ex, y + ey), (x + ex + ew, y + ey + eh), (0, 255, 0), 2) finally:
FaceWin = Toplevel()
# 更新 edge 变量 FaceWin.attributes('-topmost', True)
edge = Image.fromarray(src) FaceWin.geometry("360x300")
FaceWin.resizable(True, True) # 可缩放
# 创建Toplevel窗口 FaceWin.title("检测到的人脸")
try:
FaceWin.destroy() # 显示图像
except Exception: LabelPic = tk.Label(FaceWin, text="IMG", width=360, height=240)
print("NVM") image = ImageTk.PhotoImage(Image.fromarray(cv2.cvtColor(src, cv2.COLOR_BGR2RGB)))
finally: LabelPic.image = image
FaceWin = Toplevel() LabelPic['image'] = image
FaceWin.attributes('-topmost', True)
FaceWin.geometry("360x300") LabelPic.bind('<Configure>', lambda event: changeSize(event, src, LabelPic))
FaceWin.resizable(True, True) # 可缩放 LabelPic.pack(fill=tk.BOTH, expand=tk.YES)
FaceWin.title("检测到的人脸")
# 添加保存按钮
# 显示图像 btn_save = tk.Button(FaceWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20,
LabelPic = tk.Label(FaceWin, text="IMG", width=360, height=240) command=savefile)
image = ImageTk.PhotoImage(Image.fromarray(cv2.cvtColor(src, cv2.COLOR_BGR2RGB))) btn_save.pack(pady=10)
LabelPic.image = image
LabelPic['image'] = image
LabelPic.bind('<Configure>', lambda event: changeSize(event, src, LabelPic))
LabelPic.pack(fill=tk.BOTH, expand=tk.YES)
# 添加保存按钮
btn_save = tk.Button(FaceWin, text="保存", bg='#add8e6', fg='black', font=('Helvetica', 14), width=20,
command=savefile)
btn_save.pack(pady=10)
return return
Loading…
Cancel
Save