树莓派5 Raspberry Pi OS — Mediapipe框架:手部检测对象

说在开头:好久不见,甚是想念,好久没发布新文了,虽然这节也是库存。

希望能帮助到你。

Mediapipe框架

Google公司的框架,里面有不少操作对象都是关于视觉。

例如面部、手部关键点,人体姿态等

本节主要是使用Hands(手 检测对象)

Mediapipe是Google在2019年开发并提出的一款开源的跨平台多媒体处理框架,用于构建基于机器学习的应用程序,特别是涉及到计算机视觉、音频处理、姿势估计等领域。

Mediapipe实际上是一个集成的机器学习视觉算法的工具库(包含人脸检测、人脸关键点、手势识别、头像分割和姿态识别等各种模型),该库提供了一系列预训练模型和工具,可以帮助开发者快速构建和部署计算机视觉和音频处理应用。

它提供了一套易于使用的API,可以用于实时姿势估计、手势识别、面部识别、目标跟踪等任务。

安装

确保树莓派5已经更新:sudo apt-get update

正确连接“特殊的网络”或使用“MAGIC”可以加速下载过程。

install Mediapipe过程中如若出现:externally-managed-environment的问题可以参考下面文章:

pip(3) install,完美解决 externally-managed-environment_pip3 install error: externally-managed-environment-CSDN博客
暴力解决就好,我是这么做的,没问题。

sudo mv /usr/lib/python3.x/EXTERNALLY-MANAGED /usr/lib/python3.x/EXTERNALLY-MANAGED.bk

手部识别流程

调用Mediapipe手部检测对象,对帧画面进行处理,返还21个手部关键点。

 21 Hand Landmarks

直接放Typora笔记:

此部分也是在b站习得,方法真的很不错。

对于手势的判断就变成了:对于框架API返还的21个关键点进行操作,实现手势识别。

识别效果

 部分代码

import mediapipe as mp
import numpy as np
import cv2
# Camera
import libcamera
from picamera2 import Picamera2

# 摄像头初始化 
def Camera_Init():
    global picamera
    picamera = Picamera2()
    config = picamera.create_preview_configuration(main={"format": "RGB888"})
    config["transform"] = libcamera.Transform(hflip=0, vflip=1)
    picamera.configure(config)
    picamera.start()

def get_angle(v1,v2):
    angle = np.dot(v1,v2)/(np.sqrt(np.sum(v1*v1))*np.sqrt(np.sum(v2*v2)))
    angle = np.arccos(angle)/3.14*180
    
    return angle 
    
def get_str_guester(up_fingers,list_lms):
    
    # ....

    return str_guester
        

    
if __name__ == "__main__":
    Camera_Init()
    # 定义手 检测对象
    mpHands = mp.solutions.hands
    hands = mpHands.Hands()
    mpDraw = mp.solutions.drawing_utils
  
    while True:
        # 帧读取
        img = picamera.capture_array()
        image_height, image_width, _ = np.shape(img)
        # 转换为RGB
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 
        # 得到检测结果
        results = hands.process(imgRGB)
        if results.multi_hand_landmarks:
            hand = results.multi_hand_landmarks[0]
            mpDraw.draw_landmarks(img,hand,mpHands.HAND_CONNECTIONS)
            # 采集21个关键点的坐标 list_landmarks[]
            list_lms = []    
            for i in range(21):
                pos_x = hand.landmark[i].x*image_width
                pos_y = hand.landmark[i].y*image_height
                list_lms.append([int(pos_x),int(pos_y)])
            
            # 构造凸包点
            list_lms = np.array(list_lms,dtype=np.int32)
            hull_index = [0,1,2,3,6,10,14,19,18,17,10]
            hull = cv2.convexHull(list_lms[hull_index,:])
            # 绘制凸包
            cv2.polylines(img,[hull], True, (0, 255, 0), 2)
                
            # 查找外部的点数
            n_fig = -1
            ll = [4,8,12,16,20] 
            up_fingers = []
            
            for i in ll:
                pt = (int(list_lms[i][0]),int(list_lms[i][1]))
                dist= cv2.pointPolygonTest(hull,pt,True)
                if dist <0:
                    up_fingers.append(i)
            
            str_guester = get_str_guester(up_fingers,list_lms)
            
            cv2.putText(img,' %s'%(str_guester),(90,90),cv2.FONT_HERSHEY_SIMPLEX,3,(255,255,0),4,cv2.LINE_AA)
            
            for i in ll:
                pos_x = hand.landmark[i].x*image_width
                pos_y = hand.landmark[i].y*image_height
                # 画点
                cv2.circle(img, (int(pos_x),int(pos_y)), 3, (0,255,255),-1)
                
        cv2.imshow("hands",img)  
        
        if cv2.waitKey(1) & 0xFF ==  ord('q'):
            break
    cv2.destroyAllWindows()        

功能函数GET_STR_GUESTER中即根据LMS绘制第一指节所围成的凸包。根据五个指尖在凸包的内外判断数字。代码没给出,如果有想要的可以私信。

对于个别数字需要特殊处理,例如“1” 和 “9”(指关节角度判断)、数字“7”的判断(对了我这个七是三根手指捏合,八是拇指和食指处于凸包外;不用习惯请注意)。

结语

本期如果帮到你还记得点赞收藏。

如有不便之处私信联系,欢迎交流。

猜你喜欢

转载自blog.csdn.net/Srdpy_k/article/details/143807724
今日推荐