# -*- coding: utf-8 -*-
import dlib # 人脸识别的库dlib
import cv2 # 图像处理的库OpenCv
import wx # 构造显示界面的GUI
import wx.xrc
import wx.adv
from scipy.spatial import distance as dist
from imutils import face_utils
import numpy as np # 数据处理的库 numpy
import time
import math
import pyttsx3
import pythoncom
from win32com import client
import sats2
COVER = 'E:/Fatigue_detect/images/ui8.png'
class Fatigue_detecting(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=title, pos=wx.DefaultPosition, size=wx.Size(925, 535),
style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
self.SetSizeHints(wx.DefaultSize, wx.DefaultSize)
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENU))
bSizer1 = wx.BoxSizer(wx.VERTICAL)
bSizer2 = wx.BoxSizer(wx.HORIZONTAL)
bSizer3 = wx.BoxSizer(wx.VERTICAL)
self.m_animCtrl1 = wx.adv.AnimationCtrl(self, wx.ID_ANY, wx.adv.NullAnimation, wx.DefaultPosition,
wx.DefaultSize, wx.adv.AC_DEFAULT_STYLE)
bSizer3.Add(self.m_animCtrl1, 1, wx.ALL | wx.EXPAND, 5)
bSizer2.Add(bSizer3, 9, wx.EXPAND, 5)
bSizer4 = wx.BoxSizer(wx.VERTICAL)
sbSizer1 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, u"参数设置"), wx.VERTICAL)
sbSizer2 = wx.StaticBoxSizer(wx.StaticBox(sbSizer1.GetStaticBox(), wx.ID_ANY, u"基础操作"), wx.VERTICAL)
gSizer1 = wx.GridSizer(0, 2, 0, 8)
self.m_choice1 = wx.Button(sbSizer2.GetStaticBox(), wx.ID_ANY, u"加载车载摄像头", wx.DefaultPosition, wx.Size(120, 60),
0)
gSizer1.Add(self.m_choice1, 0, wx.ALL, 5)
self.camera_button1 = wx.Button(sbSizer2.GetStaticBox(), wx.ID_ANY, u"开始检测", wx.DefaultPosition,
wx.Size(120, 60), 0)
gSizer1.Add(self.camera_button1, 0, wx.ALL, 5)
self.off_button3 = wx.Button(sbSizer2.GetStaticBox(), wx.ID_ANY, u"暂停", wx.DefaultPosition, wx.Size(120, 60), 0)
gSizer1.Add(self.off_button3, 0, wx.ALL, 5)
self.off_button4 = wx.Button(sbSizer2.GetStaticBox(), wx.ID_ANY, u"退出检测", wx.DefaultPosition, wx.Size(120, 60),
0)
gSizer1.Add(self.off_button4, 0, wx.ALL, 5)
sbSizer2.Add(gSizer1, 1, wx.EXPAND, 5)
sbSizer1.Add(sbSizer2, 2, wx.EXPAND, 5)
sbSizer6 = wx.StaticBoxSizer(wx.StaticBox(sbSizer1.GetStaticBox(), wx.ID_ANY, u"状态输出"), wx.VERTICAL)
self.m_textCtrl3 = wx.TextCtrl(sbSizer6.GetStaticBox(), wx.ID_ANY, wx.EmptyString, wx.DefaultPosition,
wx.DefaultSize, wx.TE_MULTILINE | wx.TE_READONLY)
sbSizer6.Add(self.m_textCtrl3, 1, wx.ALL | wx.EXPAND, 5)
sbSizer1.Add(sbSizer6, 5, wx.EXPAND, 5)
bSizer4.Add(sbSizer1, 1, wx.EXPAND, 5)
bSizer2.Add(bSizer4, 3, wx.EXPAND, 5)
bSizer1.Add(bSizer2, 1, wx.EXPAND, 5)
self.SetSizer(bSizer1)
self.Layout()
self.Centre(wx.BOTH)
# Connect Events
self.m_choice1.Bind(wx.EVT_BUTTON, self.prepare)
self.camera_button1.Bind(wx.EVT_BUTTON, self.camera_on) # 开
self.off_button3.Bind(wx.EVT_BUTTON, self.off) # 关
self.off_button4.Bind(wx.EVT_BUTTON, self.exit)
# 封面图片
self.image_cover = wx.Image(COVER, wx.BITMAP_TYPE_ANY)
# 显示图片在m_animCtrl1上
self.bmp = wx.StaticBitmap(self.m_animCtrl1, -1, wx.Bitmap(self.image_cover))
# 设置窗口标题的图标
self.icon = wx.Icon('E:/Fatigue_detect/images/555.ico', wx.BITMAP_TYPE_ICO)
self.SetIcon(self.icon)
# 系统事件
self.Bind(wx.EVT_CLOSE, self.OnClose)
"""参数"""
# 默认为摄像头0
self.VIDEO_STREAM = 0
self.CAMERA_STYLE = False # False未打开摄像头,True摄像头已打开
self.AR_CONSEC_FRAMES_check = 3
self.OUT_AR_CONSEC_FRAMES_check = 5
# 闪烁阈值(秒)
# 眼睛长宽比
self.EYE_AR_THRESH = 0.2
self.EYE_AR_CONSEC_FRAMES = 3
# 打哈欠长宽比
self.MAR_THRESH = 0.5
self.MOUTH_AR_CONSEC_FRAMES = 3
# 瞌睡点头
self.HAR_THRESH = 0.3
self.NOD_AR_CONSEC_FRAMES = 5
"""计数"""
# 初始化帧计数器和眨眼总数
self.COUNTER = 0
self.TOTAL = 0
# 初始化帧计数器和打哈欠总数
self.mCOUNTER = 0
self.mTOTAL = 0
# 初始化帧计数器和点头总数
self.hCOUNTER = 0
self.hTOTAL = 0
# 离职时间长度
self.oCOUNTER = 0
# 初始化眨眼频率,点头频率,打哈欠频率
self.frequency = 0
self.hfrequency = 0
self.yfrequency = 0
# 初始化疲劳程度
self.score = 0
"""姿态"""
# 世界坐标系(UVW):填写3D参考点,该模型参考http://aifi.isr.uc.pt/Downloads/OpenGL/glAnthropometric3DModel.cpp
self.object_pts = np.float32([[6.825897, 6.760612, 4.402142], # 33左眉左上角
[1.330353, 7.122144, 6.903745], # 29左眉右角
[-1.330353, 7.122144, 6.903745], # 34右眉左角
[-6.825897, 6.760612, 4.402142], # 38右眉右上角
[5.311432, 5.485328, 3.987654], # 13左眼左上角
[1.789930, 5.393625, 4.413414], # 17左眼右上角
[-1.789930, 5.393625, 4.413414], # 25右眼左上角
[-5.311432, 5.485328, 3.987654], # 21右眼右上角
[2.005628, 1.409845, 6.165652], # 55鼻子左上角
[-2.005628, 1.409845, 6.165652], # 49鼻子右上角
[2.774015, -2.080775, 5.048531], # 43嘴左上角
[-2.774015, -2.080775, 5.048531], # 39嘴右上角
[0.000000, -3.116408, 6.097667], # 45嘴中央下角
[0.000000, -7.415691, 4.070434]]) # 6下巴角
# 相机坐标系(XYZ):添加相机内参
self.K = [6.5308391993466671e+002, 0.0, 3.1950000000000000e+002,
0.0, 6.5308391993466671e+002, 2.3950000000000000e+002,
0.0, 0.0, 1.0] # 等价于矩阵[fx, 0, cx; 0, fy, cy; 0, 0, 1]
# 图像中心坐标系(uv):相机畸变参数[k1, k2, p1, p2, k3]
self.D = [7.0834633684407095e-002, 6.9140193737175351e-002, 0.0, 0.0, -1.3073460323689292e+000]
# 像素坐标系(xy):填写凸轮的本征和畸变系数
self.cam_matrix = np.array(self.K).reshape(3, 3).astype(np.float32)
self.dist_coeffs = np.array(self.D).reshape(5, 1).astype(np.float32)
# 重新投影3D点的世界坐标轴以验证结果姿势
self.reprojectsrc = np.float32([[10.0, 10.0, 10.0],
[10.0, 10.0, -10.0],
[10.0, -10.0, -10.0],
[10.0, -10.0, 10.0],
[-10.0, 10.0, 10.0],
[-10.0, 10.0, -10.0],
[-10.0, -10.0, -10.0],
[-10.0, -10.0, 10.0]])
# 绘制正方体12轴
self.line_pairs = [[0, 1], [1, 2], [2, 3], [3, 0],
[4, 5], [5, 6], [6, 7], [7, 4],
[0, 4], [1, 5], [2, 6], [3, 7]]
def __del__(self):
pass
def get_head_pose(self, shape): # 头部姿态估计