人脸疲劳检测应用-米尔基于RK3576核心板/开发板

米尔电子嵌入式 2024-12-20 08:03

本篇源自:优秀创作者 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以及线程等:

import cv2import dlibimport numpy as npimport timefrom concurrent.futures import ThreadPoolExecutorimport threading

2、初始化dlib的面部检测器和特征点预测器

detector = dlib.get_frontal_face_detector()predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')

3、定义计算眼睛纵横比的函数

def eye_aspect_ratio(eye):    A = np.linalg.norm(np.array(eye[1]) - np.array(eye[5]))    B = np.linalg.norm(np.array(eye[2]) - np.array(eye[4]))    C = np.linalg.norm(np.array(eye[0]) - np.array(eye[3]))    ear = (A + B) / (2.0 * C)    return ear

4、定义计算头部姿势的函数

def get_head_pose(shape):    # 定义面部特征点的三维坐标    object_points = np.array([        (0.00.00.0),             # 鼻尖        (0.0-330.0-65.0),        # 下巴        (-225.0170.0-135.0),     # 左眼左眼角        (225.0, 170.0, -135.0),      # 右眼右眼角        (-150.0-150.0-125.0),    # 左嘴角        (150.0-150.0-125.0)      # 右嘴角    ], dtype=np.float32)
    image_pts = np.float32([shape[i] for i in [30836454854]])    size = frame.shape    focal_length = size[1]    center = (size[1// 2, size[0] // 2)    camera_matrix = np.array(        [[focal_length, 0, center[0]],         [0, focal_length, center[1]],         [0, 0, 1]], dtype="double"    )
    dist_coeffs = np.zeros((41))    (success, rotation_vector, translation_vector) = cv2.solvePnP(        object_points, image_pts, camera_matrix, dist_coeffs, flags=cv2.SOLVEPNP_ITERATIVE    )
    rmat, _ = cv2.Rodrigues(rotation_vector)    angles, _, _, _, _, _ = cv2.RQDecomp3x3(rmat) return angles

5、定义眼睛纵横比阈值和连续帧数阈值

EYE_AR_THRESH = 0.3EYE_AR_CONSEC_FRAMES = 48

6、打开摄像头
我们先使用v4l2-ctl --list-devices来例出接在开发板上的列表信息:

USB Camera: USB Camera (usb-xhci-hcd.0.auto-1.2):        /dev/video60        /dev/video61        /dev/media7

在代码中填入60为摄像头的编号:

cap = cv2.VideoCapture(60)cap.set(cv2.CAP_PROP_FRAME_WIDTH, 480)  # 降低分辨率cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 320)

7、创建多线程处理函数,实现采集与分析分离:

# 多线程处理函数def process_frame(frame):    global COUNTER, TOTAL    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)    faces = detector(gray, 0)  # 第二个参数为0,表示不使用upsampling
    for face in faces:        landmarks = predictor(gray, face)        shape = [(landmarks.part(i).x, landmarks.part(i).y) for i in range(68)]        
        left_eye = shape[36:42]        right_eye = shape[42:48]
        left_ear = eye_aspect_ratio(left_eye)        right_ear = eye_aspect_ratio(right_eye)        ear = (left_ear + right_ear) / 2.0
        if ear < EYE_AR_THRESH:            with lock:                COUNTER += 1        else:            with lock:                if COUNTER >= EYE_AR_CONSEC_FRAMES:                    TOTAL += 1                COUNTER = 0
        # 绘制68个特征点        for n in range(068):            x, y = shape[n]            cv2.circle(frame, (x, y), 2, (02550), -1)
        cv2.putText(frame, f"Eye AR: {ear:.2f}", (1030), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (00255), 2)        cv2.putText(frame, f"Blink Count: {TOTAL}", (1060), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (00255), 2)
        # 计算头部姿势        angles = get_head_pose(shape)        pitch, yaw, roll = angles        cv2.putText(frame, f"Pitch: {pitch:.2f}", (10120), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (00255), 2)        cv2.putText(frame, f"Yaw: {yaw:.2f}", (10150), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (00255), 2)        cv2.putText(frame, f"Roll: {roll:.2f}", (10180), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (00255), 2)
        # 判断疲劳状态        if COUNTER >= EYE_AR_CONSEC_FRAMES or abs(pitch) > 30 or abs(yaw) > 30 or abs(roll) > 30:            cv2.putText(frame, "Fatigue Detected!", (10210), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (00255), 2)
return frame

8、创建图像显示线程:

with ThreadPoolExecutor(max_workers=2as executor:    future_to_frame = {}    while True:        ret, frame = cap.read()        if not ret:            break
        # 提交当前帧到线程池        future = executor.submit(process_frame, frame.copy())        future_to_frame[future] = frame
        # 获取已完成的任务结果        for future in list(future_to_frame.keys()):            if future.done():                processed_frame = future.result()                cv2.imshow("Frame", processed_frame)                del future_to_frame[future]                break
        # 计算帧数        fps_counter += 1        elapsed_time = time.time() - start_time        if elapsed_time > 1.0:            fps = fps_counter / elapsed_time            fps_counter = 0            start_time = time.time()            cv2.putText(processed_frame, f"FPS: {fps:.2f}", (1090), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (00255), 2)
if cv2.waitKey(1) & 0xFF == ord('q'):

实现效果:


根据检测的结果,我们就可以来实现疲劳提醒等等的功能。
整体代码如下:
import cv2import dlibimport numpy as npimport timefrom concurrent.futures import ThreadPoolExecutorimport threading
# 初始化dlib的面部检测器和特征点预测器detector = dlib.get_frontal_face_detector()predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
# 修改字体大小font_scale = 0.5  # 原来的字体大小是0.7,现在改为0.5
# 定义计算眼睛纵横比的函数def eye_aspect_ratio(eye):    A = np.linalg.norm(np.array(eye[1]) - np.array(eye[5]))    B = np.linalg.norm(np.array(eye[2]) - np.array(eye[4]))    C = np.linalg.norm(np.array(eye[0]) - np.array(eye[3]))    ear = (A + B) / (2.0 * C)    return ear
# 定义计算头部姿势的函数def get_head_pose(shape):    # 定义面部特征点的三维坐标    object_points = np.array([        (0.00.00.0),             # 鼻尖        (0.0-330.0-65.0),        # 下巴        (-225.0170.0-135.0),     # 左眼左眼角        (225.0170.0-135.0),      # 右眼右眼角        (-150.0-150.0-125.0),    # 左嘴角        (150.0-150.0-125.0)      # 右嘴角    ], dtype=np.float32)
    image_pts = np.float32([shape[i] for i in [30836454854]])    size = frame.shape    focal_length = size[1]    center = (size[1] // 2, size[0] // 2)    camera_matrix = np.array(        [[focal_length, 0, center[0]],         [0, focal_length, center[1]],         [001]], dtype="double"    )
    dist_coeffs = np.zeros((41))    (success, rotation_vector, translation_vector) = cv2.solvePnP(        object_points, image_pts, camera_matrix, dist_coeffs, flags=cv2.SOLVEPNP_ITERATIVE    )
    rmat, _ = cv2.Rodrigues(rotation_vector)    angles, _, _, _, _, _ = cv2.RQDecomp3x3(rmat)    return angles
# 定义眼睛纵横比阈值和连续帧数阈值EYE_AR_THRESH = 0.3EYE_AR_CONSEC_FRAMES = 48
# 初始化计数器COUNTER = 0TOTAL = 0
# 创建锁对象lock = threading.Lock()
# 打开摄像头cap = cv2.VideoCapture(60)cap.set(cv2.CAP_PROP_FRAME_WIDTH, 480)  # 降低分辨率cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 320)
# 初始化帧计数器和时间戳fps_counter = 0start_time = time.time()
# 多线程处理函数def process_frame(frame):    global COUNTER, TOTAL    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = detector(gray, 0) # 第二个参数为0,表示不使用upsampling
    for face in faces:        landmarks = predictor(gray, face) shape = [(landmarks.part(i).x, landmarks.part(i).y) for i in range(68)]
        left_eye = shape[36:42]        right_eye = shape[42:48]
        left_ear = eye_aspect_ratio(left_eye)        right_ear = eye_aspect_ratio(right_eye)        ear = (left_ear + right_ear) / 2.0
        if ear < EYE_AR_THRESH:            with lock:                COUNTER += 1        else:            with lock:                if COUNTER >= EYE_AR_CONSEC_FRAMES:                    TOTAL += 1                COUNTER = 0
        # 绘制68个特征点        for n in range(068):            x, y = shape[n]            cv2.circle(frame, (x, y), 2, (02550), -1)
        cv2.putText(frame, f"Eye AR: {ear:.2f}", (1030), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (00255), 2) cv2.putText(frame, f"Blink Count: {TOTAL}", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (0, 0, 255), 2)
        # 计算头部姿势        angles = get_head_pose(shape)        pitch, yaw, roll = angles        cv2.putText(frame, f"Pitch: {pitch:.2f}", (10120), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (00255), 2)        cv2.putText(frame, f"Yaw: {yaw:.2f}", (10150), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (00255), 2) cv2.putText(frame, f"Roll: {roll:.2f}", (10, 180), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (0, 0, 255), 2)
        # 判断疲劳状态        if COUNTER >= EYE_AR_CONSEC_FRAMES or abs(pitch) > 30 or abs(yaw) > 30 or abs(roll) > 30:            cv2.putText(frame, "Fatigue Detected!", (10210), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (00255), 2)
    return frame
with ThreadPoolExecutor(max_workers=2as executor:    future_to_frame = {}    while True:        ret, frame = cap.read()        if not ret:            break
        # 提交当前帧到线程池        future = executor.submit(process_frame, frame.copy())        future_to_frame[future] = frame
        # 获取已完成的任务结果        for future in list(future_to_frame.keys()):            if future.done():                processed_frame = future.result()                cv2.imshow("Frame", processed_frame)                del future_to_frame[future]                break
        # 计算帧数        fps_counter += 1        elapsed_time = time.time() - start_time        if elapsed_time > 1.0:            fps = fps_counter / elapsed_time            fps_counter = 0            start_time = time.time() cv2.putText(processed_frame, f"FPS: {fps:.2f}", (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
        if cv2.waitKey(1) & 0xFF == ord('q'):            break
# 释放摄像头并关闭所有窗口cap.release()cv2.destroyAllWindows()

【总结】

【米尔MYC-LR3576核心板及开发板】
这块开发板性能强大,能轻松实现对人脸的疲劳检测,通过计算结果后进入非常多的工业、人工智能等等的实用功能。


米尔RK3576开发板折扣活动火热进行中,购买链接:

https://detail.tmall.com/item.htm?id=846172160887


米尔电子最新“明星产品”速报







 米尔电子 
领先的嵌入式处理器模组厂商
关注“米尔MYiR”公众号
不定期分享产品资料及干货
第一时间发布米尔最新资讯

米尔电子嵌入式 米尔-领先的嵌入式处理器模组厂商,专业为您提供CPU模组,NXP、ST、全志、XILINX等核心板开
评论 (0)
  • 职场之路并非一帆风顺,从初入职场的新人成长为团队中不可或缺的骨干,背后需要经历一系列内在的蜕变。许多人误以为只需努力工作便能顺利晋升,其实核心在于思维方式的更新。走出舒适区、打破旧有框架,正是让自己与众不同的重要法宝。在这条道路上,你不只需要扎实的技能,更需要敏锐的观察力、不断自省的精神和前瞻的格局。今天,就来聊聊那改变命运的三大思维转变,让你在职场上稳步前行。工作初期,总会遇到各式各样的难题。最初,我们习惯于围绕手头任务来制定计划,专注于眼前的目标。然而,职场的竞争从来不是单打独斗,而是团队协
    优思学院 2025-04-01 17:29 198浏览
  • 据先科电子官方信息,其产品包装标签将于2024年5月1日进行全面升级。作为电子元器件行业资讯平台,大鱼芯城为您梳理本次变更的核心内容及影响:一、标签变更核心要点标签整合与环保优化变更前:卷盘、内盒及外箱需分别粘贴2张标签(含独立环保标识)。变更后:环保标识(RoHS/HAF/PbF)整合至单张标签,减少重复贴标流程。标签尺寸调整卷盘/内盒标签:尺寸由5030mm升级至**8040mm**,信息展示更清晰。外箱标签:尺寸统一为8040mm(原7040mm),提升一致性。关键信息新增新增LOT批次编
    大鱼芯城 2025-04-01 15:02 196浏览
  • 提到“质量”这两个字,我们不会忘记那些奠定基础的大师们:休哈特、戴明、朱兰、克劳士比、费根堡姆、石川馨、田口玄一……正是他们的思想和实践,构筑了现代质量管理的核心体系,也深远影响了无数企业和管理者。今天,就让我们一同致敬这些质量管理的先驱!(最近流行『吉卜力风格』AI插图,我们也来玩玩用『吉卜力风格』重绘质量大师画象)1. 休哈特:统计质量控制的奠基者沃尔特·A·休哈特,美国工程师、统计学家,被誉为“统计质量控制之父”。1924年,他提出世界上第一张控制图,并于1931年出版《产品制造质量的经济
    优思学院 2025-04-01 14:02 145浏览
  • 文/郭楚妤编辑/cc孙聪颖‍不久前,中国发展高层论坛 2025 年年会(CDF)刚刚落下帷幕。本次年会围绕 “全面释放发展动能,共促全球经济稳定增长” 这一主题,吸引了全球各界目光,众多重磅嘉宾的出席与发言成为舆论焦点。其中,韩国三星集团会长李在镕时隔两年的访华之行,更是引发广泛热议。一直以来,李在镕给外界的印象是不苟言笑。然而,在论坛开幕前一天,李在镕却意外打破固有形象。3 月 22 日,李在镕与高通公司总裁安蒙一同现身北京小米汽车工厂。小米方面极为重视此次会面,CEO 雷军亲自接待,小米副董
    华尔街科技眼 2025-04-01 19:39 209浏览
  • 文/Leon编辑/cc孙聪颖‍步入 2025 年,国家进一步加大促消费、扩内需的政策力度,家电国补政策将持续贯穿全年。这一利好举措,为行业发展注入强劲的增长动力。(详情见:2025:消费提振要靠国补还是“看不见的手”?)但与此同时,也对家电企业在战略规划、产品打造以及市场营销等多个维度,提出了更为严苛的要求。在刚刚落幕的中国家电及消费电子博览会(AWE)上,家电行业的竞争呈现出胶着的态势,各大品牌为在激烈的市场竞争中脱颖而出,纷纷加大产品研发投入,积极推出新产品,试图提升产品附加值与市场竞争力。
    华尔街科技眼 2025-04-01 19:49 206浏览
  • 探针本身不需要对焦。探针的工作原理是通过接触被测物体表面来传递电信号,其精度和使用效果取决于探针的材质、形状以及与检测设备的匹配度,而非对焦操作。一、探针的工作原理探针是检测设备中的重要部件,常用于电子显微镜、坐标测量机等精密仪器中。其工作原理主要是通过接触被测物体的表面,将接触点的位置信息或电信号传递给检测设备,从而实现对物体表面形貌、尺寸或电性能等参数的测量。在这个过程中,探针的精度和稳定性对测量结果具有至关重要的影响。二、探针的操作要求在使用探针进行测量时,需要确保探针与被测物体表面的良好
    锦正茂科技 2025-04-02 10:41 69浏览
  • 退火炉,作为热处理设备的一种,广泛应用于各种金属材料的退火处理。那么,退火炉究竟是干嘛用的呢?一、退火炉的主要用途退火炉主要用于金属材料(如钢、铁、铜等)的热处理,通过退火工艺改善材料的机械性能,消除内应力和组织缺陷,提高材料的塑性和韧性。退火过程中,材料被加热到一定温度后保持一段时间,然后以适当的速度冷却,以达到改善材料性能的目的。二、退火炉的工作原理退火炉通过电热元件(如电阻丝、硅碳棒等)或燃气燃烧器加热炉膛,使炉内温度达到所需的退火温度。在退火过程中,炉内的温度、加热速度和冷却速度都可以根
    锦正茂科技 2025-04-02 10:13 70浏览
  • 在智能交互设备快速发展的今天,语音芯片作为人机交互的核心组件,其性能直接影响用户体验与产品竞争力。WT588F02B-8S语音芯片,凭借其静态功耗<5μA的卓越低功耗特性,成为物联网、智能家居、工业自动化等领域的理想选择,为设备赋予“听得懂、说得清”的智能化能力。一、核心优势:低功耗与高性能的完美结合超低待机功耗WT588F02B-8S在休眠模式下待机电流仅为5μA以下,显著延长了电池供电设备的续航能力。例如,在电子锁、气体检测仪等需长期待机的场景中,用户无需频繁更换电池,降低了维护成本。灵活的
    广州唯创电子 2025-04-02 08:34 148浏览
  • 引言在语音芯片设计中,输出电路的设计直接影响音频质量与系统稳定性。WT588系列语音芯片(如WT588F02B、WT588F02A/04A/08A等),因其高集成度与灵活性被广泛应用于智能设备。然而,不同型号在硬件设计上存在关键差异,尤其是DAC加功放输出电路的配置要求。本文将从硬件架构、电路设计要点及选型建议三方面,解析WT588F02B与F02A/04A/08A的核心区别,帮助开发者高效完成产品设计。一、核心硬件差异对比WT588F02B与F02A/04A/08A系列芯片均支持PWM直推喇叭
    广州唯创电子 2025-04-01 08:53 188浏览
  • 北京贞光科技有限公司作为紫光同芯授权代理商,专注于为客户提供车规级安全芯片的硬件供应与软件SDK一站式解决方案,同时配备专业技术团队,为选型及定制需求提供现场指导与支持。随着新能源汽车渗透率突破40%(中汽协2024数据),智能驾驶向L3+快速演进,车规级MCU正迎来技术范式变革。作为汽车电子系统的"神经中枢",通过AEC-Q100 Grade 1认证的MCU芯片需在-40℃~150℃极端温度下保持μs级响应精度,同时满足ISO 26262 ASIL-D功能安全要求。在集中式
    贞光科技 2025-04-02 14:50 122浏览
  • 随着汽车向智能化、场景化加速演进,智能座舱已成为人车交互的核心承载。从驾驶员注意力监测到儿童遗留检测,从乘员识别到安全带状态判断,座舱内的每一次行为都蕴含着巨大的安全与体验价值。然而,这些感知系统要在多样驾驶行为、复杂座舱布局和极端光照条件下持续稳定运行,传统的真实数据采集方式已难以支撑其开发迭代需求。智能座舱的技术演进,正由“采集驱动”转向“仿真驱动”。一、智能座舱仿真的挑战与突破图1:座舱实例图智能座舱中的AI系统,不仅需要理解驾驶员的行为和状态,还要同时感知乘员、儿童、宠物乃至环境中的潜在
    康谋 2025-04-02 10:23 96浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