说在开头:好久不见,甚是想念,好久没发布新文了,虽然这节也是库存。
希望能帮助到你。
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”的判断(对了我这个七是三根手指捏合,八是拇指和食指处于凸包外;不用习惯请注意)。
结语
本期如果帮到你还记得点赞收藏。
如有不便之处私信联系,欢迎交流。