mediapipe 眨眼检测、头部三轴姿态检测(改进版)

这篇具有很好参考价值的文章主要介绍了mediapipe 眨眼检测、头部三轴姿态检测(改进版)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

其实视觉检测的项目我也搞了一段时间了,只不过自我感觉不精,基本就是调库侠加拼接侠,会把各种例程拼来拼去的。
今天研究的是眨眼检测,开始用的是比较常见的opencv dlib的库,不过发现逼格不够高,有三个缺点:一是模型要64m,二是点数只有64,三是对侧脸的检测效果不好。特别是第三点很影响实际效果,所以为啥不用高大上的mediapipe呢?
很快找到了一个外国大佬的项目,在此
GITHUB-mediapipe眨眼检测
拿下来就直接可以用,很好,meidapipe的人脸mask检测有400多个点,这个库里给出了人脸眉毛合嘴巴的具体点数,省了很多事儿了,不过实际跑下来效果过不太好,原因很简单,**可能我眼睛太小了。。。**而且头部高低不同眼睛的参数也不同,为了适合更多人合更多姿态,我加了个平均参数,就是取前5次的平均值再来跟本次比较,这样一来就准确多啦!
不废话,上源码:

from numpy import *
import cv2 as cv
import mediapipe as mp
import time
import utils, math
import numpy as np
# variables 
frame_counter =0
CEF_COUNTER =0
TOTAL_BLINKS =0
# constants
THRESHOLD=0.6    #关键参数1,闭眼与睁眼的阈值调整,越大越不容易检测
CLOSED_EYES_FRAME =1    #关键参数2,闭眼的帧数,越大判定的时间越久
FONTS =cv.FONT_HERSHEY_COMPLEX

# face bounder indices 
FACE_OVAL=[ 10, 338, 297, 332, 284, 251, 389, 356, 454, 323, 361, 288, 397, 365, 379, 378, 400, 377, 152, 148, 176, 149, 150, 136, 172, 58, 132, 93, 234, 127, 162, 21, 54, 103,67, 109]

# lips indices for Landmarks
LIPS=[ 61, 146, 91, 181, 84, 17, 314, 405, 321, 375,291, 308, 324, 318, 402, 317, 14, 87, 178, 88, 95,185, 40, 39, 37,0 ,267 ,269 ,270 ,409, 415, 310, 311, 312, 13, 82, 81, 42, 183, 78 ]
LOWER_LIPS =[61, 146, 91, 181, 84, 17, 314, 405, 321, 375, 291, 308, 324, 318, 402, 317, 14, 87, 178, 88, 95]
UPPER_LIPS=[ 185, 40, 39, 37,0 ,267 ,269 ,270 ,409, 415, 310, 311, 312, 13, 82, 81, 42, 183, 78] 
# Left eyes indices 
LEFT_EYE =[ 362, 382, 381, 380, 374, 373, 390, 249, 263, 466, 388, 387, 386, 385,384, 398 ]
LEFT_EYEBROW =[ 336, 296, 334, 293, 300, 276, 283, 282, 295, 285 ]

# right eyes indices
RIGHT_EYE=[ 33, 7, 163, 144, 145, 153, 154, 155, 133, 173, 157, 158, 159, 160, 161 , 246 ]  
RIGHT_EYEBROW=[ 70, 63, 105, 66, 107, 55, 65, 52, 53, 46 ]

map_face_mesh = mp.solutions.face_mesh
# camera object 
camera = cv.VideoCapture(0)
# landmark detection function 
def landmarksDetection(img, results, draw=False):
    img_height, img_width= img.shape[:2]
    # list[(x,y), (x,y)....]
    mesh_coord = [(int(point.x * img_width), int(point.y * img_height)) for point in results.multi_face_landmarks[0].landmark]
    if draw :
        [cv.circle(img, p, 2, (0,255,0), -1) for p in mesh_coord]

    # returning the list of tuples for each landmarks 
    return mesh_coord

# Euclaidean distance 
def euclaideanDistance(point, point1):
    x, y = point
    x1, y1 = point1
    distance = math.sqrt((x1 - x)**2 + (y1 - y)**2)
    return distance

