You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于鼻-上唇距离的dlib面部标记咀嚼动作检测失效问题

问题:dlib面部标记检测咀嚼状态失效

使用dlib面部标记识别咀嚼状态,通过计算鼻尖到上唇的帧间距离变化判断,但实际检测时,即使人员咀嚼,输出仍显示“lip is not moving around too much!”,且帧间距离值始终固定(如0.75)。

问题根源分析

  • 变量引用错误:检测循环中始终使用最后一帧的shape值,而非当前帧的面部标记数据,导致距离计算完全不变。
  • 距离维度错误:代码中计算的是鼻尖与上唇的水平距离(x轴差值),但咀嚼动作主要是上唇的垂直(y轴)移动,水平距离变化极小。
  • 缺失必要初始化代码:未加载dlib的人脸检测器和面部标记预测器,也未定义shape_to_list等依赖函数,可能导致标记检测异常。
  • 阈值未归一化:固定阈值0.015未考虑视频分辨率差异,不同尺寸的帧会导致阈值失效。

修复方案与代码调整

1. 补全基础初始化代码

添加dlib检测器、预测器加载,以及shape_to_list函数实现:

# 初始化dlib人脸检测器和面部标记预测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")  # 需要下载该模型文件

def shape_to_list(shape):
    # 将dlib的面部标记转换为numpy数组列表
    coords = np.zeros((68, 2), dtype=int)
    for i in range(0, 68):
        coords[i] = (shape.part(i).x, shape.part(i).y)
    return coords

2. 修正距离计算逻辑

改为计算鼻尖与上唇的垂直距离(y轴差值),这才是咀嚼时的主要变化维度:

def lip_nose_distance(shape):
    # 取上唇的关键标记点(50-53对应上唇上部)
    top_lip = shape[50:54]
    # 取鼻尖的标记点(33是鼻尖中心)
    nose = shape[33]
    
    # 计算垂直方向(y轴)的距离
    distance = abs(nose[1] - np.mean(top_lip, axis=0)[1])
    return distance

3. 修复帧循环中的变量引用

在标记缓冲循环中,使用当前帧的landmark作为计算依据,而非固定的shape:

old_lip_mar1 = 0.0
# 遍历每帧的面部标记数据
for (i, landmark) in enumerate(landmark_buffer):
    if landmark is None:
        print("未检测到人脸")
        continue
    # 使用当前帧的landmark计算距离
    lip_dist = lip_nose_distance(landmark)
    
    if old_lip_mar1 > 0.0:
        # 计算帧间距离变化率(归一化处理,避免分辨率影响)
        change_ratio = abs(lip_dist - old_lip_mar1) / old_lip_mar1
        # 调整阈值为相对变化率,比如超过5%则判断为咀嚼
        if change_ratio > 0.05:
            print("检测到咀嚼动作!")
        else:
            print("未检测到咀嚼动作")
    
    old_lip_mar1 = lip_dist

4. 优化标记缓冲获取逻辑

移除未定义的get_rotated_mouth_loc_with_height函数,改用标准的dlib人脸检测流程:

landmark_buffer = []
for image in frame_buffer:
    # 检测人脸
    rects = detector(image, 0)
    if len(rects) == 0:
        # 未检测到人脸时跳过或记录
        landmark_buffer.append(None)
        continue
    # 获取面部标记
    shape = predictor(image, rects[0])
    shape = shape_to_list(shape)
    landmark_buffer.append(shape)

额外优化建议

  • 添加人脸跟踪:如果视频中存在多个人脸,需要跟踪特定目标,避免切换人脸导致误判。
  • 滑动窗口判断:不要仅依赖单帧变化,连续3-5帧的变化趋势更能准确判断咀嚼动作。
  • 归一化处理:用面部整体高度(如下颌到头顶的距离)缩放鼻唇距离,消除不同拍摄距离的影响。

内容的提问来源于stack exchange,提问作者Sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 13:36:08