基于opencv和mediapipe的手部框选

前言当我们进行机器学习时,如果想识别手势信息,比较好的办法就是把手部信息给裁剪出来。这样在进行模型预测时,通过把手部裁剪部分进行预测就可以大大提高准确率。所以应该如何进行手部裁剪呢?

在这里我们将介绍开源模型mediapipe,其通过把手部信息用21个坐标来确定手部,就像这样

 那么,我们想知道他存储手部这些信息用的什么数据结构呢,看下面代码:

results.multi_hand_landmarks = [
    # 第一只手的关键点列表(21个Landmark)
    <NormalizedLandmarkList landmarks=[
        <NormalizedLandmark x=0.5 y=0.3 z=-0.1>,
        <NormalizedLandmark x=0.6 y=0.4 z=-0.2>,
        ... # 共21个
    ]>,
    # 第二只手的关键点列表
    <NormalizedLandmarkList landmarks=[
        <NormalizedLandmark x=0.2 y=0.7 z=-0.3>,
        ...
    ]>
]

通过这个输出信息我们可以看到multi_hand_landmarks通过列表来表示一个手部的信息,如21个关键点的坐标,而我们可以通过遍历其中的landmark列表来获取21个坐标信息,其中每一个坐标信息存储均通过归一化。

tips:其中的z表示的是点位离摄像头的距离,不知道之前一直在想手部怎么建立三维坐标。。。

好的,现在我们要实现框选手部信息就会非常简单,通过以下代码就可以实现:

import cv2
import mediapipe as mp

# mediapipe初始化
mp_hands = mp.solutions.hands
hands = mp_hands.Hands()  # 采用默认配置

cap = cv2.VideoCapture(0)
padding = 20

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break  # 处理视频读取错误

    results = hands.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
    h, w, _ = frame.shape

    if results.multi_hand_landmarks:
        # 取第一个检测到的手
        hand_landmarks = results.multi_hand_landmarks[0]

        # 收集所有关键点的归一化坐标并转换为像素坐标
        # for lm in hand_landmarks.landmark为遍历手中的每一个坐标点
        x_coords = [int(lm.x * w) for lm in hand_landmarks.landmark]
        y_coords = [int(lm.y * h) for lm in hand_landmarks.landmark]

        # 计算包围盒边界(添加padding)

        #x_min :左边界
        #y_min :上边界
        #x_max :右边界
        #y_max :下边界
        x_min = max(0, min(x_coords) - padding)
        y_min = max(0, min(y_coords) - padding)
        x_max = min(w, max(x_coords) + padding)
        y_max = min(h, max(y_coords) + padding)

        # 绘制包围盒

        cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), (0, 0, 255), 2)
        cv2.putText(frame, f"{x_min}", (x_min-20, y_min-8), cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2)
        
    cv2.imshow('frame', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

最后就可以实现下图这种手部信息框选(这里我输出了左上角的边距信息,可以自己DIY,这里是基于笔记本摄像头的):

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值