# Blinking Ratio
def blinkRatio(img, landmarks, right_indices, left_indices):
    # Right eyes 
    # horizontal line 
    rh_right = landmarks[right_indices[0]]
    rh_left = landmarks[right_indices[8]]
    # vertical line 
    rv_top = landmarks[right_indices[12]]
    rv_bottom = landmarks[right_indices[4]]
    # draw lines on right eyes 
    #cv.line(img, rh_right, rh_left, utils.GREEN, 2)
    #cv.line(img, rv_top, rv_bottom, utils.WHITE, 2)

    # LEFT_EYE 
    # horizontal line 
    lh_right = landmarks[left_indices[0]]
    lh_left = landmarks[left_indices[8]]

    # vertical line 
    lv_top = landmarks[left_indices[12]]
    lv_bottom = landmarks[left_indices[4]]

    rhDistance = euclaideanDistance(rh_right, rh_left)
    rvDistance = euclaideanDistance(rv_top, rv_bottom)

    lvDistance = euclaideanDistance(lv_top, lv_bottom)
    lhDistance = euclaideanDistance(lh_right, lh_left)

    reRatio = rhDistance/rvDistance
    leRatio = lhDistance/lvDistance

    ratio = (reRatio+leRatio)/2
    return ratio 


ratiolist=[4,4,4,4,4]
with map_face_mesh.FaceMesh(min_detection_confidence =0.5, min_tracking_confidence=0.5) as face_mesh:

    # starting time here 
    start_time = time.time()
    # starting Video loop here.
    while True:
        frame_counter +=1 # frame counter
        ret, frame = camera.read() # getting frame from camera 
        if not ret: 
            break # no more frames break
        #  resizing frame
        
        frame = cv.resize(frame, None, fx=1.5, fy=1.5, interpolation=cv.INTER_CUBIC)
        frame_height, frame_width= frame.shape[:2]
        rgb_frame = cv.cvtColor(frame, cv.COLOR_RGB2BGR)
        results  = face_mesh.process(rgb_frame)
        if results.multi_face_landmarks:
            mesh_coords = landmarksDetection(frame, results, False)
            ratio = blinkRatio(frame, mesh_coords, RIGHT_EYE, LEFT_EYE)
            # cv.putText(frame, f'ratio {ratio}', (100, 100), FONTS, 1.0, utils.GREEN, 2)
            utils.colorBackgroundText(frame,  f'Ratio : {round(ratio,2)}', FONTS, 0.7, (30,100),2, utils.PINK, utils.YELLOW)
            ave=mean(ratiolist)
            if ratio >ave+THRESHOLD:
                CEF_COUNTER +=1
                # cv.putText(frame, 'Blink', (200, 50), FONTS, 1.3, utils.PINK, 2)
                utils.colorBackgroundText(frame,  f'Blink', FONTS, 1.7, (int(frame_height/2), 100), 2, utils.YELLOW, pad_x=6, pad_y=6, )
            else:
                if CEF_COUNTER>CLOSED_EYES_FRAME:
                    TOTAL_BLINKS +=1
                    CEF_COUNTER =0
            ratiolist.pop(0)
            ratiolist.append(ratio)
            # cv.putText(frame, f'Total Blinks: {TOTAL_BLINKS}', (100, 150), FONTS, 0.6, utils.GREEN, 2)
            utils.colorBackgroundText(frame,  f'Total Blinks: {TOTAL_BLINKS}', FONTS, 0.7, (30,150),2)
            
            #cv.polylines(frame,  [np.array([mesh_coords[p] for p in LEFT_EYE ], dtype=np.int32)], True, utils.GREEN, 1, cv.LINE_AA)
            #cv.polylines(frame,  [np.array([mesh_coords[p] for p in RIGHT_EYE ], dtype=np.int32)], True, utils.GREEN, 1, cv.LINE_AA)



        # calculating  frame per seconds FPS
        end_time = time.time()-start_time
        fps = frame_counter/end_time

        frame =utils.textWithBackground(frame,f'FPS: {round(fps,1)}',FONTS, 1.0, (30, 50), bgOpacity=0.9, textThickness=2)
        # writing image for thumbnail drawing shape
        # cv.imwrite(f'img/frame_{frame_counter}.png', frame)
        cv.imshow('frame', frame)
        key = cv.waitKey(2)
        if key==ord('q') or key ==ord('Q'):
            break
    cv.destroyAllWindows()
    camera.release()


