diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..10b731c
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,5 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
diff --git a/.idea/face-random.iml b/.idea/face-random.iml
new file mode 100644
index 0000000..8437fe6
--- /dev/null
+++ b/.idea/face-random.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..9de2865
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..b81af9f
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/main.py b/1.py
similarity index 97%
rename from main.py
rename to 1.py
index 8c6f004..429760a 100644
--- a/main.py
+++ b/1.py
@@ -2,9 +2,9 @@ import sys
import random
import cv2
from cvzone.FaceDetectionModule import FaceDetector
-from PyQt6.QtCore import QTimer
-from PyQt6.QtGui import QImage, QPixmap
-from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QPushButton
+from PySide6.QtCore import QTimer
+from PySide6.QtGui import QImage, QPixmap
+from PySide6.QtWidgets import QApplication, QWidget, QLabel, QPushButton
class FaceRandomApp(QWidget):
diff --git a/2.py b/2.py
new file mode 100644
index 0000000..d5b9bbb
--- /dev/null
+++ b/2.py
@@ -0,0 +1,207 @@
+import cv2
+import numpy as np
+import random
+import os
+import sys
+from collections import deque
+
+class FaceSelector:
+ def __init__(self):
+ # 获取模型文件的正确路径
+ cascade_path = self.get_cascade_path()
+ self.face_cascade = cv2.CascadeClassifier(cascade_path)
+
+ # 检查模型是否加载成功
+ if self.face_cascade.empty():
+ fallback_path = cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
+ self.face_cascade = cv2.CascadeClassifier(fallback_path)
+
+ if self.face_cascade.empty():
+ sys.exit(1)
+
+ # 状态变量
+ self.random_mode = False
+ self.selected_face = None
+ self.static_frame = None
+ self.static_faces = None
+
+ # 用于平滑检测的队列
+ self.face_queue = deque(maxlen=5)
+
+ # 创建窗口
+ self.window_name = "Face Selector"
+ cv2.namedWindow(self.window_name, cv2.WINDOW_NORMAL)
+
+ # 添加窗口关闭事件处理
+ self.running = True
+
+ def get_cascade_path(self):
+ """获取模型文件的正确路径"""
+ if getattr(sys, 'frozen', False):
+ base_path = sys._MEIPASS
+ else:
+ base_path = os.path.dirname(os.path.abspath(__file__))
+
+ possible_paths = [
+ os.path.join(base_path, 'haarcascade_frontalface_default.xml'),
+ os.path.join(base_path, 'cv2', 'data', 'haarcascade_frontalface_default.xml'),
+ os.path.join(base_path, 'Library', 'etc', 'haarcascades', 'haarcascade_frontalface_default.xml'),
+ cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
+ ]
+
+ for path in possible_paths:
+ if os.path.isfile(path):
+ return path
+
+ return possible_paths[0]
+
+ def detect_faces(self, frame):
+ """检测人脸并返回位置"""
+ gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
+
+ faces = self.face_cascade.detectMultiScale(
+ gray,
+ scaleFactor=1.05,
+ minNeighbors=6,
+ minSize=(40, 40),
+ flags=cv2.CASCADE_SCALE_IMAGE
+ )
+ return faces
+
+ def draw_faces(self, frame, faces):
+ """在帧上绘制人脸框"""
+ # 在随机模式下,只绘制选中的红框
+ if self.random_mode and self.selected_face is not None and self.static_faces is not None:
+ if self.selected_face < len(self.static_faces):
+ x, y, w, h = self.static_faces[self.selected_face]
+ cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 3) # 选中的为红色
+ else:
+ # 在正常模式下,绘制所有人脸框
+ for (x, y, w, h) in faces:
+ cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2) # 绿色
+
+ return frame
+
+ def draw_button(self, frame):
+ """绘制按钮"""
+ button_text = "Reset" if self.random_mode else "Random"
+ button_color = (0, 0, 255) if self.random_mode else (0, 255, 0)
+
+ # 绘制按钮背景
+ cv2.rectangle(frame, (10, 10), (150, 50), button_color, -1)
+ cv2.rectangle(frame, (10, 10), (150, 50), (255, 255, 255), 2)
+
+ # 绘制按钮文字
+ cv2.putText(frame, button_text, (20, 35), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
+
+ return frame
+
+ def toggle_random_mode(self, frame, faces):
+ """切换随机模式"""
+ if not self.random_mode:
+ # 进入随机模式
+ self.random_mode = True
+ if len(faces) > 0:
+ self.selected_face = random.randint(0, len(faces)-1)
+ self.static_frame = frame.copy()
+ self.static_faces = faces.copy() # 保存静态状态下的人脸位置
+ else:
+ self.selected_face = None
+ self.static_frame = None
+ self.static_faces = None
+ else:
+ # 退出随机模式
+ self.random_mode = False
+ self.selected_face = None
+ self.static_frame = None
+ self.static_faces = None
+
+ def process_frame(self, frame):
+ """处理每一帧"""
+ # 检测人脸
+ faces = self.detect_faces(frame)
+
+ # 更新人脸队列
+ if len(faces) > 0:
+ self.face_queue.append(faces)
+
+ # 使用队列中最新的人脸数据
+ current_faces = faces
+ if self.face_queue:
+ current_faces = self.face_queue[-1]
+
+ # 处理随机模式
+ if self.random_mode:
+ if self.static_frame is not None:
+ # 使用静态帧,只绘制选中的红框
+ display_frame = self.static_frame.copy()
+ display_frame = self.draw_faces(display_frame, current_faces)
+ else:
+ display_frame = frame.copy()
+ else:
+ # 在实时帧上绘制所有人脸
+ display_frame = self.draw_faces(frame.copy(), current_faces)
+
+ # 绘制按钮
+ display_frame = self.draw_button(display_frame)
+
+ return display_frame
+
+ def run(self):
+ """运行主程序"""
+ cap = cv2.VideoCapture(0)
+
+ if not cap.isOpened():
+ return
+
+ # 获取摄像头分辨率并设置窗口大小
+ ret, frame = cap.read()
+ if ret:
+ height, width = frame.shape[:2]
+ cv2.resizeWindow(self.window_name, width, height)
+
+ while self.running:
+ ret, frame = cap.read()
+ if not ret:
+ cv2.waitKey(1000)
+ continue
+
+ # 处理帧
+ display_frame = self.process_frame(frame)
+
+ # 显示结果
+ cv2.imshow(self.window_name, display_frame)
+
+ # 处理鼠标点击
+ def mouse_callback(event, x, y, flags, param):
+ if event == cv2.EVENT_LBUTTONDOWN:
+ # 检查是否点击了按钮区域
+ if 10 <= x <= 150 and 10 <= y <= 50:
+ faces = self.detect_faces(frame)
+ self.toggle_random_mode(frame, faces)
+
+ cv2.setMouseCallback(self.window_name, mouse_callback)
+
+ # 处理键盘输入和窗口关闭事件
+ key = cv2.waitKey(1) & 0xFF
+ if key == ord('q') or key == 27: # 'q' 或 ESC 键退出
+ self.running = False
+ break
+
+ # 检查窗口是否被关闭
+ try:
+ if cv2.getWindowProperty(self.window_name, cv2.WND_PROP_VISIBLE) <= 0:
+ self.running = False
+ break
+ except:
+ self.running = False
+ break
+
+ # 释放资源
+ cap.release()
+ cv2.destroyAllWindows()
+ sys.exit(0)
+
+if __name__ == "__main__":
+ app = FaceSelector()
+ app.run()
diff --git a/3.py b/3.py
new file mode 100644
index 0000000..e4017a5
--- /dev/null
+++ b/3.py
@@ -0,0 +1,199 @@
+import sys
+import random
+import cv2
+from cvzone.FaceDetectionModule import FaceDetector
+from PySide6.QtCore import QTimer
+from PySide6.QtGui import QImage, QPixmap
+from PySide6.QtWidgets import QApplication, QWidget, QLabel, QPushButton
+
+
+class FaceRandomApp(QWidget):
+ def __init__(self):
+ super().__init__()
+
+ self.setWindowTitle("Face Random Selector")
+
+ # 状态:normal → random
+ self.state = "normal"
+ self.selected_face_index = -1
+ self.static_frame = None # 保存随机状态下的静态画面
+ self.all_faces_snapshot = [] # 保存所有人脸信息快照
+
+ # ---------------- 摄像头 ----------------
+ self.cap = cv2.VideoCapture(0)
+
+ # 设置摄像头分辨率
+ self.cap.set(3, 1280)
+ self.cap.set(4, 720)
+
+ # 设置窗口初始大小
+ self.resize(1280, 720)
+
+ # 使用长距离模型和更低的人脸检测阈值以提高检测率
+ self.detector = FaceDetector(minDetectionCon=0.25, modelSelection=1)
+
+ # ---------------- 创建界面 ----------------
+ self.setup_ui()
+
+ self.faces = []
+
+ def setup_ui(self):
+ # 视频标签 - 填充整个窗口
+ self.video_label = QLabel(self)
+ self.video_label.setStyleSheet("background:#000;")
+ self.video_label.setGeometry(0, 0, self.width(), self.height())
+
+ # 按钮 - 叠加在视频上
+ self.btn = QPushButton("随机", self)
+ self.btn.setFixedSize(140, 55)
+ self.btn.setStyleSheet("""
+ QPushButton {
+ background-color: rgba(0, 0, 0, 120);
+ color: white;
+ font-size: 20px;
+ padding: 10px 20px;
+ border-radius: 8px;
+ }
+ QPushButton:hover {
+ background-color: rgba(30, 30, 30, 180);
+ }
+ """)
+ self.btn.clicked.connect(self.button_clicked)
+
+ # 初始按钮位置
+ self.update_button_position()
+
+ def resizeEvent(self, event):
+ """窗口大小改变时自动调整视频和按钮位置"""
+ self.video_label.setGeometry(0, 0, self.width(), self.height())
+ self.update_button_position()
+ super().resizeEvent(event)
+
+ def update_button_position(self):
+ """更新按钮位置"""
+ btn_w = 140
+ btn_h = 55
+ margin = 20
+ self.btn.setGeometry(
+ margin,
+ self.height() - btn_h - margin,
+ btn_w,
+ btn_h
+ )
+
+ # ---------------------------------------------------------
+ # 逻辑按钮:随机 ↔ 重置
+ # ---------------------------------------------------------
+ def button_clicked(self):
+ if self.state == "normal":
+ # 切换到随机状态
+ self.state = "random"
+ self.btn.setText("重置")
+
+ # 随机选择一个人脸
+ if len(self.faces) > 0:
+ self.selected_face_index = random.randint(0, len(self.faces) - 1)
+
+ # 保存当前帧作为静态画面
+ ret, img = self.cap.read()
+ if ret:
+ img = cv2.flip(img, 1)
+ # 调整图像大小以适应窗口
+ img = cv2.resize(img, (self.video_label.width(), self.video_label.height()))
+ self.static_frame = img.copy()
+ self.all_faces_snapshot = self.faces.copy()
+ else: # self.state == "random"
+ # 切换回初始状态
+ self.state = "normal"
+ self.selected_face_index = -1
+ self.static_frame = None
+ self.all_faces_snapshot = []
+ self.btn.setText("随机")
+
+ # ---------------------------------------------------------
+ # 刷视频帧
+ # ---------------------------------------------------------
+ def update_frame(self):
+ # ============================
+ # 状态:normal(检测所有人脸并显示绿框)
+ # ============================
+ if self.state == "normal":
+ ret, img = self.cap.read()
+ if not ret:
+ return
+
+ img = cv2.flip(img, 1)
+
+ # 调整图像大小以适应窗口
+ img = cv2.resize(img, (self.video_label.width(), self.video_label.height()))
+
+ # 检测人脸
+ img, faces = self.detector.findFaces(img, draw=False)
+ self.faces = faces if faces else []
+
+ # 绘制所有人脸为绿色
+ for face in self.faces:
+ x, y, w, h = face["bbox"]
+ score = face["score"][0]
+ cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 3)
+ cv2.putText(img, f"{score:.2f}", (x, y - 10),
+ cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
+
+ # 显示图像
+ self.display_image(img)
+
+ # ============================
+ # 状态:random(显示静态画面,选中的人脸为红色,其他为绿色)
+ # ============================
+ elif self.state == "random" and self.static_frame is not None:
+ img = self.static_frame.copy()
+
+ # 绘制所有人脸,选中的为红色,其他为绿色
+ for i, face in enumerate(self.all_faces_snapshot):
+ x, y, w, h = face["bbox"]
+ score = face["score"][0]
+
+ if i == self.selected_face_index:
+ color = (0, 0, 255) # 红色
+ else:
+ color = (0, 255, 0) # 绿色
+
+ cv2.rectangle(img, (x, y), (x + w, y + h), color, 3)
+ cv2.putText(img, f"{score:.2f}", (x, y - 10),
+ cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)
+
+ # 显示图像
+ self.display_image(img)
+
+ # ---------------------------------------------------------
+ # 显示图像到 QLabel
+ # ---------------------------------------------------------
+ def display_image(self, img):
+ rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
+ h, w, ch = rgb.shape
+ bytes_per_line = ch * w
+ qimg = QImage(rgb.data, w, h, bytes_per_line, QImage.Format.Format_RGB888)
+ self.video_label.setPixmap(QPixmap.fromImage(qimg))
+
+ # ---------------------------------------------------------
+ def closeEvent(self, event):
+ if self.cap.isOpened():
+ self.cap.release()
+ event.accept()
+
+
+def main():
+ app = QApplication(sys.argv)
+ window = FaceRandomApp()
+ window.show()
+
+ # 启动定时器
+ timer = QTimer()
+ timer.timeout.connect(window.update_frame)
+ timer.start(30)
+
+ sys.exit(app.exec())
+
+
+if __name__ == "__main__":
+ main()
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..7b660a8
--- /dev/null
+++ b/readme.md
@@ -0,0 +1 @@
+nuitka --standalone --include-package=cv2 --enable-plugin=pyside6 --include-data-dir=F:\python310\lib\site-packages\cv2\data=cv2\data --output-dir=dist3 --remove-output 3.py
\ No newline at end of file