update
This commit is contained in:
parent
a2774513cb
commit
94146dacbb
70
main.py
70
main.py
@ -1,9 +1,15 @@
|
|||||||
|
from concurrent.futures import thread
|
||||||
|
from threading import Thread
|
||||||
|
import threading
|
||||||
import cv2
|
import cv2
|
||||||
import mediapipe as mp
|
import mediapipe as mp
|
||||||
# 在Pygame中使用归一化坐标
|
|
||||||
import pygame
|
import pygame
|
||||||
import time
|
import time
|
||||||
import random
|
import random
|
||||||
|
import os
|
||||||
|
import tkinter as tk
|
||||||
|
from PIL import Image, ImageTk
|
||||||
|
|
||||||
# 初始化游戏窗口
|
# 初始化游戏窗口
|
||||||
pygame.init()
|
pygame.init()
|
||||||
# 字体初始化
|
# 字体初始化
|
||||||
@ -57,13 +63,69 @@ last_obstacle_time_right = 0
|
|||||||
MIN_OBSTACLE_INTERVAL = 2000 # 毫秒,同一侧障碍物最小生成间隔
|
MIN_OBSTACLE_INTERVAL = 2000 # 毫秒,同一侧障碍物最小生成间隔
|
||||||
|
|
||||||
start_time = time.time() # 游戏开始时间
|
start_time = time.time() # 游戏开始时间
|
||||||
|
|
||||||
|
def get_player_avatar():
|
||||||
|
global cap
|
||||||
|
"""获取当前游玩者的头像(人脸图像)。"""
|
||||||
|
mp_face = mp.solutions.face_detection # type: ignore
|
||||||
|
face_detection = mp_face.FaceDetection(min_detection_confidence=0.5)
|
||||||
|
|
||||||
|
ret, frame = cap.read()
|
||||||
|
if not ret:
|
||||||
|
return None # 如果未读取到帧,返回 None
|
||||||
|
|
||||||
|
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||||
|
results = face_detection.process(frame_rgb)
|
||||||
|
|
||||||
|
if results.detections:
|
||||||
|
max_area = 0
|
||||||
|
best_detection = None
|
||||||
|
|
||||||
|
# 找到最大的面框
|
||||||
|
for detection in results.detections:
|
||||||
|
bbox = detection.location_data.relative_bounding_box
|
||||||
|
area = bbox.width * bbox.height
|
||||||
|
if area > max_area:
|
||||||
|
max_area = area
|
||||||
|
best_detection = bbox
|
||||||
|
|
||||||
|
if best_detection:
|
||||||
|
# 计算面框在原始帧中的坐标
|
||||||
|
h, w, _ = frame.shape
|
||||||
|
x_min = int(best_detection.xmin * w)
|
||||||
|
y_min = int(best_detection.ymin * h)
|
||||||
|
x_max = int((best_detection.xmin + best_detection.width) * w)
|
||||||
|
y_max = int((best_detection.ymin + best_detection.height) * h)
|
||||||
|
|
||||||
|
# 增加边界,确保完整性
|
||||||
|
border_x = int(0.1 * (x_max - x_min)) # 边界宽度为框宽度的10%
|
||||||
|
border_y = int(0.1 * (y_max - y_min)) # 边界高度为框高度的10%
|
||||||
|
|
||||||
|
# 更新坐标以增加边界,同时确保坐标在有效范围内
|
||||||
|
x_min = max(x_min - border_x, 0) # 确保不小于0
|
||||||
|
y_min = max(y_min - border_y, 0) # 确保不小于0
|
||||||
|
x_max = min(x_max + border_x, w) # 确保不超出图像宽度
|
||||||
|
y_max = min(y_max + border_y, h) # 确保不超出图像高度
|
||||||
|
|
||||||
|
# 裁剪出面框区域
|
||||||
|
avatar = frame[y_min:y_max, x_min:x_max]
|
||||||
|
return avatar
|
||||||
|
|
||||||
|
return None # 如果未检测到人脸,返回 None
|
||||||
|
|
||||||
def you_failed(elapsed_time):
|
def you_failed(elapsed_time):
|
||||||
global obstacles
|
global obstacles
|
||||||
obstacles.clear()
|
obstacles.clear()
|
||||||
"""处理失败的函数,弹出消息或重置游戏等"""
|
"""处理失败的函数,弹出消息或重置游戏等"""
|
||||||
global start_time
|
global start_time
|
||||||
|
print(f"You failed! Elapsed dis: {elapsed_time:.2f} meters")
|
||||||
|
if not os.path.exists("faces"):
|
||||||
|
os.makedirs("faces")
|
||||||
|
file_name = os.path.join("faces",f"{elapsed_time:.2f}.png")
|
||||||
|
avatar = get_player_avatar()
|
||||||
|
if avatar is not None:
|
||||||
|
cv2.imwrite(file_name,avatar)
|
||||||
start_time=time.time()
|
start_time=time.time()
|
||||||
print(f"You failed! Elapsed time: {elapsed_time:.2f} seconds")
|
|
||||||
# 在此处添加其他失败处理逻辑,例如重置游戏、显示消息等
|
# 在此处添加其他失败处理逻辑,例如重置游戏、显示消息等
|
||||||
|
|
||||||
def draw_ball(normalized_x, normalized_y):
|
def draw_ball(normalized_x, normalized_y):
|
||||||
@ -72,7 +134,7 @@ def draw_ball(normalized_x, normalized_y):
|
|||||||
"""在Pygame窗口中绘制小球并处理障碍物"""
|
"""在Pygame窗口中绘制小球并处理障碍物"""
|
||||||
# 计算经过的时间
|
# 计算经过的时间
|
||||||
elapsed_time = time.time() - start_time
|
elapsed_time = time.time() - start_time
|
||||||
elapsed_seconds = int(elapsed_time) # 整数秒数
|
# elapsed_seconds = # 整数秒数
|
||||||
|
|
||||||
# 计算小球位置
|
# 计算小球位置
|
||||||
ball_x = int(normalized_x * (screen.get_width() - ball_radius * 2)) + ball_radius
|
ball_x = int(normalized_x * (screen.get_width() - ball_radius * 2)) + ball_radius
|
||||||
@ -139,7 +201,7 @@ def draw_ball(normalized_x, normalized_y):
|
|||||||
obstacles.remove(obstacle)
|
obstacles.remove(obstacle)
|
||||||
|
|
||||||
# 绘制计时器文本
|
# 绘制计时器文本
|
||||||
timer_text = font.render(f"{elapsed_seconds} M", True, (255, 255, 255)) # 白色文本
|
timer_text = font.render(f"{elapsed_time:.2f} M", True, (255, 255, 255)) # 白色文本
|
||||||
screen.blit(timer_text, (10, 10)) # 在左上角绘制文本(10, 10)是坐标
|
screen.blit(timer_text, (10, 10)) # 在左上角绘制文本(10, 10)是坐标
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
clock.tick(60)
|
clock.tick(60)
|
||||||
|
@ -5,7 +5,7 @@ description = "Default template for PDM package"
|
|||||||
authors = [
|
authors = [
|
||||||
{name = "Zengtudor", email = "Zengtudor@outlook.com"},
|
{name = "Zengtudor", email = "Zengtudor@outlook.com"},
|
||||||
]
|
]
|
||||||
dependencies = ["opencv-python>=4.11.0.86", "mediapipe>=0.10.21", "numpy>=1.26.4", "pygame>=2.6.1"]
|
dependencies = ["opencv-python>=4.11.0.86", "mediapipe>=0.10.21", "numpy>=1.26.4", "pygame>=2.6.1", "Pillow>=11.1.0"]
|
||||||
requires-python = "==3.12.*"
|
requires-python = "==3.12.*"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = {text = "MIT"}
|
license = {text = "MIT"}
|
||||||
|
76
show_avatar.py
Normal file
76
show_avatar.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import os
|
||||||
|
import tkinter as tk
|
||||||
|
from PIL import Image, ImageTk, ImageDraw, ImageFont
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
|
def load_images_from_folder(folder):
|
||||||
|
"""从指定文件夹加载图像文件,并按文件前的数字排序."""
|
||||||
|
images = []
|
||||||
|
for filename in sorted(os.listdir(folder), key=lambda x: float(x[:-4]), reverse=True):
|
||||||
|
if filename.endswith(('.png', '.jpg', '.jpeg')): # 只处理图像文件
|
||||||
|
img_path = os.path.join(folder, filename)
|
||||||
|
images.append((img_path, filename[:-4])) # 返回图像路径及文件名(去掉扩展名)
|
||||||
|
return images
|
||||||
|
|
||||||
|
def create_image_viewer(folder_path):
|
||||||
|
"""创建图像查看器并展示指定文件夹中的图像, 返回刷新函数."""
|
||||||
|
|
||||||
|
def show_images():
|
||||||
|
"""显示前五张图像于标签中."""
|
||||||
|
for i, (image_path, filename) in enumerate(images[:8]):
|
||||||
|
img = Image.open(image_path).convert("RGBA")
|
||||||
|
img = img.resize((200, 200), Image.Resampling.LANCZOS) # 调整图像大小,使用 LANCZOS
|
||||||
|
|
||||||
|
# 在图像上添加文本
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
font = ImageFont.load_default() # 使用默认字体
|
||||||
|
text_position = (10, 10) # 文本位置
|
||||||
|
try:
|
||||||
|
font = ImageFont.truetype("arial.ttf", 30) # 加载自定义字体并设置大小
|
||||||
|
except IOError:
|
||||||
|
font = ImageFont.load_default() # 如果无法加载自定义字体则使用默认字体
|
||||||
|
draw.text(text_position, f"{filename} M", fill="red",font=font) # 添加文本
|
||||||
|
|
||||||
|
img = ImageTk.PhotoImage(img)
|
||||||
|
|
||||||
|
# 计算位置并创建标签显示图像
|
||||||
|
image_label = tk.Label(root, image=img)
|
||||||
|
image_label.image = img # type: ignore # 保持对图像的引用
|
||||||
|
image_label.grid(row=i//2, column=i%2) # 放置在一列中,垂直排列
|
||||||
|
|
||||||
|
def refresh_images():
|
||||||
|
"""刷新图像列表."""
|
||||||
|
nonlocal images
|
||||||
|
images = load_images_from_folder(folder_path) # 重新加载图像
|
||||||
|
for widget in root.grid_slaves(): # 清除之前的图像标签
|
||||||
|
widget.destroy()
|
||||||
|
show_images() # 显示新图像
|
||||||
|
|
||||||
|
def auto_refresh():
|
||||||
|
"""每五秒自动刷新图像."""
|
||||||
|
while True:
|
||||||
|
refresh_images()
|
||||||
|
time.sleep(10)
|
||||||
|
|
||||||
|
# 创建Tkinter窗口
|
||||||
|
root = tk.Tk()
|
||||||
|
root.title("Display Faces Images")
|
||||||
|
|
||||||
|
# 加载图像
|
||||||
|
images = load_images_from_folder(folder_path)
|
||||||
|
|
||||||
|
# 显示图像
|
||||||
|
show_images()
|
||||||
|
|
||||||
|
# 启动自动刷新线程
|
||||||
|
refresh_thread = threading.Thread(target=auto_refresh, daemon=True)
|
||||||
|
refresh_thread.start()
|
||||||
|
|
||||||
|
# 启动程序
|
||||||
|
root.after(0, lambda: root.focus_force()) # 确保窗口获得焦点
|
||||||
|
root.mainloop()
|
||||||
|
|
||||||
|
# 使用示例:
|
||||||
|
folder_path = "faces" # 图像文件夹路径
|
||||||
|
create_image_viewer(folder_path)
|
Loading…
Reference in New Issue
Block a user