<var id="fnfpo"><source id="fnfpo"></source></var>
<rp id="fnfpo"></rp>

<em id="fnfpo"><object id="fnfpo"><input id="fnfpo"></input></object></em>
<em id="fnfpo"><acronym id="fnfpo"></acronym></em>
  • <th id="fnfpo"><track id="fnfpo"></track></th>
  • <progress id="fnfpo"><track id="fnfpo"></track></progress>
  • <tbody id="fnfpo"><pre id="fnfpo"></pre></tbody>

  • x
    x

    如何用OpenCV進行人臉疲勞檢測--基于米爾瑞芯微RK3576開發板

    發布時間:2024-12-19 11:37    發布者:swiftman
    關鍵詞: 瑞芯微 , RK3576 , 嵌入式 , OpenCV , 米爾電子 , OpenCV
    本篇源自:優秀創作者 lulugl

    本文將介紹基于米爾電子MYD-LR3576開發板(米爾基于瑞芯微 RK3576開發板)的人臉疲勞檢測方案測試。
    米爾基于RK3576核心板/開發板
    【前言】
    人臉疲勞檢測:一種通過分析人臉特征來判斷一個人是否處于疲勞狀態的技術。其原理主要基于計算機視覺和機器學習方法。當人疲勞時,面部會出現一些特征變化,如眼睛閉合程度增加、眨眼頻率變慢、打哈欠、頭部姿態改變等。
    例如,通過檢測眼睛的狀態來判斷疲勞程度是一個關鍵部分。正常情況下,人的眨眼頻率相對穩定,而當疲勞時,眨眼頻率會降低,并且每次眨眼時眼睛閉合的時間可能會延長。同時,頭部可能會不自覺地下垂或者搖晃,這些特征都可以作為疲勞檢測的依據。米爾MYC-LR3576采用8核CPU+搭載6 TOPS的NPU加速器,3D GPU,能夠非常輕松的實現這個功能,下面就如何實現這一功能分享如下:
    【硬件】
    1、米爾MYC-LR3576開發板
    2、USB攝像頭
    【軟件】
    1、v4l2
    2、openCV
    3、dlib庫:dlib 是一個現代化的 C++ 工具包,它包含了許多用于機器學習、圖像處理、數值計算等多種任務的算法和工具。它的設計目標是提供高性能、易于使用的庫,并且在開源社區中被廣泛應用。
    【實現步驟】
    1、安裝python-opencv
    2、安裝dlib庫
    3、安裝v4l2庫
    代碼實現】
    1、引入cv2、dlib以及線程等:
    1. import cv2
    2. import dlib
    3. import numpy as np
    4. import time
    5. from concurrent.futures import ThreadPoolExecutor
    6. import threading
    復制代碼

    2、初始化dlib的面部檢測器和特征點預測器
    1. detector = dlib.get_frontal_face_detector()
    2. predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
    復制代碼

    3、定義計算眼睛縱橫比的函數
    1. def eye_aspect_ratio(eye):
    2.     A = np.linalg.norm(np.array(eye[1]) - np.array(eye[5]))
    3.     B = np.linalg.norm(np.array(eye[2]) - np.array(eye[4]))
    4.     C = np.linalg.norm(np.array(eye[0]) - np.array(eye[3]))
    5.     ear = (A + B) / (2.0 * C)                                                                                
    6.     return ear
    復制代碼

    4、定義計算頭部姿勢的函數
    1. def get_head_pose(shape):
    2.     # 定義面部特征點的三維坐標
    3.     object_points = np.array([
    4.         (0.0, 0.0, 0.0),             # 鼻尖
    5.         (0.0, -330.0, -65.0),        # 下巴
    6.         (-225.0, 170.0, -135.0),     # 左眼左眼角
    7.         (225.0, 170.0, -135.0),      # 右眼右眼角
    8.         (-150.0, -150.0, -125.0),    # 左嘴角
    9.         (150.0, -150.0, -125.0)      # 右嘴角
    10.     ], dtype=np.float32)

    11.     image_pts = np.float32([shape[i] for i in [30, 8, 36, 45, 48, 54]])
    12.     size = frame.shape
    13.     focal_length = size[1]
    14.     center = (size[1] // 2, size[0] // 2)
    15.     camera_matrix = np.array(
    16.         [[focal_length, 0, center[0]],
    17.          [0, focal_length, center[1]],
    18.          [0, 0, 1]], dtype="double"
    19.     )

    20.     dist_coeffs = np.zeros((4, 1))
    21.     (success, rotation_vector, translation_vector) = cv2.solvePnP(
    22.         object_points, image_pts, camera_matrix, dist_coeffs, flags=cv2.SOLVEPNP_ITERATIVE
    23.     )

    24.     rmat, _ = cv2.Rodrigues(rotation_vector)
    25.     angles, _, _, _, _, _ = cv2.RQDecomp3x3(rmat)
    26.     return angles
    復制代碼

    5、定義眼睛縱橫比閾值和連續幀數閾值
    1. EYE_AR_THRESH = 0.3
    2. EYE_AR_CONSEC_FRAMES = 48
    復制代碼

    6、打開攝像頭
    我們先使用v4l2-ctl --list-devices來例出接在開發板上的列表信息:
    1. USB Camera: USB Camera (usb-xhci-hcd.0.auto-1.2):
    2.         /dev/video60
    3.         /dev/video61
    4.         /dev/media7
    復制代碼

    在代碼中填入60為攝像頭的編號:
    1. cap = cv2.VideoCapture(60)
    2. cap.set(cv2.CAP_PROP_FRAME_WIDTH, 480)  # 降低分辨率
    3. cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 320)
    復制代碼

    7、創建多線程處理函數,實現采集與分析分離:
    1. # 多線程處理函數
    2. def process_frame(frame):
    3.     global COUNTER, TOTAL
    4.     gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    5.     faces = detector(gray, 0)  # 第二個參數為0,表示不使用upsampling

    6.     for face in faces:
    7.         landmarks = predictor(gray, face)
    8.         shape = [(landmarks.part(i).x, landmarks.part(i).y) for i in range(68)]
    9.         
    10.         left_eye = shape[36:42]
    11.         right_eye = shape[42:48]

    12.         left_ear = eye_aspect_ratio(left_eye)
    13.         right_ear = eye_aspect_ratio(right_eye)
    14.         ear = (left_ear + right_ear) / 2.0

    15.         if ear < EYE_AR_THRESH:
    16.             with lock:
    17.                 COUNTER += 1
    18.         else:
    19.             with lock:
    20.                 if COUNTER >= EYE_AR_CONSEC_FRAMES:
    21.                     TOTAL += 1
    22.                 COUNTER = 0

    23.         # 繪制68個特征點
    24.         for n in range(0, 68):
    25.             x, y = shape[n]
    26.             cv2.circle(frame, (x, y), 2, (0, 255, 0), -1)

    27.         cv2.putText(frame, f"Eye AR: {ear:.2f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (0, 0, 255), 2)
    28.         cv2.putText(frame, f"Blink Count: {TOTAL}", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (0, 0, 255), 2)

    29.         # 計算頭部姿勢
    30.         angles = get_head_pose(shape)
    31.         pitch, yaw, roll = angles
    32.         cv2.putText(frame, f"Pitch: {pitch:.2f}", (10, 120), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (0, 0, 255), 2)
    33.         cv2.putText(frame, f"Yaw: {yaw:.2f}", (10, 150), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (0, 0, 255), 2)
    34.         cv2.putText(frame, f"Roll: {roll:.2f}", (10, 180), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (0, 0, 255), 2)

    35.         # 判斷疲勞狀態
    36.         if COUNTER >= EYE_AR_CONSEC_FRAMES or abs(pitch) > 30 or abs(yaw) > 30 or abs(roll) > 30:
    37.             cv2.putText(frame, "Fatigue Detected!", (10, 210), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (0, 0, 255), 2)

    38.     return frame
    復制代碼
    8、創建圖像顯示線程:
    1. with ThreadPoolExecutor(max_workers=2) as executor:
    2.     future_to_frame = {}
    3.     while True:
    4.         ret, frame = cap.read()
    5.         if not ret:
    6.             break

    7.         # 提交當前幀到線程池
    8.         future = executor.submit(process_frame, frame.copy())
    9.         future_to_frame[future] = frame

    10.         # 獲取已完成的任務結果
    11.         for future in list(future_to_frame.keys()):
    12.             if future.done():
    13.                 processed_frame = future.result()
    14.                 cv2.imshow("Frame", processed_frame)
    15.                 del future_to_frame[future]
    16.                 break

    17.         # 計算幀數
    18.         fps_counter += 1
    19.         elapsed_time = time.time() - start_time
    20.         if elapsed_time > 1.0:
    21.             fps = fps_counter / elapsed_time
    22.             fps_counter = 0
    23.             start_time = time.time()
    24.             cv2.putText(processed_frame, f"FPS: {fps:.2f}", (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

    25.         if cv2.waitKey(1) & 0xFF == ord('q'):
    復制代碼

    實現效果:

    根據檢測的結果,我們就可以來實現疲勞提醒等等的功能。
    整體代碼如下:
    1. import cv2
    2. import dlib
    3. import numpy as np
    4. import time
    5. from concurrent.futures import ThreadPoolExecutor
    6. import threading

    7. # 初始化dlib的面部檢測器和特征點預測器
    8. detector = dlib.get_frontal_face_detector()
    9. predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')

    10. # 修改字體大小
    11. font_scale = 0.5  # 原來的字體大小是0.7,現在改為0.5

    12. # 定義計算眼睛縱橫比的函數
    13. def eye_aspect_ratio(eye):
    14.     A = np.linalg.norm(np.array(eye[1]) - np.array(eye[5]))
    15.     B = np.linalg.norm(np.array(eye[2]) - np.array(eye[4]))
    16.     C = np.linalg.norm(np.array(eye[0]) - np.array(eye[3]))
    17.     ear = (A + B) / (2.0 * C)                                                                                
    18.     return ear

    19. # 定義計算頭部姿勢的函數
    20. def get_head_pose(shape):
    21.     # 定義面部特征點的三維坐標
    22.     object_points = np.array([
    23.         (0.0, 0.0, 0.0),             # 鼻尖
    24.         (0.0, -330.0, -65.0),        # 下巴
    25.         (-225.0, 170.0, -135.0),     # 左眼左眼角
    26.         (225.0, 170.0, -135.0),      # 右眼右眼角
    27.         (-150.0, -150.0, -125.0),    # 左嘴角
    28.         (150.0, -150.0, -125.0)      # 右嘴角
    29.     ], dtype=np.float32)

    30.     image_pts = np.float32([shape[i] for i in [30, 8, 36, 45, 48, 54]])
    31.     size = frame.shape
    32.     focal_length = size[1]
    33.     center = (size[1] // 2, size[0] // 2)
    34.     camera_matrix = np.array(
    35.         [[focal_length, 0, center[0]],
    36.          [0, focal_length, center[1]],
    37.          [0, 0, 1]], dtype="double"
    38.     )

    39.     dist_coeffs = np.zeros((4, 1))
    40.     (success, rotation_vector, translation_vector) = cv2.solvePnP(
    41.         object_points, image_pts, camera_matrix, dist_coeffs, flags=cv2.SOLVEPNP_ITERATIVE
    42.     )

    43.     rmat, _ = cv2.Rodrigues(rotation_vector)
    44.     angles, _, _, _, _, _ = cv2.RQDecomp3x3(rmat)
    45.     return angles

    46. # 定義眼睛縱橫比閾值和連續幀數閾值
    47. EYE_AR_THRESH = 0.3
    48. EYE_AR_CONSEC_FRAMES = 48

    49. # 初始化計數器
    50. COUNTER = 0
    51. TOTAL = 0

    52. # 創建鎖對象
    53. lock = threading.Lock()

    54. # 打開攝像頭
    55. cap = cv2.VideoCapture(60)
    56. cap.set(cv2.CAP_PROP_FRAME_WIDTH, 480)  # 降低分辨率
    57. cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 320)

    58. # 初始化幀計數器和時間戳
    59. fps_counter = 0
    60. start_time = time.time()

    61. # 多線程處理函數
    62. def process_frame(frame):
    63.     global COUNTER, TOTAL
    64.     gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    65.     faces = detector(gray, 0)  # 第二個參數為0,表示不使用upsampling

    66.     for face in faces:
    67.         landmarks = predictor(gray, face)
    68.         shape = [(landmarks.part(i).x, landmarks.part(i).y) for i in range(68)]
    69.         
    70.         left_eye = shape[36:42]
    71.         right_eye = shape[42:48]

    72.         left_ear = eye_aspect_ratio(left_eye)
    73.         right_ear = eye_aspect_ratio(right_eye)
    74.         ear = (left_ear + right_ear) / 2.0

    75.         if ear < EYE_AR_THRESH:
    76.             with lock:
    77.                 COUNTER += 1
    78.         else:
    79.             with lock:
    80.                 if COUNTER >= EYE_AR_CONSEC_FRAMES:
    81.                     TOTAL += 1
    82.                 COUNTER = 0

    83.         # 繪制68個特征點
    84.         for n in range(0, 68):
    85.             x, y = shape[n]
    86.             cv2.circle(frame, (x, y), 2, (0, 255, 0), -1)

    87.         cv2.putText(frame, f"Eye AR: {ear:.2f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (0, 0, 255), 2)
    88.         cv2.putText(frame, f"Blink Count: {TOTAL}", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (0, 0, 255), 2)

    89.         # 計算頭部姿勢
    90.         angles = get_head_pose(shape)
    91.         pitch, yaw, roll = angles
    92.         cv2.putText(frame, f"Pitch: {pitch:.2f}", (10, 120), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (0, 0, 255), 2)
    93.         cv2.putText(frame, f"Yaw: {yaw:.2f}", (10, 150), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (0, 0, 255), 2)
    94.         cv2.putText(frame, f"Roll: {roll:.2f}", (10, 180), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (0, 0, 255), 2)

    95.         # 判斷疲勞狀態
    96.         if COUNTER >= EYE_AR_CONSEC_FRAMES or abs(pitch) > 30 or abs(yaw) > 30 or abs(roll) > 30:
    97.             cv2.putText(frame, "Fatigue Detected!", (10, 210), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (0, 0, 255), 2)

    98.     return frame

    99. with ThreadPoolExecutor(max_workers=2) as executor:
    100.     future_to_frame = {}
    101.     while True:
    102.         ret, frame = cap.read()
    103.         if not ret:
    104.             break

    105.         # 提交當前幀到線程池
    106.         future = executor.submit(process_frame, frame.copy())
    107.         future_to_frame[future] = frame

    108.         # 獲取已完成的任務結果
    109.         for future in list(future_to_frame.keys()):
    110.             if future.done():
    111.                 processed_frame = future.result()
    112.                 cv2.imshow("Frame", processed_frame)
    113.                 del future_to_frame[future]
    114.                 break

    115.         # 計算幀數
    116.         fps_counter += 1
    117.         elapsed_time = time.time() - start_time
    118.         if elapsed_time > 1.0:
    119.             fps = fps_counter / elapsed_time
    120.             fps_counter = 0
    121.             start_time = time.time()
    122.             cv2.putText(processed_frame, f"FPS: {fps:.2f}", (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

    123.         if cv2.waitKey(1) & 0xFF == ord('q'):
    124.             break

    125. # 釋放攝像頭并關閉所有窗口
    126. cap.release()
    127. cv2.destroyAllWindows()
    復制代碼

    【總結】
    【米爾MYC-LR3576核心板及開發板】
    這塊開發板性能強大,能輕松實現對人臉的疲勞檢測,通過計算結果后進入非常多的工業、人工智能等等的實用功能。
    本文地址:http://www.portaltwn.com/thread-878896-1-1.html     【打印本頁】

    本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
    您需要登錄后才可以發表評論 登錄 | 立即注冊

    廠商推薦

    • Microchip視頻專區
    • EtherCAT®和Microchip LAN925x從站控制器介紹培訓教程
    • MPLAB®模擬設計器——在線電源解決方案,加速設計
    • 讓您的模擬設計靈感,化為觸手可及的現實
    • 深度體驗Microchip自動輔助駕駛應用方案——2025巡展開啟報名!
    • 貿澤電子(Mouser)專區

    相關視頻

    關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
    電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
    快速回復 返回頂部 返回列表
    精品一区二区三区自拍图片区_国产成人亚洲精品_亚洲Va欧美va国产综合888_久久亚洲国产精品五月天婷