import cv2
import dlib
import numpy as np
from scipy.spatial import distance as dist
import pyttsx3
import time
import webbrowser
import subprocess
from flask import Flask, render_template, Response, jsonify
# 初始化语音引擎
engine = pyttsx3.init()
# 加载Dlib的面部关键点检测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
# 定义函数来计算眼睛的纵横比
def eye_aspect_ratio(eye):
A = dist.euclidean(eye[1], eye[5])
B = dist.euclidean(eye[2], eye[4])
C = dist.euclidean(eye[0], eye[3])
ear = (A + B) / (2.0 * C)
return ear
# 定义常量
EYE_AR_THRESHOLD = 0.3
EYE_AR_CONSEC_FRAMES = 48
# 初始化帧计数器和眼睛纵横比历史列表
COUNTER = 0
EAR_HISTORY = []
# 打开摄像头
cap = cv2.VideoCapture(0)
# 设置程序运行的最大时间,单位为秒
MAX_RUN_TIME = 300 # 例如,设置为运行5分钟
# 记录程序的启动时间
start_time = time.time()
app = Flask(__name__)
@app.route('/get_ear_value')
def get_ear_value():
global EAR_HISTORY
if EAR_HISTORY:
avg_ear = np.mean(EAR_HISTORY)
return jsonify({'ear': avg_ear})
else:
return jsonify({'ear': 0.0})
@app.route('/')
def index():
return render_template('index.html')
def gen():
global COUNTER # 声明COUNTER为全局变量
while True:
ret, frame = cap.read()
if not ret:
break
# 将图像转换为灰度图
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 检测面部
faces = detector(gray)
for face in faces:
shape = predictor(gray, face)
# 提取左眼和右眼的坐标
left_eye = [(shape.part(i).x, shape.part(i).y) for i in range(42, 48)]
right_eye = [(shape.part(i).x, shape.part(i).y) for i in range(36, 42)]
# 计算左眼和右眼的纵横比
left_ear = eye_aspect_ratio(left_eye)
right_ear = eye_aspect_ratio(right_eye)
# 平均左右眼的纵横比
ear = (left_ear + right_ear) / 2.0
# 将纵横比添加到历史列表
EAR_HISTORY.append(ear)
# 如果历史列表超过指定帧数,则进行判断
if len(EAR_HISTORY) >= EYE_AR_CONSEC_FRAMES:
# 计算历史纵横比的平均值
avg_ear = np.mean(EAR_HISTORY)
# 如果平均纵横比低于阈值,则认为面部疲劳
if avg_ear < EYE_AR_THRESHOLD:
COUNTER += 1
if COUNTER == EYE_AR_CONSEC_FRAMES:
engine.say("面部疲劳检测")
engine.runAndWait()
else:
COUNTER = 0
EAR_HISTORY.clear()
# 绘制面部区域和纵横比
cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
current_time = time.time()
elapsed_time = current_time - start_time
# 如果运行时间超过设定的时间,自动停止程序
if elapsed_time >= MAX_RUN_TIME:
break
# 将图像数据转换为JPEG格式
ret, jpeg = cv2.imencode('.jpg', frame)
if not ret:
break
# 使用生成器发送JPEG数据
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + jpeg.tobytes() + b'\r\n')
@app.route('/video_feed')
def video_feed():
return Response(gen(), mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == '__main__':
app.run(debug=True)
# Flask应用程序的URL
url = 'http://127.0.0.1:5000/'
subprocess.Popen(['start', 'edge', url])