方案二 :MediaPipe
運用MediaPipe的facemesh(人臉網格)計算眼睛縱橫比 (EAR)區分睜眼與閉眼,並設定閉眼後不間斷的時長以判斷學生狀況。
MediaPipe的facemesh(人臉網格)
MediaPipe 是 Google Research 所開發針對視覺的多媒體機器學習模型應用框架,其中facemesh是可以實時估計3D 面部特徵的模型。只需要一個攝像頭輸入,經由機器學習判斷人臉的表面和深度,再透過 468 個臉部標記畫出 3D 的人臉網格。
眼睛縱橫比(EAR)
眼睛縱橫比 (The Eye Aspect Ratio) 是在2016年的一篇《使用面部標記的實時眨眼測試》論文中被Soukupová 和 Čech所提出的指標,單以個人而言可以發現在張眼時縱向數值幾乎恆定不變,但在閉眼時分子數值幾乎為零,配合橫向眼距套用到每個人身上。
主要程式介紹
用Python版MediaPipe的facemesh(人臉網格)抓取12個眼眶特徵,將座標套入眼睛縱橫比 (EAR)公式,計算值和閾值的大小區分睜眼與閉眼,並設定閉眼後不間斷的時長以判斷學生狀況。
分稱三個程式檔介紹
- 主程式的定義
- 反映的聲音程式
- 主程式的執行和介面
主程式的定義
distance(…):
計算每隻眼睛的眼睛縱橫比。定義計算距離的函數:
distance
函數接收兩個參數point_1
和point_2
。使用zip()將point_1和point_2兩個點中相同位置的座標取出,接著對這些座標進行運算,計算兩個點之間的歐式距離。
回傳兩點間的歐式距離。
get_ear (…):
函數將.landmark屬性作為參數。每個索引位置,都有一個NormalizedLandmark對象。該對象保存規範化的x、y和z坐標值。
定義計算E.A.R的函數。
計算眼部六個特徵點之間的距離。
計算E.A.R。
回傳E.A.R及六個特徵點座標。
calculate_avg_ear(…):
測試 EAR 公式。將計算先前使用的圖像和另一張閉上眼睛的圖像的平均 EAR 值。定義函數
用
get_ear
函數,分別計算左右眼的 EAR 以及左右眼的特徵點坐標。計算左右眼的平均 EAR。
回傳計算出來的平均 EAR 以及左右眼特徵點的坐標。
get_mediapipe_app(…):
初始化 Mediapipe Face Mesh 解決方案對象。定義函數。
使用 Mediapipe 套件中的
FaceMesh
類別來建立物件。將傳入函式的參數設定給
FaceMesh
類別的建構子。回傳建立完成的
FaceMesh
物件。
plot_eye_landmarks(…):
此函數繪製檢測到的(和選擇的)眼睛標誌。定義函數。
對於左眼和右眼的特徵點座標,分別繪製圓圈。
將畫面水平翻轉,並回傳畫好特徵點的影像。
定義警示聲音程式
在audio_frame_callback 定義的函數中,在每個時間戳,都會收到一個具有一定長度、形狀、frame_rate、通道等的聲音幀。
假設輸入聲音幀長20 毫秒。現在有一個問題,因為我們的警報/聲音檔案可以持續很長時間。而且不能一次性發送整個警報聲。如果壓縮並傳送它,聲音將只是一小段噪音。
解決方法是將報警聲音檔案分割成20ms 長的片段。如果play_alarm標誌為True,則繼續將切碎的警報檔案段一個一個地返回,直到發送最後一個段。
在聲音幀準備就緒時,準備自定義聲音。它會將聲音幀轉換為聲音片段,並將聲音片段分成一個個固定時間的片段。
處理聲音幀,並根據
play_sound
參數決定是播放聲音還是將幀靜音。如果正在播放聲音,它會逐一播放片段,否則它會使幀靜音。
主程式的執行和介面
我們的介面設計了兩個可控項目,用滑桿的方式控制閾值和閉眼時⾧的判斷。
WAIT_TIME:
左側滑桿控制閉眼持續幾秒才算睡著,一開始的默認值為1秒,同學可以根據實際體驗修改時長(範圍:0-5秒,每0.25秒為單位。)
EAR_THRESH:
右側滑桿控制閾值,也就是眼睛縱橫比的比值,一開始的默認值為0.18秒,可以根據實際體驗修改眼距判斷(範圍:0-0.4,每0.01為單位。)
當主程式執行過程中,兩個滑桿的設定值會依照dict格式儲存並回傳。