智识第二版 250205班级 人工智能项目
dks
2025-06-10 c64815b9abdaad8713e964429891d3f477204357
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import cv2
import dlib
import os
import numpy as np
 
# 计算眼睛纵横比
def eye_aspect_ratio(eye):
    A = np.linalg.norm(eye[1] - eye[5])
    B = np.linalg.norm(eye[2] - eye[4])
    C = np.linalg.norm(eye[0] - eye[3])
    ear = (A + B) / (2.0 * C)
    return ear
 
# 检测头部运动(简单示例,可根据实际情况优化)
def detect_head_movement(prev_face_landmarks, face_landmarks):
    if prev_face_landmarks is None:
        return False
    prev_nose = prev_face_landmarks[30]
    current_nose = face_landmarks[30]
    movement_threshold = 10  # 调整阈值
    return abs(current_nose[0] - prev_nose[0]) > movement_threshold or abs(
        current_nose[1] - prev_nose[1]
    ) > movement_threshold
 
# 直接指定路径和参数
input_path = None  # 如果需要从文件读取可以指定路径,这里设为None表示使用摄像头
# 使用原始字符串来定义路径,避免转义问题
output_path = r"H:\python_charm\python_project\database"
detector_path = r"H:\python_charm\python_project\face_detector"
confidence = 0.5
 
# 加载人脸检测模型
print("[INFO] loading face detector...")
protoPath = os.path.sep.join([detector_path, "deploy.prototxt"])
modelPath = os.path.sep.join([detector_path, "res10_300x300_ssd_iter_140000.caffemodel"])
net = cv2.dnn.readNetFromCaffe(protoPath, modelPath)
 
# 创建输出目录
if not os.path.exists(output_path):
    os.makedirs(output_path)
real_output_dir = os.path.join(output_path, "real")
fake_output_dir = os.path.join(output_path, "fake")
if not os.path.exists(real_output_dir):
    os.makedirs(real_output_dir)
if not os.path.exists(fake_output_dir):
    os.makedirs(fake_output_dir)
 
# 初始化dlib的面部关键点检测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
 
# 初始化参数
EYE_AR_THRESH = 0.3
EYE_AR_CONSEC_FRAMES = 3
COUNTER = 0
TOTAL = 0
prev_face_landmarks = None
has_shaken_head = False
has_blinked = False
saved_fake = 0
saved_real = 0
# 各自采集500张
target_count = 500
# 新增标志变量,用于记录是否正在连续采集
is_continuous_capturing = False
capture_type = None  # 记录当前采集的类型('real' 或 'fake')
 
# 打开摄像头
cap = cv2.VideoCapture(0)
 
print("[INFO] Automatically taking pictures...")
 
while True:
    ret, frame = cap.read()
    if not ret:
        break
 
    (h, w) = frame.shape[:2]
    blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 1.0,
                                 (300, 300), (104.0, 177.0, 123.0))
    net.setInput(blob)
    detections = net.forward()
 
    # 检测到的人脸
    if len(detections) > 0:
        i = np.argmax(detections[0, 0, :, 2])
        detection_confidence = detections[0, 0, i, 2]  # 重命名变量,避免混淆
 
        if detection_confidence > confidence:
            box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
            (startX, startY, endX, endY) = box.astype("int")
 
            # 提取面部关键点
            rect = dlib.rectangle(int(startX), int(startY), int(endX), int(endY))
            face_landmarks = predictor(frame, rect)
            face_landmarks = np.array([[part.x, part.y] for part in face_landmarks.parts()])
 
            # 检测头部运动
            has_shaken_head = has_shaken_head or detect_head_movement(prev_face_landmarks, face_landmarks)
            prev_face_landmarks = face_landmarks
 
            # 检测眨眼动作
            left_eye = face_landmarks[42:48]
            right_eye = face_landmarks[36:42]
            left_ear = eye_aspect_ratio(left_eye)
            right_ear = eye_aspect_ratio(right_eye)
            ear = (left_ear + right_ear) / 2.0
 
            if ear < EYE_AR_THRESH:
                COUNTER += 1
            else:
                if COUNTER >= EYE_AR_CONSEC_FRAMES:
                    TOTAL += 1
                    has_blinked = has_blinked or True
                COUNTER = 0
 
            # 保存人脸区域
            face = frame[startY:endY, startX:endX]
 
            if is_continuous_capturing:
                if capture_type == "real":
                    label = "real"
                    saved = saved_real
                    output_dir = real_output_dir
                else:
                    label = "fake"
                    saved = saved_fake
                    output_dir = fake_output_dir
 
                p = os.path.sep.join([output_dir, f"{label}_{saved}.png"])
                cv2.imwrite(p, face)
                print(f"[INFO] saved {p} to disk")
 
                if label == "fake":
                    saved_fake += 1
                else:
                    saved_real += 1
 
                if (capture_type == "real" and saved_real >= target_count) or \
                   (capture_type == "fake" and saved_fake >= target_count):
                    is_continuous_capturing = False
                    print(f"[INFO] Reached the target count for {capture_type} images.")
            else:
                print("[INFO] Please enter 'r' for real or 'f' for fake (q to quit): ")
                key = cv2.waitKey(0) & 0xFF
                if key == ord("r"):
                    if saved_real < target_count:
                        is_continuous_capturing = True
                        capture_type = "real"
                    else:
                        print("[INFO] Already reached the target count for real images. Skipping.")
                elif key == ord("f"):
                    if saved_fake < target_count:
                        is_continuous_capturing = True
                        capture_type = "fake"
                    else:
                        print("[INFO] Already reached the target count for fake images. Skipping.")
                elif key == ord("q"):
                    break
 
    # 显示画面
    cv2.imshow("Frame", frame)
 
    key = cv2.waitKey(1) & 0xFF
    if key == ord("q"):
        break
 
    # 当真实和虚假图片都采集到500张时结束
    if saved_fake >= target_count and saved_real >= target_count:
        print("[INFO] Reached the target count for both real and fake images. Exiting...")
        break
 
cap.release()
cv2.destroyAllWindows()