
睡意檢測是一項安全技術,可以防止駕駛員在駕駛中入睡而導致的事故,
目的是建立一個睡意檢測系統,該系統將檢測人的眼睛閉合幾秒鐘, 當檢測到困倦時,該系統將警告駕駛員,
睡意檢測版本1.0
睡眠檢測關鍵步驟
步驟1-從相機獲取影像作為輸入,
步驟2-檢測影像中的人臉并創建關注區域(ROI),
步驟3-從ROI中檢測眼睛并將其輸入分類器,
步驟4-分類器將對眼睛睜開還是閉眼進行分類,
步驟5-計算檢查該人是否困倦,
1.1睡眠檢測前期軟體配置
軟體1.OpenCV – pip安裝opencv-python (面部和眼睛檢測),
由于Tensorflow安裝到處采坑,我老老實實慢慢的確定版本號,
Windows 安裝OpenCV
- 1.準備版本號查詢
cmd->pip list
pycharm->File->setting->Project:檔案名->Project Interpreter->在左側Package找 python->對應Version即為版本號,
即環境 python版本為3.8 tensorflow版本為2.3.1 Windows系統為64,
-
2.確定你是否已經安裝了numpy,
-
3.opencv下載網站找對應python3.8版本下載.whl 檔案,
python3.8:opencv_python?4.4.0?cp38?cp38?win_amd64.whl
opencv下載網站:https://www.lfd.uci.edu/~gohlke/pythonlibs
- 4.將這個opencv_python?4.4.0?cp38?cp38?win_amd64.whl檔案復制到D:\根目錄下即可**
- 5.打開cmd,將路徑切換到D:,然后輸入:
pip install opencv_python?4.4.0?cp38?cp38?win_amd64.whl 回車
軟體2.TensorFlow – pip安裝tensorflow(keras使用TensorFlow作為后端),
軟體3.Keras – pip安裝keras(建立我們的分類模型),
軟體4.Pygame –點子安裝pygame(播放警報聲音),
1.2資料集
用于此模型的資料集由我們創建, 為了創建資料集,我們撰寫了一個腳本,可以捕獲相機的眼睛并將其存盤在本地磁盤, 我們將它們分成各自的標簽“打開”或’關閉’, 通過洗掉不需要的影像手動清除了資料,這對于構建模型不是必需的, 資料包括在不同的照明條件下,大約有7000張人眼影像,在資料集上訓練模型后,我們將最終權重和模型架構檔案“ models / cnnCat2.h5”,
現在,您可以使用此模型對人眼睜開或閉眼進行分類,
1.3模型架構
我們使用的模型是通過Keras使用卷積神經網路(CNN)構建的, 卷積神經網路是一種特殊的深度神經網路,在影像分類方面表現非常出色, CNN基本上由一個輸入層、一個輸出層和一個可以包含多個層的隱藏層組成, 使用在層和濾波器上執行2D矩陣乘法的濾波器對這些層執行卷積操作,
CNN模型架構包括以下幾層:
卷積層; 32個節點,內核大小為3
卷積層; 32個節點,內核大小為3
卷積層; 64個節點,內核大小3
全連接層; 128個節點
最后一層也是具有2個節點的完全連接的層, 在所有層,除了在輸出層中使用Relu激活功能,我們都使用Softmax,
2.Python專案執行駕駛員睡意檢測步驟
從zip下載Python專案源代碼,然后將檔案提取到系統中: Python Project Zip File
壓縮檔案的內容為:
“ haar級聯檔案”檔案夾包含從影像中檢測物件所需的xml檔案, 在我們的案例中,我們正在檢測人的臉部和眼睛,
models檔案夾包含我們的模型檔案“ cnnCat2.h5”,該檔案在卷積神經網路上進行了訓練,
我們有一個音頻剪輯“ alarm.wav”,當人昏昏欲睡時播放,
“ Model.py”檔案包含該程式,通過該程式,我們可以通過對資料集進行訓練來構建分類模型, 您可以在此檔案中看到卷積神經網路的實作,
“睡意檢測.py”是我們專案的主檔案, 要開始檢測程序,我們必須運行此檔案,
現在讓我們逐步了解我們的演算法,步驟1–將影像作為來自攝像機的輸入
使用網路攝像頭,我們將影像作為輸入, 因此,要訪問網路攝像頭,我們進行了無限回圈,將捕獲每個幀, 我們使用OpenCV提供的方法cv2.VideoCapture(0)訪問攝像機并設定捕獲物件(上限), cap.read()將讀取每一幀,然后將影像存盤在frame變數中,
3.在影像中檢測人臉并創建關注區域(ROI)
要檢測影像中的人臉,我們首先需要將影像轉換為灰度,因為用于物件檢測的OpenCV演算法在輸入中獲取了灰度影像, 我們不需要顏色資訊來檢測物體, 我們將使用haar級聯分類器來檢測人臉, 該行用于設定分類器face = cv2.CascadeClassifier(‘我們的haar級聯xml檔案的路徑’) , 然后,我們使用faces = face.detectMultiScale(gray)執行檢測, 它回傳帶有x,y坐標的檢測陣列,高度為物件邊界框的寬度, 現在我們可以遍歷這些面并為每個面繪制邊界框,
for (x,y,w,h) in faces:
cv2.rectangle(frame, (x,y), (x+w, y+h), (100,100,100), 1 )
4. 從ROI中檢測眼睛并將其輸入分類器
檢測臉部的相同程序也用于檢測眼睛, 首先,我們分別在leye和reye中為眼睛設定級聯分類器,然后使用left_eye = leye.detectMultiScale(gray)來檢測眼睛, 現在,我們只需要從完整影像中提取眼睛資料即可, 這可以通過提取眼睛的邊界框來實現,然后我們可以使用此代碼從幀中提取眼睛影像,
I_eye = frame[ y : y+h, x : x+w ]
l_eye僅包含眼睛的影像資料, 這將被輸入到我們的CNN分類器中,該分類器將預測眼睛是睜著還是閉著, 同樣,我們將右眼提取到r_eye中 ,
5.分類器將對眼睛睜開還是閉眼進行分類
我們正在使用CNN分類器來預測眼睛狀態, 要將影像輸入到模型中,我們需要執行某些操作,因為模型首先需要正確的尺寸, 首先,我們使用r_eye = cv2.cvtColor(r_eye,cv2.COLOR_BGR2GRAY)將彩色影像轉換為灰度,
然后,當我們的模型在24 * 24像素影像cv2.resize(r_eye,(24,24))上訓練時,我們將影像調整為24 * 24像素, 我們對資料進行歸一化以獲得更好的收斂性r_eye = r_eye / 255 (所有值將在0-1之間), 擴展尺寸以輸入到我們的分類器中, 我們使用model = load_model('models / cnnCat2.h5')加載了模型, 現在我們用模型預測每只眼睛
lpred = model.predict_classes(l_eye) 如果lpred [0]的值= 1,則表明眼睛是張開的;如果lpred [0]的值= 0,則表明眼睛是張開的,
6.計算分數以檢查人是否困倦
分數基本上是一個值,我們將使用該值來確定該人閉上眼睛多長時間, 因此,如果兩只眼睛都閉合,我們將繼續增加得分,而當眼睛睜開時,我們將降低得分, 我們正在使用cv2.putText()函式在螢屏上繪制結果,該函式將顯示人員的實時狀態,
cv2.putText(frame, “Open”, (10, height-20), font, 1, (255,255,255), 1, cv2.LINE_AA )
例如,如果得分變得大于15,則定義一個閾值,這意味著該人的眼睛長時間閉合, 這是當我們使用sound.play()發出警報聲,
7.程式源代碼
7.1分塊部分
import cv2
import os
from keras.models
import load_model
import numpy as np
from pygame import mixer
//匯入各個需要的庫
import time
mixer.init()
//匯入聲音提示部分
sound = mixer.Sound('alarm.wav')
face = cv2.CascadeClassifier('haar cascade files\haarcascade_frontalface_alt.xml')
leye = cv2.CascadeClassifier('haar cascade files\haarcascade_lefteye_2splits.xml')
reye = cv2.CascadeClassifier('haar cascade files\haarcascade_righteye_2splits.xml')
//檔案路徑錄入
lbl=['Close','Open']
model = load_model('models/cnncat2.h5')
path = os.getcwd()
cap = cv2.VideoCapture(0)
font = cv2.FONT_HERSHEY_COMPLEX_SMALL
count=0
score=0
thicc=2
rpred=[99]
lpred=[99]
//引數賦初值
while(True):
ret, frame = cap.read()
height,width = frame.shape[:2]
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face.detectMultiScale(gray,minNeighbors=5,scaleFactor=1.1,minSize=(25,25))
left_eye = leye.detectMultiScale(gray)
right_eye = reye.detectMultiScale(gray)
cv2.rectangle(frame, (0,height-50) , (200,height) , (0,0,0) , thickness=cv2.FILLED )
for (x,y,w,h) in faces:
cv2.rectangle(frame, (x,y) , (x+w,y+h) , (100,100,100) , 1 )
//彩色影像變灰色影像,ROI選取,影像基礎處理
for (x,y,w,h) in right_eye:
r_eye=frame[y:y+h,x:x+w]
count=count+1
r_eye = cv2.cvtColor(r_eye,cv2.COLOR_BGR2GRAY)
r_eye = cv2.resize(r_eye,(24,24))
r_eye= r_eye/255
r_eye= r_eye.reshape(24,24,-1)
r_eye = np.expand_dims(r_eye,axis=0)
rpred = model.predict_classes(r_eye)
if(rpred[0]==1):
lbl='Open'
if(rpred[0]==0):
lbl='Closed'
break
for (x,y,w,h) in left_eye:
l_eye=frame[y:y+h,x:x+w]
count=count+1
l_eye = cv2.cvtColor(l_eye,cv2.COLOR_BGR2GRAY)
l_eye = cv2.resize(l_eye,(24,24))
l_eye= l_eye/255
l_eye=l_eye.reshape(24,24,-1)
l_eye = np.expand_dims(l_eye,axis=0)
lpred = model.predict_classes(l_eye)
if(lpred[0]==1):
lbl='Open'
if(lpred[0]==0):
lbl='Closed'
break
//判斷左、右眼睜開閉合
if(rpred[0]==0 and lpred[0]==0):
score=score+1
cv2.putText(frame,"Closed",(10,height-20), font, 1,(255,255,255),1,cv2.LINE_AA)
# if(rpred[0]==1 or lpred[0]==1):
else:
score=score-1
cv2.putText(frame,"Open",(10,height-20), font, 1,(255,255,255),1,cv2.LINE_AA)
if(score<0):
score=0
cv2.putText(frame,'Score:'+str(score),(100,height-20), font, 1,(255,255,255),1,cv2.LINE_AA)
if(score>15):
#person is feeling sleepy so we beep the alarm
cv2.imwrite(os.path.join(path,'image.jpg'),frame)
//對影像打上標簽,表上分數
try:
sound.play()
//聲音警報
except: # isplaying = False
pass
if(thicc<16):
thicc= thicc+2
else:
thicc=thicc-2
if(thicc<2):
thicc=2
cv2.rectangle(frame,(0,0),(width,height),(0,0,255),thicc)
cv2.imshow('frame',frame)
//界面美觀處理
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
//銷毀視窗
7.2代碼細解
import cv2
//匯入cv2庫
import os
//匯入os庫
from keras.models
//匯入keras模型
import load_model
//匯入load
import numpy as np
//匯入numpy庫并賦予別名np
from pygame import mixer
//匯入pygame包中mixer函式
import time
//匯入庫time
mixer.init()
//初始化混音器
sound = mixer.Sound('alarm.wav')
//從檔案緩沖區物件創建新的sound物件
face = cv2.CascadeClassifier('haar cascade files\haarcascade_frontalface_alt.xml')
//檢測capture檔案是否在路徑下面
leye = cv2.CascadeClassifier('haar cascade files\haarcascade_lefteye_2splits.xml')
//檢測capture檔案是否在路徑下面
reye = cv2.CascadeClassifier('haar cascade files\haarcascade_righteye_2splits.xml')
//檢測capture檔案是否在路徑下面
lbl=['Close','Open']
//串列b包含兩個標簽
model = load_model('models/cnncat2.h5')
path = os.getcwd()
//回傳當前所在目錄路徑
cap = cv2.VideoCapture(0)
//獲得攝像頭
font = cv2.FONT_HERSHEY_COMPLEX_SMALL
//font=文本字體
count=0
score=0
thicc=2
rpred=[99]
lpred=[99]
while(True):
//開始回圈
ret, frame = cap.read()
//引數ret為T或F表示有沒有讀到圖片,frame表示截取到一幀的圖片
height,width = frame.shape[:2]
//每一幀圖片的長、寬賦值給heigh、weight
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
//將每一幀影像變為灰度影像
faces = face.detectMultiScale(gray,minNeighbors=5,scaleFactor=1.1,minSize=(25,25))
//灰度圖片minNeighbors-表示構成目標的相鄰矩陣的最小個數為5個 scaleFactor--表示在前后兩次相繼的掃描中,搜索視窗的比例系數,默認為1.1即每次搜索視窗依次擴大10% minsize:限制得到的目標區域的范圍為25到25
left_eye = leye.detectMultiScale(gray)
//檢測左人臉灰度圖片
right_eye = reye.detectMultiScale(gray)
//檢測右人臉灰度圖片
cv2.rectangle(frame, (0,height-50) , (200,height) , (0,0,0) , thickness=cv2.FILLED )
//對每一幀frame影像進行影像剪切,左上角坐標為(0,height-50) ,右下角坐標為(200,height)邊框顏色為(0,0,0),邊框填充整個矩形
for (x,y,w,h) in faces:
cv2.rectangle(frame, (x,y) , (x+w,y+h) , (100,100,100) , 1 )
//對每一幀frame影像進行影像剪切,左上角坐標為(x,y) ,右下角坐標為(x+w,y+h)邊框顏色為(100,100,100),邊框為1
for (x,y,w,h) in right_eye:
//進行判斷左眼是否睜開閉合
r_eye=frame[y:y+h,x:x+w]
// 提取眼睛的邊界框來實作,幀中提取左眼睛影像資料
count=count+1
r_eye = cv2.cvtColor(r_eye,cv2.COLOR_BGR2GRAY)
//將顏色轉換函式將r_eye圖片BGR圖片轉換為灰度圖片(單通道、八整型)
r_eye = cv2.resize(r_eye,(24,24))
//將影像尺寸變為24*24像素
r_eye= r_eye/255
//為了資料收斂性,將數值歸在0-1之間
r_eye= r_eye.reshape(24,24,-1)
//將r_eye的矩陣/陣列重組,以24行24串列示,
r_eye = np.expand_dims(r_eye,axis=0)
//這個資料在axis這個軸0位置就是在axis的那一個軸把資料加上去
rpred = model.predict_classes(r_eye)
//keras模型-樣本所屬類別標簽
if(rpred[0]==1):
//判斷是否睜眼閉眼
lbl='Open'
//睜眼
if(rpred[0]==0):
lbl='Closed'
//閉眼
break
//退出
for (x,y,w,h) in left_eye:
//進行判斷右眼是否睜開閉合
l_eye=frame[y:y+h,x:x+w]
// 提取眼睛的邊界框來實作,幀中提取左眼睛影像資料
count=count+1
l_eye = cv2.cvtColor(l_eye,cv2.COLOR_BGR2GRAY)
//將顏色轉換函式將r_eye圖片BGR圖片轉換為灰度圖片(單通道、八整型)
l_eye = cv2.resize(l_eye,(24,24))
//將影像尺寸變為24*24像素
l_eye= l_eye/255
//為了資料收斂性,將數值歸在0-1之間
l_eye=l_eye.reshape(24,24,-1)
//將l_eye的矩陣/陣列重組,以24行24串列示,
l_eye = np.expand_dims(l_eye,axis=0)
//這個資料在axis這個軸0位置就是在axis的那一個軸把資料加上去
lpred = model.predict_classes(l_eye)
//keras模型-樣本所屬類別標簽
if(lpred[0]==1):
//判斷是否睜眼閉眼
lbl='Open'
//睜眼
if(lpred[0]==0):
lbl='Closed'
//閉眼
break
if(rpred[0]==0 and lpred[0]==0):
score=score+1
cv2.putText(frame,"Closed",(10,height-20), font, 1,(255,255,255),1,cv2.LINE_AA)
//frame圖片打上closed標簽,帶上左上角數值為(10,height-20)的坐標,字體為font,字號為1字體顏色(255,255,255),字體粗細為1
else:
score=score-1
cv2.putText(frame,"Open",(10,height-20), font, 1,(255,255,255),1,cv2.LINE_AA)
//frame圖片列印上open標簽,帶上左上角數值為(10,height-20)的坐標,字體為font,字號為1顏色為(255,255,255),字體粗細為1
if(score<0):
score=0
cv2.putText(frame,'Score:'+str(score),(100,height-20), font, 1,(255,255,255),1,cv2.LINE_AA)
//frame圖片列印上'Score:'+str(score)標簽,帶上左上角數值為(100,height-20)的坐標,字體為font,字號為1顏色為(255,255,255),字體粗細為1
if(score>15):
cv2.imwrite(os.path.join(path,'image.jpg'),frame)
//將圖片保存并將path和image.jpg的路徑組合,圖片保存型別為frame幀
try:
sound.play()
//播放警告音樂
except: # isplaying = False
pass
if(thicc<16):
thicc= thicc+2
else:
thicc=thicc-2
if(thicc<2):
thicc=2
cv2.rectangle(frame,(0,0),(width,height),(0,0,255),thicc)
//frame影像以(0,0)為左上角(width,height)為右下角兩點rgb為(0,0,255)矩形厚度為thicc
cv2.imshow('frame',frame)
//輸出圖片
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
#需要放置在while回圈體外,釋放Camera,
cv2.destroyAllWindows()
#需要放置在while回圈體外,銷毀所有視窗,
8.源代碼語法決議補充
detectMultiScale函式引數:
引數1:image–待檢測圖片,一般為灰度影像加快檢測速度;
引數2:objects–被檢測物體的矩形框向量組;
引數3:scaleFactor–表示在前后兩次相繼的掃描中,搜索視窗的比例系數,默認為1.1即每次搜索視窗依次擴大10%;
引數4:minNeighbors–表示構成檢測目標的相鄰矩形的最小個數(默認為3個),
如果組成檢測目標的小矩形的個數和小于 min_neighbors - 1 都會被排除,
如果min_neighbors 為 0, 則函式不做任何操作就回傳所有的被檢候選矩形框,
這種設定值一般用在用戶自定義對檢測結果的組合程式上;
引數5:flags–要么使用默認值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果設定為
CV_HAAR_DO_CANNY_PRUNING,那么函式將會使用Canny邊緣檢測來排除邊緣過多或過少的區域,
因此這些區域通常不會是人臉所在區域;
引數6、7:minSize和maxSize用來限制得到的目標區域的范圍
os 模塊中常用的屬性和函式:
1.os.getcwd():查看當前所在目錄(路徑);
2.os.chdir():切換目錄(路徑);
3.os.curdir、os.pardir:回傳當前目錄字串名、回傳當前目錄的父目錄的字串名;
4.os.makedirs():生成一個多層遞回目錄
5.os.removedirs():若目錄為空,則洗掉,并遞回到上一級目錄,如若也為空,則洗掉,依次類推;
6.os.mkdir():創建一個目錄;
7.os.rmdir():洗掉一個目錄,若目錄不為空則無法洗掉,報錯;
8.os.listdir():顯示指定目錄下,所有的檔案和子目錄,包括隱藏檔案;
cv2.CascadeClassifier()函式:
CascadeClassifier,是Opencv中做人臉檢測的時候的一個級聯分類器,并且既可以使用Haar,也可以使用LBP特征,
Haar特征是一種反映影像的灰度變化的,像素分模塊求差值的一種特征,它分為三類:邊緣特征、線性特征、中心特征和對角線特征,用黑白兩種矩形框組合成特征模板,在特征模板內用 黑色矩形像素和 減去 白色矩形像素和來表示這個模版的特征值,例如:臉部的一些特征能由矩形模塊差值特征簡單的描述,如:眼睛要比臉頰顏色要深,鼻梁兩側比鼻梁顏色要深,嘴巴比周圍顏色要深等,但矩形特征只對一些簡單的圖形結構,如邊緣、線段較敏感,所以只能描述在特定方向(水平、垂直、對角)上有明顯像素模塊梯度變化的影像結構,這樣就可以進行區分人臉,
def getfacefromcamera(outdir):
createdir(outdir)
#獲取攝像頭
camera = cv2.VideoCapture(0)
#要檢測cascade檔案是否在路徑下,最后一般使用絕對路徑,
haar = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
n = 1
while 1:
if (n <= 200):
print('It`s processing %s image.' % n)
# 讀幀(從攝像頭當中讀取照片)
success, img = camera.read()
# 將圖片進行轉灰
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = haar.detectMultiScale(gray_img, 1.3, 5)
for f_x, f_y, f_w, f_h in faces:
face = img[f_y:f_y+f_h, f_x:f_x+f_w]
face = cv2.resize(face, (IMGSIZE, IMGSIZE))
#could deal with face to train
face = relight(face, random.uniform(0.5, 1.5), random.randint(-50, 50))
cv2.imwrite(os.path.join(outdir, str(n)+'.jpg'), face)
cv2.putText(img, 'haha', (f_x, f_y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 2) #顯示名字
img = cv2.rectangle(img, (f_x, f_y), (f_x + f_w, f_y + f_h), (255, 0, 0), 2)
n+=1
cv2.imshow('img', img)
key = cv2.waitKey(30) & 0xff
if key == 27:
break
else:
break
camera.release()
cv2.destroyAllWindows()
cv2.putText()
cv2.putText(img, str(i), (123,456), font, 2, (0,255,0), 3)
各引數依次是:圖片、添加的文字,左上角的坐標、字體、字體大小、顏色、字體粗細,
#img – 想要列印上文字的影像
#text – 想要列印的文字
#fontScale – 字號
#color – 顏色
#org – 文字的左下角坐標
#fontFace – 字體,可選的有:
FONT_HERSHEY_SIMPLEX,
FONT_HERSHEY_PLAIN, FONT_HERSHEY_DUPLEX,
FONT_HERSHEY_COMPLEX, FONT_HERSHEY_TRIPLEX,
以及 FONT_HERSHEY_SCRIPT_COMPLEX, 其中任意一種字體
都可加上 FONT_ITALIC 使其變為斜體
os.path,join()路徑拼接函式
join()函式
1. ‘sep’.join(seq)
引數:
sep:分隔符,可以為空
seq:要連接的元素序列、字串、元組、字典
上面的語法即:以sep作為分隔符,將seq所有的元素合并成一個新的字串
回傳值:回傳一個以分隔符sep連接各個元素后生成的字串
2.os.path.join()函式
語法: os.path.join(path1[,path2[,……]])
回傳值:將多個路徑組合后回傳
3.os.path.join()函式:連接兩個或更多的路徑名組件
如果各組件名首字母不包含’/’,則函式會自動加上
如果有一個組件是一個絕對路徑,則在它之前的所有組件均會被舍棄
如果最后一個組件為空,則生成的路徑以一個’/’分隔符結尾
注意:若出現”./”開頭的引數,會從”./”開頭的引數的上一個引數開始拼接
cv2.imwrite函式
cv2.imwrite(1.“圖片名字.格式”,2.Mat型別的影像資料,3.特定格式保存的引數編碼,默認值std::vector() 所以一般可以不寫,
pygame函式方法
pygame.mixer.Sound():播放音頻
| 方法 | 含義 |
|---|---|
| play() | 播放音頻 |
| stop() | 停止播放 |
| fadeout() | 淡出 |
| set_volume() | 設定音量 |
| get_volume() | 獲取音量 |
| get_num_channels() | 計算該音效播放了多少次 |
| get_length() | 獲得該音效的長度 |
| get_raw() | 將該音效以二進制格式的字串回傳 |
cv2.rectangle 引數含義
https://blog.csdn.net/sinat_41104353/article/details/85171185?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160437362219724836764895%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=160437362219724836764895&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v28-2-85171185.first_rank_ecpm_v3_pc_rank_v2&utm_term=cv2.rectangle&spm=1018.2118.3001.4449
本文借鑒網站:
https://blog.csdn.net/dfsgwe1231/article/details/105993294?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160370033719724822515506%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=160370033719724822515506&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v28-1-105993294.first_rank_ecpm_v3_pc_rank_v2&utm_term=%E7%9D%A1%E6%84%8F%E6%A3%80%E6%B5%8B&spm=1018.2118.3001.4187
由于該版本源代碼包無法下載 ,本人換了一個開源代碼,睡意檢測版本2.0開始
睡意檢測版本2.0
通過預測司機開車狀態來預防交通事故事故利用cnn和LSTMs檢測睡意的分類,使用維奧拉·瓊斯人臉檢測器進行人臉檢測后,我們進行跟蹤眼睛,這些資訊被輸入到一個預先訓練好的CNN序列然后將CNN提取的特征賦給LSTM檢測嗜睡,
睡眠檢測簡單思路
- 1.利用Haar Cascades和CamShift演算法,通過視頻中實時眼球跟蹤,建立司機睡意檢測模型,
- 2.使用CNN從最終池化層中提取的每個視頻幀的顯著特征作為連續幀的特征向量序列進行縫合,
- 3.這個序列(2048-D)作為長短期記憶(LSTM)遞推神經網路(RNN)的輸入,根據視頻序列預測司機的瞌睡,并在這種情況下發出警報,
- 4.通過Adam優化演算法優化網路權值,
1.1睡眠檢測前期軟體配置
- 軟體1:Python 2.7(本人用的3.8,python2與python3并不兼容,版本不同,代碼有微小區別)
- 軟體2:OpenCV 3.3.0, (本人用的4.4.0,與python對應版本)
- 軟體3:Tensorflow2.2.0
- 各種包: Keras, CNN, RNN, LSTM
1.2資料集
- 資料收集:
8名被試(男6名,女2名)模仿視頻警覺和困倦的跡象被記錄下來在環境記錄條件下,在錄音在這些視頻中,受試者被要求表演一些特定的動作模仿睡意的動作,如緩慢地閉上眼皮眼睛下垂,緊接著頭部姿勢迅速恢復模仿微睡眠,為了模仿警覺性,受試者被要求看不同的方向有/沒有頭運動, - 資料集:由16個訓練和3個測驗組成視頻,都包含類:Alert-Eyes和DrowsyEyes,視頻是用CMOS前置網路攝像頭錄制的
1280x720p,頻率30fps,閃爍減少50hz, - 人臉ROI檢測和眼睛檢測模塊:我們使用基于Viola-Jones haar特征的級聯分類器[6]用于人臉檢測,為了避免錯誤陽性,我們首先檢測到感興趣的面部區域(fROI)然后對該ROI進行眼檢測,得到a包含一雙眼睛的矩形區域貼片,后在第一幀中檢測人臉和眼睛,我們跟蹤他們使用CAMShift(連續自適應Mean-shift),下面的圖表顯示了關閉的檢測以及
睜開眼睛,
1.3模型結構
- 卷積神經網路(incep -v3)模塊我們手動創建一個影像資料集用于特征提取,用大約120幅影像制作了兩個類它們分別是醒眼和倦眼,提取重要從這些影像的視覺特征,我們使用卷積神經網路(CNNs),這是最先進的影像分類和特征提取,我們適應了預先訓練模型,v3[12],這是訓練包含1000個類的大型資料集Scale Visual Recognition Challenge(2012)[10],使用轉移學習程序中,我們重新訓練了這個模型的最后一層資料集與Tensorflow[11],完成4000個訓練步驟后,我們的模型驗證集的準確率達到了96.5%,
我們運行了每個視頻的每一幀(影像)建模并保存來自最終池化層的輸出(pool-3:0),這將得到一個2048維的向量特征,我們傳遞給順序神經模型,最后,我們將這些提取的特征轉化為序列提取的特征, - 長期記憶網路是一種特殊的記憶網路回圈神經網路,能夠長期學習依賴,同時避免消失和爆發梯度問題,每個塊遞回地包含一個或多個連接記憶細胞和三乘法單元,輸入,輸出和遺忘門,控制資訊在記憶體塊內部流動,
- LSTM框架支持預測(文本描述)用于視覺時間序列問題,在昏昏欲睡的驅動檢測,拼接特征(16個視頻x 26幀x1024個特征向量)用于訓練序列模型,我們使用了一個4096寬的LSTM層,然后厚層1024層,中間有一些空隙我們對模型進行了10個epoch的訓練,批量為4個,使用Keras和Tensorflow作為后端,我們使用[13]Adam優化器配置的學習率為0.00005訓練和優化我們的網路權值,下面的圖4顯示了我們的LSTM模型的體系結構,
2.Python專案執行駕駛員睡意檢測源代碼
源代碼網站:https://github.com/TejasNaikk/DriverDrowsiness_Detection
代碼報錯問題記錄
TabError: inconsistent use of tabs and spaces in indentation
問題原因:混用了Tab和4個空格造成的,要么全用Tab,要么全用4個空格,
解決方法:


SyntaxError:invalid syntax
問題原因:語法錯誤,
解決方法:
- 版本問題:python2與python3是不兼容的,python2 print無括號,python3 print有括號,
- 粗心問題:if,elif,else,for,while,class,def宣告末尾添加冒號( : ) 誤將=當作==使用,
- 縮進未對齊,混用了Tab和4個空格,
return SyntaxError: return outside function
問題原因:原因是return關鍵字只能在def自定義函式里面使用,在while回圈中只能使用break關鍵字來結束回圈!這里沒有自定義函式,所以不能出現return這樣的關鍵字
解決方法:j將return改成break或調整縮進將return調整到def中,
pycharm 中import 代碼塊 呈現灰色
問題:pycharm中單個py檔案匯入包時呈灰色,而別的檔案卻能正常顯示
解決辦法:
將滑鼠移動到那行代碼,點擊出現提示“Unused import statement”表示import宣告不可用,左邊同時出現黃色小燈泡,將滑鼠移動至黃色小燈泡那里,會出現向下箭頭,點擊箭頭出現下拉選單,繼續點擊第一條“Optimize imports”(切記要點擊的是最右邊的三角號,不是這一整行,否則會出錯),右面選擇第四個“Suppress for statement”,

解決效果:

train.py 檔案原始碼
rom keras.callbacks import TensorBoard, ModelCheckpoint, EarlyStopping, CSVLogger
from models import ResearchModels
from data import Dataset
import time
import os
import os.path
import numpy as np
def train(batch_size=4, nb_epoch=10):
checkpointer = ModelCheckpoint(
filepath=os.path.join('data', 'checkpoints', 'lstm' + '-' + 'features' + \
'.{epoch:03d}-{val_loss:.3f}.hdf5'),
verbose=1,
save_best_only=True)
tb = TensorBoard(log_dir=os.path.join('data', 'logs', 'lstm'))
early_stopper = EarlyStopping(patience=5)
timestamp = time.time()
csv_logger = CSVLogger(os.path.join('data', 'logs', 'lstm' + '-' + 'training-' + \
str(timestamp) + '.log'))
data = Dataset(
seq_length=26,
class_limit=2,
)
steps_per_epoch = 4
X, y = data.get_all_sequences_in_memory('training')
X_test, y_test = data.get_all_sequences_in_memory('testing')
rm = ResearchModels(len(data.classes),'lstm',data.seq_length, None)
print("##################################################")
X=np.ravel(X)
X=X.reshape(16,26,-1)
X_test=np.ravel(X_test)
X_test=X_test.reshape(3,26,-1)
#print "X", X[0:10]
print ("X.shape", X.shape)
print ("y.shape", y.shape)
print ("X_test.shape" ,X_test.shape)
print ("y_test.shape" ,y_test.shape)
print ("##################################################")
rm.model.fit(
X,
atch_size=batch_size,
validation_data=(X_test, y_test),
verbose=1,
callbacks=[tb, early_stopper, csv_logger],
epochs=nb_epoch);
rm.model.fit(
y,
atch_size=batch_size,
validation_data=(X_test, y_test),
verbose=1,
callbacks=[tb, early_stopper, csv_logger],
epochs=nb_epoch);
predictions = rm.model.predict(X_test)
loss,accuracy = rm.model.evaluate(X_test, y_test)
#print 'Loss:',loss*100,'%'
for j in predictions:
if j[0]>j[1]:
print ("Driver is alert with the confidence of",(j[0]*100),"%")
else:
print("Driver is drowsy with the confidence of",(j[1]*100),"%")
print("Sounding the alarm now....");
duration = 10# second
freq = 440# Hz
os.system('play --no-show-progress --null --channels 1 synth %s sine %f' % (duration, freq))
def main():
# model can be one of lstm, lrcn, mlp, conv_3d, c3d
batch_size = 4
nb_epoch = 10
# Chose images or features and image shape based on network.
train(batch_size=batch_size, nb_epoch=nb_epoch)
if __name__ == '__main__':
main()
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/232588.html
標籤:python
