基于Dlib模型实现驾驶员疲劳检测项目

Dlib系列文章目录


文章目录

  • Dlib系列文章目录
  • 前言
  • 一、背景
    • 环境:
    • 技术:
  • 二、使用步骤
    • 1.环境搭建
      • opencv3.4.1
      • dlib人脸识别库
      • wxFromBuilder可视化界面
        • 新建画布:
        • 布局设置:
        • 添加控件:
        • 对齐规则:
        • 右侧设置属性(Properties):
        • 点击事件:
        • 导出设计界面:
        • wxpython加载界面:(添加封面图和图标)
    • 2.检测原理
        • wxpython主要控件
  • 总结


前言

经查阅相关文献,疲劳在人体面部表情中表现出大致三个类型:打哈欠(嘴巴张大且相对较长时间保持这一状态)、眨眼(或眼睛微闭,此时眨眼次数增多,且眨眼速度变慢)、点头(瞌睡点头)。本实验从人脸朝向、位置、瞳孔朝向、眼睛开合度、眨眼频率、瞳孔收缩率等数据入手,并通过这些数据,实时地计算出驾驶员的注意力集中程度,分析驾驶员是否疲劳驾驶和及时作出安全提示。


一、背景

环境:

Win10、Python3.7、anaconda3、JupyterNotebook、wxFromBuilder

技术:

