卡車(chē)司機(jī)在白天和晚上長(zhǎng)途運(yùn)輸貨物和重物,他們經(jīng)常遭受睡眠不足的困擾。疲勞和困倦是高速公路上發(fā)生重大事故的一些主要原因。汽車(chē)行業(yè)正在研究一些可以檢測(cè)困倦并提醒駕駛員注意的技術(shù)。
在這個(gè)項(xiàng)目中,我們將使用 Raspberry Pi、OpenCV 和 Pi 攝像頭模塊為駕駛員構(gòu)建睡眠感應(yīng)和警報(bào)系統(tǒng)。該系統(tǒng)的基本目的是跟蹤駕駛員的面部狀況和眼球運(yùn)動(dòng),如果駕駛員感到困倦,則系統(tǒng)將觸發(fā)警告信息。這是我們之前人臉地標(biāo)檢測(cè)和人臉識(shí)別應(yīng)用的擴(kuò)展。
所需組件
硬件組件
樹(shù)莓派 3
Pi 相機(jī)模塊
微型 USB 數(shù)據(jù)線
蜂鳴器
軟件和在線服務(wù)
開(kāi)放式CV
數(shù)據(jù)庫(kù)
在繼續(xù)這個(gè) 驅(qū)動(dòng)程序嗜睡檢測(cè)項(xiàng)目之前, 首先我們需要在這個(gè)項(xiàng)目中安裝 OpenCV、imutils、dlib、Numpy 和一些其他依賴項(xiàng)。OpenCV在這里用于 數(shù)字圖像處理。數(shù)字圖像處理最常見(jiàn)的應(yīng)用是 物體檢測(cè)、 人臉識(shí)別和 人數(shù)統(tǒng)計(jì)。
這里我們只使用樹(shù)莓派、Pi Camera 和蜂鳴器來(lái)構(gòu)建這個(gè)睡眠檢測(cè)系統(tǒng)。
在樹(shù)莓派中安裝 OpenCV
在安裝 OpenCV 和其他依賴項(xiàng)之前,Raspberry Pi 需要完全更新。使用以下命令將 Raspberry Pi 更新到其最新版本:
?
sudo apt-get 更新
?
然后使用以下命令安裝在 Raspberry Pi 上安裝 OpenCV 所需的依賴項(xiàng)。
?
sudo apt-get install libhdf5-dev -y sudo apt-get install libhdf5-serial-dev –y sudo apt-get install libatlas-base-dev –y sudo apt-get install libjasper-dev -y sudo apt-get install libqtgui4 –y sudo apt-get install libqt4-test –y
?
最后,使用以下命令在 Raspberry Pi 上安裝 OpenCV。
?
pip3 安裝 opencv-contrib-python==4.1.0.25
?
安裝其他必需的軟件包
在對(duì) Raspberry Pi 進(jìn)行嗜睡檢測(cè)器編程之前,讓我們安裝其他所需的軟件包。
安裝 dlib:?dlib 是現(xiàn)代工具包,其中包含用于解決實(shí)際問(wèn)題的機(jī)器學(xué)習(xí)算法和工具。使用以下命令安裝 dlib。
?
pip3 安裝 dlib
?
安裝 NumPy:?NumPy 是科學(xué)計(jì)算的核心庫(kù),包含強(qiáng)大的 n 維數(shù)組對(duì)象,提供集成 C、C++ 等的工具。
?
pip3 安裝 numpy
?
安裝 face_recognition 模塊:該庫(kù)用于從 Python 或命令行識(shí)別和操作人臉。使用以下命令安裝人臉識(shí)別庫(kù)。
?
Pip3 安裝 face_recognition
?
最后,使用以下命令安裝eye_game庫(kù):
?
pip3 安裝眼睛游戲
?
對(duì)樹(shù)莓派進(jìn)行編程
使用 OpenCV 的 Driver Drrowsiness Detector的完整代碼在頁(yè)面末尾給出。在這里,我們將解釋代碼的一些重要部分,以便更好地理解。
因此,像往常一樣,通過(guò)包含所有必需的庫(kù)來(lái)啟動(dòng)代碼。
?
導(dǎo)入人臉識(shí)別 導(dǎo)入簡(jiǎn)歷2 將 numpy 導(dǎo)入為 np 進(jìn)口時(shí)間 導(dǎo)入簡(jiǎn)歷2 導(dǎo)入 RPi.GPIO 作為 GPIO 導(dǎo)入 eye_game
?
之后,創(chuàng)建一個(gè)實(shí)例以從 pi 相機(jī)獲取視頻源。如果您使用多個(gè)攝像頭,則在cv2.VideoCapture(0)函數(shù)中將零替換為一個(gè)。
?
video_capture = cv2.VideoCapture(0)
?
現(xiàn)在在接下來(lái)的幾行中,輸入文件的文件名和路徑。就我而言,代碼和文件都在同一個(gè)文件夾中。然后使用人臉編碼得到圖片中的人臉位置。
?
img_image = face_recognition.load_image_file("img.jpg") img_face_encoding = face_recognition.face_encodings(img_image)[0]
?
之后創(chuàng)建兩個(gè)數(shù)組來(lái)保存人臉及其名稱。我只使用一張圖片;您可以在代碼中添加更多圖像及其路徑。
?
known_face_encodings = [ img_face_encoding ] known_face_names = [ “阿什” ]
?
然后創(chuàng)建一些變量來(lái)存儲(chǔ)面部部位的位置、面部名稱和編碼。
?
face_locations = [] face_encodings = [] 面名 = [] process_this_frame = True
?
在while函數(shù)中,從流中捕獲視頻幀并將幀調(diào)整為更小的尺寸,并將捕獲的幀轉(zhuǎn)換為 RGB 顏色以進(jìn)行人臉識(shí)別。
?
ret, frame = video_capture.read() small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) rgb_small_frame = small_frame[:, :, ::-1]
?
之后,運(yùn)行人臉識(shí)別過(guò)程,將視頻中的人臉與圖像進(jìn)行比較。并獲得面部部位的位置。
?
如果 process_this_frame: face_locations = face_recognition.face_locations(rgb_small_frame) face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations) cv2.imwrite(文件,small_frame)
?
如果識(shí)別出的人臉與圖像中的人臉匹配,則調(diào)用eyegame函數(shù)跟蹤眼球運(yùn)動(dòng)。代碼會(huì)反復(fù)跟蹤眼球和眼球的位置。?
?
face_distances = face_recognition.face_distance(known_face_encodings, face_encoding) best_match_index = np.argmin(face_distances) 如果匹配[best_match_index]: 名稱 = known_face_names[best_match_index] 方向= eye_game.get_eyeball_direction(文件) 打?。ǚ较颍?/pre>?
如果代碼在 10 秒內(nèi)沒(méi)有檢測(cè)到任何眼球運(yùn)動(dòng),則會(huì)觸發(fā)警報(bào)將人叫醒。
?
別的: 計(jì)數(shù)=1+計(jì)數(shù) 打印(計(jì)數(shù)) 如果(計(jì)數(shù)>=10): GPIO.輸出(蜂鳴器,GPIO.HIGH) 時(shí)間.sleep(2) GPIO.輸出(蜂鳴器,GPIO.LOW) 打?。ā熬瘓?bào)!警報(bào)!檢測(cè)到駕駛員嗜睡”)?
然后使用 OpenCV 函數(shù)在面部周?chē)L制一個(gè)矩形并在其上放置文本。此外,使用cv2.imshow函數(shù)顯示視頻幀。
?
cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2) cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 255, 0), cv2.FILLED) 字體 = cv2.FONT_HERSHEY_DUPLEX cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (0, 0, 255), 1) cv2.imshow('視頻', 幀) 設(shè)置鍵“S”以停止代碼。 如果 cv2.waitKey(1) & 0xFF == ord('s'): 休息?
測(cè)試駕駛員困倦檢測(cè)系統(tǒng)
代碼準(zhǔn)備好后,將 Pi 攝像頭和蜂鳴器連接到Raspberry Pi并運(yùn)行代碼。大約 10 秒后,將出現(xiàn)一個(gè)窗口,其中包含來(lái)自您的 Raspberry Pi 相機(jī)的實(shí)時(shí)流。當(dāng)設(shè)備識(shí)別到人臉時(shí),它會(huì)在框架上打印你的名字并開(kāi)始跟蹤眼球運(yùn)動(dòng)?,F(xiàn)在閉上眼睛 7 到 8 秒來(lái)測(cè)試警報(bào)。當(dāng)計(jì)數(shù)超過(guò) 10 時(shí),它會(huì)觸發(fā)警報(bào),提醒您有關(guān)情況。
?導(dǎo)入人臉識(shí)別
導(dǎo)入簡(jiǎn)歷2
將 numpy 導(dǎo)入為 np
進(jìn)口時(shí)間
導(dǎo)入簡(jiǎn)歷2
導(dǎo)入 eye_game
導(dǎo)入 RPi.GPIO 作為 GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(假)
蜂鳴器= 23
GPIO.setup(蜂鳴器,GPIO.OUT)
以前的 =“未知”
計(jì)數(shù)=0
video_capture = cv2.VideoCapture(0)
#frame = (video_capture, 文件)
文件 = 'image_data/image.jpg'
# 加載示例圖片并學(xué)習(xí)如何識(shí)別它。
img_image = face_recognition.load_image_file("img.jpg")
img_face_encoding = face_recognition.face_encodings(img_image)[0]
# 創(chuàng)建已知人臉編碼及其名稱的數(shù)組
known_face_encodings = [
img_face_encoding
]
known_face_names = [
“阿什”
]
# 初始化一些變量
face_locations = []
face_encodings = []
面名 = []
process_this_frame = True
而真:
# 抓取單幀視頻
ret, frame = video_capture.read()
# 將視頻幀大小調(diào)整為 1/4 大小,以加快人臉識(shí)別處理
small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
# 將圖像從 BGR 顏色(OpenCV 使用)轉(zhuǎn)換為 RGB 顏色(face_recognition 使用)
rgb_small_frame = small_frame[:, :, ::-1]
# 只處理每隔一幀的視頻以節(jié)省時(shí)間
如果 process_this_frame:
# 查找當(dāng)前視頻幀中的所有人臉和人臉編碼
face_locations = face_recognition.face_locations(rgb_small_frame)
face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)
cv2.imwrite(文件,small_frame)
面名 = []
對(duì)于 face_encodings 中的 face_encoding:
# 查看人臉是否與已知人臉匹配
匹配 = face_recognition.compare_faces(known_face_encodings, face_encoding)
名稱=“未知”
face_distances = face_recognition.face_distance(known_face_encodings, face_encoding)
best_match_index = np.argmin(face_distances)
如果匹配[best_match_index]:
名稱 = known_face_names[best_match_index]
方向= eye_game.get_eyeball_direction(文件)
打?。ǚ较颍?br /> #eye_game.api.get_eyeball_direction(cv_image_array)
如果前一個(gè)!=方向:
上一個(gè)=方向
別的:
print("老一樣")
計(jì)數(shù)=1+計(jì)數(shù)
打?。ㄓ?jì)數(shù))
如果(計(jì)數(shù)>=10):
GPIO.輸出(蜂鳴器,GPIO.HIGH)
時(shí)間.sleep(2)
GPIO.輸出(蜂鳴器,GPIO.LOW)
打?。ā熬瘓?bào)!警報(bào)!檢測(cè)到駕駛員嗜睡”)
cv2.putText(frame, "睡意警報(bào)!", (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
face_names.append(名字)
process_this_frame = 不是 process_this_frame
# 顯示結(jié)果
對(duì)于(上、右、下、左),zip 中的名稱(face_locations,face_names):
# 縮放人臉位置,因?yàn)槲覀儥z測(cè)到的幀被縮放到 1/4 大小
頂部 *= 4
對(duì) *= 4
底部 *= 4
左 *= 4
# 在臉部周?chē)?huà)一個(gè)框
cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2)
# 在人臉下方繪制一個(gè)帶有名字的標(biāo)簽
cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
字體 = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (0, 0, 255), 1)
#cv2.putText(frame, frame_string, (left + 10, top - 10), font, 1.0, (255, 255, 255), 1)
# 顯示結(jié)果圖像
cv2.imshow('視頻', 幀)
# 按鍵盤(pán)上的“q”退出!
如果 cv2.waitKey(1) & 0xFF == ord('q'):
休息
# 釋放網(wǎng)絡(luò)攝像頭的句柄
video_capture.release()
cv2.destroyAllWindows()?
評(píng)論