反正也没人看,偷偷加一个头部三轴姿态的检测吧,巨好用哦!
github mediapipe 头部三轴姿态检测文章来源地址https://www.toymoban.com/news/detail-625831.html

import math

import cv2
import mediapipe as mp
import numpy as np

mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(min_detection_confidence=0.5,
                                  min_tracking_confidence=0.5)
cap = cv2.VideoCapture(0)


def rotation_matrix_to_angles(rotation_matrix):
    """
    Calculate Euler angles from rotation matrix.
    :param rotation_matrix: A 3*3 matrix with the following structure
    [Cosz*Cosy  Cosz*Siny*Sinx - Sinz*Cosx  Cosz*Siny*Cosx + Sinz*Sinx]
    [Sinz*Cosy  Sinz*Siny*Sinx + Sinz*Cosx  Sinz*Siny*Cosx - Cosz*Sinx]
    [  -Siny             CosySinx                   Cosy*Cosx         ]
    :return: Angles in degrees for each axis
    """
    x = math.atan2(rotation_matrix[2, 1], rotation_matrix[2, 2])
    y = math.atan2(-rotation_matrix[2, 0], math.sqrt(rotation_matrix[0, 0] ** 2 +
                                                     rotation_matrix[1, 0] ** 2))
    z = math.atan2(rotation_matrix[1, 0], rotation_matrix[0, 0])
    return np.array([x, y, z]) * 180. / math.pi


while cap.isOpened():
    success, image = cap.read()

    # Convert the color space from BGR to RGB and get Mediapipe results
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    results = face_mesh.process(image)

    # Convert the color space from RGB to BGR to display well with Opencv
    image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

    face_coordination_in_real_world = np.array([
        [285, 528, 200],
        [285, 371, 152],
        [197, 574, 128],
        [173, 425, 108],
        [360, 574, 128],
        [391, 425, 108]
    ], dtype=np.float64)

    h, w, _ = image.shape
    face_coordination_in_image = []

    if results.multi_face_landmarks:
        for face_landmarks in results.multi_face_landmarks:
            for idx, lm in enumerate(face_landmarks.landmark):
                if idx in [1, 9, 57, 130, 287, 359]:
                    x, y = int(lm.x * w), int(lm.y * h)
                    face_coordination_in_image.append([x, y])

            face_coordination_in_image = np.array(face_coordination_in_image,
                                                  dtype=np.float64)

            # The camera matrix
            focal_length = 1 * w
            cam_matrix = np.array([[focal_length, 0, w / 2],
                                   [0, focal_length, h / 2],
                                   [0, 0, 1]])

            # The Distance Matrix
            dist_matrix = np.zeros((4, 1), dtype=np.float64)

            # Use solvePnP function to get rotation vector
            success, rotation_vec, transition_vec = cv2.solvePnP(
                face_coordination_in_real_world, face_coordination_in_image,
                cam_matrix, dist_matrix)

            # Use Rodrigues function to convert rotation vector to matrix
            rotation_matrix, jacobian = cv2.Rodrigues(rotation_vec)

            result = rotation_matrix_to_angles(rotation_matrix)
            for i, info in enumerate(zip(('pitch', 'yaw', 'roll'), result)):
                k, v = info
                text = f'{k}: {int(v)}'
                cv2.putText(image, text, (20, i*30 + 20),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)


    cv2.imshow('Head Pose Angles', image)

    if cv2.waitKey(5) & 0xFF == 27:
        break

cap.release()