Opencv:图像处理
Dlib:一个很经典的用于图像处理的开源库,shape_predictor_68_face_landmarks.dat是一个用于人脸68个关键点检测的dat模型库,使用这个模型库可以很方便地进行人脸检测,并进行简单的应用。
Numpy:基于Python的n维数值计算扩展。
Imutils :一系列使得opencv 便利的功能,包括图像旋转、缩放、平移,骨架化、边缘检测、显示
matplotlib 图像(imutils.opencv2matplotlib(image)。
wx: 可视化UI界面

import dlib                     # 人脸识别的库dlib(单独安装)
import numpy as np              # 数据处理的库numpy
import cv2                      # 图像处理的库OpenCv
import wx                       # 构造显示界面的GUI
import wx.xrc
import wx.adv
# import the necessary packages
from scipy.spatial import distance as dist
from imutils.video import FileVideoStream
from imutils.video import VideoStream
from imutils import face_utils
import numpy as np # 数据处理的库 numpy
import argparse
import imutils
import datetime,time
import math
import os

二、使用步骤

1.环境搭建

安装配置环境:anaconda3、JupyterNotebook,搭建opencv和dlib环境

opencv3.4.1

dlib人脸识别库

wxFromBuilder可视化界面

安装包
这是可视化拖拽控件,使用步骤:

新建画布:

先选择forms里面的Frame,开始的时候必须用这个,其他控件都是在里面。
![在这里插入图片描述](https://img-blog.csdnimg.cn/f04bdc1b678449179e674b77f63332fd.png

布局设置:

在Layout里面选择一个布局。布局就是用来将Frame分成单独的小方格。各种布局都不一样,有的是只有行没有列,有的是行列都可以。根据需要添加即可。
基于Dlib模型实现驾驶员疲劳检测项目_第1张图片

添加控件:

在common里面选择基础的按钮等控件。在这里很难控制好位置,因为只有选定好了在哪个方格里,添加的时候才能添加。添加后的位置不好变化。所以,必须先设计好正规布局,然后再往里面添加小控件。
基于Dlib模型实现驾驶员疲劳检测项目_第2张图片

对齐规则:

如果不满意都是在左侧,可以在上面中选择是居中还是左对齐。(填充,边框等)
在这里插入图片描述
可以在语言栏中点击查看:python代码
基于Dlib模型实现驾驶员疲劳检测项目_第3张图片

右侧设置属性(Properties):

名称,相对位置等;
基于Dlib模型实现驾驶员疲劳检测项目_第4张图片

点击事件:

填写事件函数名
基于Dlib模型实现驾驶员疲劳检测项目_第5张图片
python自动生成函数:
基于Dlib模型实现驾驶员疲劳检测项目_第6张图片

导出设计界面:

选中MyProject2:Project,在属性(Properties)中代码规则(code_generation)勾选上python
基于Dlib模型实现驾驶员疲劳检测项目_第7张图片
键盘按F8,项目同目录下自动生成noname.py界面
在这里插入图片描述
综上,本次UI界面设计:
基于Dlib模型实现驾驶员疲劳检测项目_第8张图片

wxpython加载界面:(添加封面图和图标)

基于Dlib模型实现驾驶员疲劳检测项目_第9张图片
在python中显示,需要初始化加载画布即可:

self.frame = Fatigue_detecting(parent=None,title="Fatigue Demo")
self.frame.Show(True)

完整界面

# -*- coding: utf-8 -*- 
import wx                       # 构造显示界面的GUI
import wx.xrc
import wx.adv

###########################################################################
## Class Fatigue_detecting
###########################################################################

COVER = 'D:/myworkspace/JupyterNotebook/fatigue_detecting/images/camera.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( 873,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 )
        m_choice1Choices = [ u"摄像头ID_0", u"摄像头ID_1", u"摄像头ID_2" ]
        self.m_choice1 = wx.Choice( sbSizer2.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.Size( 90,25 ), m_choice1Choices, 0 )
        self.m_choice1.SetSelection( 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( 90,25 ), 0 )
        gSizer1.Add( self.camera_button1, 0, wx.ALL, 5 )
        self.vedio_button2 = wx.Button( sbSizer2.GetStaticBox(), wx.ID_ANY, u"打开视频文件", wx.DefaultPosition, wx.Size( 90,25 ), 0 )
        gSizer1.Add( self.vedio_button2, 0, wx.ALL, 5 )

        self.off_button3 = wx.Button( sbSizer2.GetStaticBox(), wx.ID_ANY, u"暂停", wx.DefaultPosition, wx.Size( 90,25 ), 0 )
        gSizer1.Add( self.off_button3, 0, wx.ALL, 5 )
        sbSizer2.Add( gSizer1, 1, wx.EXPAND, 5 )
        sbSizer1.Add( sbSizer2, 2, wx.EXPAND, 5 )
        sbSizer3 = wx.StaticBoxSizer( wx.StaticBox( sbSizer1.GetStaticBox(), wx.ID_ANY, u"疲劳检测" ), wx.VERTICAL )
        bSizer5 = wx.BoxSizer( wx.HORIZONTAL )
        self.yawn_checkBox1 = wx.CheckBox( sbSizer3.GetStaticBox(), wx.ID_ANY, u"打哈欠检测", wx.Point( -1,-1 ), wx.Size( -1,15 ), 0 )
        self.yawn_checkBox1.SetValue(True) 
        bSizer5.Add( self.yawn_checkBox1, 0, wx.ALL, 5 )
        self.blink_checkBox2 = wx.CheckBox( sbSizer3.GetStaticBox(), wx.ID_ANY, u"闭眼检测", wx.Point( -1,-1 ), wx.Size( -1,15 ), 0 )
        self.blink_checkBox2.SetValue(True) 
        bSizer5.Add( self.blink_checkBox2, 0, wx.ALL, 5 )
        sbSizer3.Add( bSizer5, 1, wx.EXPAND, 5 )
        bSizer6 = wx.BoxSizer( wx.HORIZONTAL )
        self.nod_checkBox7 = wx.CheckBox( sbSizer3.GetStaticBox(), wx.ID_ANY, u"点头检测", wx.Point( -1,-1 ), wx.Size( -1,15 ), 0 )
        self.nod_checkBox7.SetValue(True) 
        bSizer6.Add( self.nod_checkBox7, 0, wx.ALL, 5 )
        self.m_staticText1 = wx.StaticText( sbSizer3.GetStaticBox(), wx.ID_ANY, u"疲劳时间(秒):", wx.DefaultPosition, wx.Size( -1,15 ), 0 )
        self.m_staticText1.Wrap( -1 )
        bSizer6.Add( self.m_staticText1, 0, wx.ALL, 5 )
        m_listBox2Choices = [ u"3", u"4", u"5", u"6", u"7", u"8" ]
        self.m_listBox2 = wx.ListBox( sbSizer3.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.Size( 50,24 ), m_listBox2Choices, 0 )
        bSizer6.Add( self.m_listBox2, 0, 0, 5 )
        sbSizer3.Add( bSizer6, 1, wx.EXPAND, 5 )
        sbSizer1.Add( sbSizer3, 2, 0, 5 )
        sbSizer4 = wx.StaticBoxSizer( wx.StaticBox( sbSizer1.GetStaticBox(), wx.ID_ANY, u"脱岗检测" ), wx.VERTICAL )
        bSizer8 = wx.BoxSizer( wx.HORIZONTAL )
        self.m_checkBox4 = wx.CheckBox( sbSizer4.GetStaticBox(), wx.ID_ANY, u"脱岗检测", wx.DefaultPosition, wx.Size( -1,15 ), 0 )
        self.m_checkBox4.SetValue(True) 
        bSizer8.Add( self.m_checkBox4, 0, wx.ALL, 5 )
        self.m_staticText2 = wx.StaticText( sbSizer4.GetStaticBox(), wx.ID_ANY, u"脱岗时间(秒):", wx.DefaultPosition, wx.Size( -1,15 ), 0 )
        self.m_staticText2.Wrap( -1 )
        bSizer8.Add( self.m_staticText2, 0, wx.ALL, 5 )
        m_listBox21Choices = [ u"5", u"10", u"15", u"20", u"25", u"30" ]
        self.m_listBox21 = wx.ListBox( sbSizer4.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.Size( 50,24 ), m_listBox21Choices, 0 )
        bSizer8.Add( self.m_listBox21, 0, 0, 5 )
        sbSizer4.Add( bSizer8, 1, 0, 5 )
        sbSizer1.Add( sbSizer4, 1, 0, 5 )
        sbSizer5 = wx.StaticBoxSizer( wx.StaticBox( sbSizer1.GetStaticBox(), wx.ID_ANY, u"分析区域" ), wx.VERTICAL )
        bSizer9 = wx.BoxSizer( wx.HORIZONTAL )
        self.m_staticText3 = wx.StaticText( sbSizer5.GetStaticBox(), wx.ID_ANY, u"检测区域:   ", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText3.Wrap( -1 )
        bSizer9.Add( self.m_staticText3, 0, wx.ALL, 5 )
        m_choice2Choices = [ u"全视频检测", u"部分区域选取" ]
        self.m_choice2 = wx.Choice( sbSizer5.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_choice2Choices, 0 )
        self.m_choice2.SetSelection( 0 )
        bSizer9.Add( self.m_choice2, 0, wx.ALL, 5 )
        sbSizer5.Add( bSizer9, 1, wx.EXPAND, 5 )
        sbSizer1.Add( sbSizer5, 1, 0, 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 )
        
        # 封面图片
        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('./images/123.ico', wx.BITMAP_TYPE_ICO)
        self.SetIcon(self.icon)
        print("wxpython界面初始化加载完成!")
            
class main_app(wx.App):
    """
     在OnInit() 里边申请Frame类,这样能保证一定是在app后调用,
     这个函数是app执行完自己的__init__函数后就会执行
    """
    # OnInit 方法在主事件循环开始前被wxPython系统调用,是wxpython独有的
    def OnInit(self):
        self.frame = Fatigue_detecting(parent=None,title="Fatigue Demo")
        self.frame.Show(True)
        return True   

    
if __name__ == "__main__":
    app = main_app()
    app.MainLoop()

2.检测原理

下载开源数据集:
shape_predictor_68_face_landmarks.dat

官方下载地址:https://pypi.org/simple/dlib/
码云下载:https://gitee.com/cungudafa/fatigue_detecting/tree/master/model
基于图像驾驶员疲劳检测技术研究 ,更多参考:

Dlib模型之驾驶员疲劳检测系列(眨眼、打哈欠、瞌睡点头、可视化界面)

眨眼 https://blog.csdn.net/cungudafa/article/details/103477960
打哈欠 https://blog.csdn.net/cungudafa/article/details/103496881
瞌睡点头 https://blog.csdn.net/cungudafa/article/details/103499230

标准参数说明

疲劳认定标准:

眨眼:连续3帧内,眼睛长宽比为 0.2
打哈欠:连续3帧内,嘴部长宽比为 0.5
瞌睡点头:连续3帧内,pitch(x)旋转角为 0.3

wxpython主要控件

下拉选择框,按钮,复选框,文本框,视频界面
基于Dlib模型实现驾驶员疲劳检测项目_第10张图片
wxpython主要控件监听事件self.m_choice1.Bind(event):

    # Connect Events
    self.m_choice1.Bind( wx.EVT_CHOICE, self.cameraid_choice )#绑定事件
    self.camera_button1.Bind( wx.EVT_BUTTON, self.camera_on )#开
    self.vedio_button2.Bind( wx.EVT_BUTTON, self.vedio_on )
    self.off_button3.Bind( wx.EVT_BUTTON, self.off )#关

    self.m_listBox2.Bind( wx.EVT_LISTBOX, self.AR_CONSEC_FRAMES )# 闪烁阈值设置
    self.m_listBox21.Bind( wx.EVT_LISTBOX, self.OUT_AR_CONSEC_FRAMES )# 脱岗时间设置

基于Dlib模型实现驾驶员疲劳检测项目_第11张图片
(3.1)选择

event.GetString()获取选择内容,
并写入文本框self.m_textCtrl3.AppendText()
把值传给全局变量(在def __init__( ):中定义的self.VIDEO_STREAM = 0)
	 def cameraid_choice( self, event ):
        # 摄像头编号
        cameraid = int(event.GetString()[-1])# 截取最后一个字符
        if cameraid == 0:
            self.m_textCtrl3.AppendText(u"准备打开本地摄像头!!!\n")
        if cameraid == 1 or cameraid == 2:
            self.m_textCtrl3.AppendText(u"准备打开外置摄像头!!!\n")
        self.VIDEO_STREAM = cameraid
        
	def AR_CONSEC_FRAMES( self, event ):
        self.m_textCtrl3.AppendText(u"设置疲劳间隔为:\t"+event.GetString()+"秒\n")
        self.AR_CONSEC_FRAMES_check = int(event.GetString())
        
    def OUT_AR_CONSEC_FRAMES( self, event ):
        self.m_textCtrl3.AppendText(u"设置脱岗间隔为:\t"+event.GetString()+"秒\n")
        self.OUT_AR_CONSEC_FRAMES_check = int(event.GetString())

选择本地摄像头,或外接摄像头设备:
基于Dlib模型实现驾驶员疲劳检测项目_第12张图片修改检测时间参数:
基于Dlib模型实现驾驶员疲劳检测项目_第13张图片
(3.2)打开本地视频

def vedio_on( self, event ):  
        # 选择文件夹对话框窗口
        dialog = wx.FileDialog(self,u"选择视频检测",os.getcwd(),'',wildcard="(*.mp4)|*.mp4",style=wx.FD_OPEN | wx.FD_CHANGE_DIR)
        if dialog.ShowModal() == wx.ID_OK:
            #如果确定了选择的文件夹,将文件夹路径写到m_textCtrl3控件
            self.m_textCtrl3.SetValue(u"文件路径:"+dialog.GetPath()+"\n")
            self.VIDEO_STREAM = str(dialog.GetPath())# 更新全局变量路径
            dialog.Destroy    

基于Dlib模型实现驾驶员疲劳检测项目_第14张图片
(3.3)opencv图转wxpython图像opencv显示视频流是imshow:

总结

例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

https://blog.csdn.net/cungudafa/article/details/103712875
dlib安装参考

你可能感兴趣的:(dlib人脸检测项目,深度学习,自动驾驶,python,pandas)