到了这里,关于mediapipe 眨眼检测、头部三轴姿态检测(改进版)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python 涉及opencv mediapipe知识,眨眼计数 供初学者参考

    基本思路  我们知道正面侦测到人脸时,任意一只眼睛水平方向上的两个特征点构成水平距离,上下两个特征点构成垂直距离 当头像靠近或者远离摄像头时,垂直距离与水平距离的比值基本恒定  根据这一思路 当闭眼时 垂直距离变小 比值固定小于某一个值 当睁眼时 比值大

    2024年01月23日
    浏览(51)
  • 三轴陀螺仪解算姿态(四元数)

    三轴陀螺仪可以测量载体在三个轴上的角速度分量,对这些角速度进行积分就可以得到旋转的角度,应用到载体上就可以得到载体的姿态。 假设导航坐标系为东北天,载体坐标系为右前上。 初始载体坐标系和导航坐标系重合,对应的四元数为q=[1,0,0,0],使用此四元数表示 载

    2024年02月05日
    浏览(42)
  • 三轴加速度计解算姿态(四元数)

    当传感器载体静止时,加速度计只会输出重力加速度,可以凭此来计算载体的俯仰角和滚转角。 假设导航坐标系为东北天,载体坐标系为右前上。 初始载体坐标系和导航坐标系重合,对应的四元数为q=[1,0,0,0],使用此四元数表示 载体在导航坐标系下的旋转 。 先将四元数转为

    2024年02月15日
    浏览(47)
  • 计算机视觉实战项目(图像分类+目标检测+目标跟踪+姿态识别+车道线识别+车牌识别)

    教程博客_传送门链接:链接 在本教程中,您将学习如何使用迁移学习训练卷积神经网络以进行图像分类。您可以在 cs231n 上阅读有关迁移学习的更多信息。 本文主要目的是教会你如何自己搭建分类模型,耐心看完,相信会有很大收获。废话不多说,直切主题… 首先们要知道深

    2024年02月07日
    浏览(76)
  • 【姿态估计】MediaPipe部分solution(手势,人体姿态,面部动作)的用法

    Mediapipe介绍 MediaPipe是个基于图形的跨平台框架,用于构建多模式应用的机器学习管道。 MediaPipe可在移动设备,工作站和服务器上跨平台运行,并支持移动GPU加速。使用MediaPipe,可以将应用的机器学习管道构建为模块化组件的图形。 MediaPipe专为机器学习从业者而设计包括研究

    2024年02月01日
    浏览(85)
  • 使用OpenCV和MediaPipe实现姿态识别!

    大家好,我是小F~ MediaPipe是一款由Google开发并开源的数据流处理机器学习应用开发框架。 它是一个基于图的数据处理管线,用于构建使用了多种形式的数据源,如视频、音频、传感器数据以及任何时间序列数据。 MediaPipe通过将各个感知模型抽象为模块并将其连接到可维护的

    2024年02月11日
    浏览(43)
  • 基于mediapipe的姿态识别和简单行为识别

    源码地址: 🚀🚀🚀🚀 其实这部分很简单,直接在windows命令行的环境下 就可以啦 Mediapipe是一个用于构建机器学习管道的框架,用户处理视频、音频等时间序列数据。这个跨平台框架适用于桌面/服务器、Android、ios和各类嵌入式设备。 目前mediapipe包含16个solutions,分别为 总

    2024年02月02日
    浏览(59)
  • WinUI(WASDK)使用MediaPipe检查人体姿态关键点

    之前有用这个MediaPipe.NET .NET包装库搞了手势识别,丰富了稚晖君的ElectronBot机器人的第三方上位机软件的功能,MediaPipe作为谷歌开源的机器视觉库,功能很丰富了,于是就开始整活了,来体验了一把人体姿态关键点检测。 这个框架是微软最新的应用开发框架,我是用来开发程

    2024年02月15日
    浏览(52)
  • opencv-疲劳检测-眨眼检测

    2024年02月12日
    浏览(37)
  • 在你眨眼时,VR这样欺骗你的视觉

    VR的沉浸感,可以让人仿佛置身于现实之外,还可以利用各种生物传感特性,来模拟一种具有存在感的虚拟空间。实际上,VR可以很好的欺骗人的感官,比如尽管你身处空间有限的房间中,但在VR中你仿佛已来到开阔的户外大空间中。 为了进一步欺骗你的视觉,一些方案会在你

    2023年04月26日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包