树莓派4B Python3.7.3 Opencv+Mediapipe 手指方向识别

这篇具有很好参考价值的文章主要介绍了树莓派4B Python3.7.3 Opencv+Mediapipe 手指方向识别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

起因:2023年4月接触树莓派之后,想实现手指方向的实时识别,现有Google的框架Mediapipe可以实现21个手指关键点位置实时识别,去尝试装Mediapipe以及相关依赖库,发现树莓派的源(官方源),一些库比较旧(15年的都有),所以整体思想要装15年 16年的版本,才能适配

系统环境搭建:

1.系统选择:官方镜像下载Legacy版本Operating system images – Raspberry Pi

相关系统配置如下图:Python3.7.3,Pip18.1,Numpy1.16.2都可以用Pip更新一下

树莓派安装midiapipe,opencv,人工智能,计算机视觉

2.没有显示屏的话,需要先预埋ssh启动和Wifi自动连接,这里需要笔记本和树莓派连同一个网,烧录结束后,拔下SD再插到电脑上,把 wpa_supplicant.conf 和 ssh 扔到 root 里面:(ssh是新建文档.txt直接改的,wpa_supplicant.conf 用记事本打开输入下面)

country=CN
ctrl_interface=DIR=/var/run/wpa_supplicant
update_config=1

network={
ssid="和电脑在同一个wifi下的热点名"
psk="密码"
key_mgmt=WPA-PSK
}

3.通过和PC在同一个网络下,用Advanced IP Scanner软件找到IP地址,用Putty连接ssh,第一次开启VNC开机,设置VNC自启给树莓派配置VNC,设置开机自启_树莓派vnc自启动_9677的博客-CSDN博客

4.关于换源的问题,如果官方源不卡,包括后面可以选择手动下载安装,官方源挺好,如果卡了换树莓派换源教程_萌新源的博客-CSDN博客

5.装Opencv和拓展库以及Mediapipe,我是跟于泓老师的教程树莓派-Opencv+mediapipe安装全过程_哔哩哔哩_bilibili

(相关文件视频下面也有)百度云链接:https://pan.baidu.com/s/1jUIh4wJgKB7I6fDX5fkGwQ 
提取码:sm00

6.我跟着视频装Mediapipe-rpi4 之后import会报错,搜到mediapipe 安装笔记-1:使用anaconda python 3.7.13__message.message._checkcalledfromgeneratedfile()_不解不惑的博客-CSDN博客

protobuf版本高了,需要卸载protobuf 装protobuf==3.20版本,

pip uninstall protobuf
pip install protobuf==3.20

之后import mediapipe就没问题了(需要装的软件都在百度云里)之后再手动pip装一个

1)cvzone是一个计算机视觉工具包,可方便的图像处理和实现视觉AI功能。核心是使用OpenCV和Mediapipe库。安装使用都十分简单方便 pip3 install cvzone

2)Protobuf是Protocol Buffers的简称,它是Google公司开发的一种数据描述语言,用于描述一种轻便高效的结构化数据存储格式,

代码运行(10月21日更新)

手指方向检测(食指, 可以修改其他手指) 可以直接运行,这里的hands_module是单独检测左手或者右手,test_time检测时间就是超时返回0,last_dire是我项目里需要的参数,这应该是最快速的检测手指指向的方案了,包含了手指的方向以及手指是否直指,(食指一二三关节关键点夹角)这里是手指关节必须大于140度
效果图:
 

树莓派安装midiapipe,opencv,人工智能,计算机视觉

 手指指向判断时候,cvzone手势识别有,手掌21个关键点的三维坐标,所以这里利用的是三维向量判断和对应角度夹角,这里三维向量∠ABC需要满足需求才表示指向某个方向。

树莓派安装midiapipe,opencv,人工智能,计算机视觉


检测最大的那只手,指向判断,完成功能。


 

# -*- coding: utf-8 -*-
import cv2
import time
import numpy as np
import cvzone.HandTrackingModule
import cvzone.FaceDetectionModule
from collections import Counter

face_detector = cvzone.FaceDetectionModule.FaceDetector(minDetectionCon=0.5)
hand_direction_detector = cvzone.HandTrackingModule.HandDetector(mode=False,  # 视频流图像
                                                                 maxHands=4,  # 最多检测两只手
                                                                 detectionCon=0.5,  # 最小检测置信度
                                                                 minTrackCon=0.7)  # 最小跟踪置信度

def detect_hand_direction(cap_hand_direction, hands_module=1, last_dire=5, test_time=5):
    print("开始指向检测")
    reference_vectors = [np.array([0, -1, 0]), np.array([1, 0, 0]),
                         np.array([-1, 0, 0]), np.array([0, 1, 0])]  # 3D坐标单位向量
    angles = []
    add_count = [1, 1, 1, 1]
    left_hand_direction = [0, 0, 0, 0]
    right_hand_direction = [0, 0, 0, 0]
    video_model = 1  # 是否显示视频
    if 0 < last_dire < 5:  # 平常是5 不作数, 如果对应了某一个方向,那就让对应方向检测次数更多
        add_count[last_dire-1] = 1/3
    # 清除之前的视频流数据
    frames_to_skip = 2  # 要丢弃的帧数
    for _ in range(frames_to_skip):
        _, _ = cap_hand_direction.read()
        atime = time.time()
    while True:
        success, frame = cap_hand_direction.read()
        if success is not True:
            break
        hands = hand_direction_detector.findHands(frame, draw=False, flipType=False)
        if hands:
            left_hand_max_area = 0  # 初始化最大面积为0
            right_hand_max_area = 0  # 初始化最大面积为0
            left_hand_max_index = -1  # 初始化最大面积对应的遍历序号为-1
            right_hand_max_index = -1  # 初始化最大面积对应的遍历序号为-1
            left_region_status = 0  # 初始化左手是否在范围内
            right_region_status = 0  # 初始化右手是否在范围内
            for index, hand in enumerate(hands):
                if hand["type"] == "Left":  # 左手
                    _, _, w_left, h_left = hand["bbox"]
                    left_hand_area = w_left * h_left  # 计算面积
                    if left_hand_area > left_hand_max_area:
                        left_hand_max_area = left_hand_area
                        left_hand_max_index = index
                if hand["type"] == "Right":  # 右手
                    _, _, w_right, h_right = hand["bbox"]
                    right_hand_area = w_right * h_right  # 计算面积
                    if right_hand_area > right_hand_max_index:
                        right_hand_max_index = right_hand_area
                        right_hand_max_index = index
            if hands_module == 2 and left_hand_max_index != -1:
                # 模式2 只检测左手

                # # 采用食指的第一关节[7]第二关节[6]第三关节即指根[5]来求出 食指第二关节的角度 计算食指弯曲角度
                # # 将夹角余弦值转换为角度制并输出夹角
                ab = np.array(hands[left_hand_max_index]["lmList"][6]) - np.array(
                    hands[left_hand_max_index]["lmList"][7])
                bc = np.array(hands[left_hand_max_index]["lmList"][5]) - np.array(
                    hands[left_hand_max_index]["lmList"][6])
                cos_angle = np.dot(ab, bc) / (np.linalg.norm(ab) * np.linalg.norm(bc))
                angle = 180 - np.arccos(cos_angle) * 180 / np.pi
                if angle > 140:

                direction = np.array(hands[left_hand_max_index]["lmList"][5]) - np.array(
                    hands[left_hand_max_index]["lmList"][8])
                angles.clear()
                for reference_vector in reference_vectors:
                    cos_angle = np.dot(direction, reference_vector) / (
                                np.linalg.norm(direction) * np.linalg.norm(reference_vector))
                    angle = np.arccos(cos_angle) * 180 / np.pi
                    angles.append(angle)
                # 判断手指朝向是否符合四个方向中的至少一个
                if angles[0] < 45 <= max(angles):  # 下
                    left_hand_direction.append(1)
                elif angles[1] < 45 <= max(angles):  # 左
                    left_hand_direction.append(2)
                elif angles[2] < 45 <= max(angles):  # 右
                    left_hand_direction.append(3)
                elif angles[3] < 45 <= max(angles):  # 上
                    left_hand_direction.append(4)
                if len(left_hand_direction) >= 10:
                    counter = Counter(left_hand_direction)  # 使用Counter计算每个数字的出现次数
                    most_common_digit = counter.most_common(1)[0][0]  # 找到出现次数最多的数字
                    print("Most common digit:", most_common_digit)
                    return most_common_digit
            if hands_module == 1 and right_hand_max_index != -1:
                # 模式1 只检测右手

                # 采用食指的第一关节[7]第二关节[6]第三关节即指根[5]来求出 食指第二关节的角度 计算食指弯曲角度
                # # 将夹角余弦值转换为角度制并输出夹角
                ab = np.array(hands[right_hand_max_index]["lmList"][6]) - np.array(
                    hands[right_hand_max_index]["lmList"][7])
                bc = np.array(hands[right_hand_max_index]["lmList"][5]) - np.array(
                    hands[right_hand_max_index]["lmList"][6])
                cos_angle = np.dot(ab, bc) / (np.linalg.norm(ab) * np.linalg.norm(bc))
                angle = 180 - np.arccos(cos_angle) * 180 / np.pi
                if angle > 140:

                direction = np.array(hands[right_hand_max_index]["lmList"][5]) - np.array(
                    hands[right_hand_max_index]["lmList"][8])
                angles.clear()
                for reference_vector in reference_vectors:
                    cos_angle = np.dot(direction, reference_vector) / (
                                np.linalg.norm(direction) * np.linalg.norm(reference_vector))
                    angle = np.arccos(cos_angle) * 180 / np.pi
                    angles.append(angle)
                # 判断手指朝向是否符合四个方向中的至少一个
                if angles[0] < 45 <= max(angles):  # 下
                    right_hand_direction.append(1)
                elif angles[1] < 45 <= max(angles):  # 左
                    right_hand_direction.append(2)
                elif angles[2] < 45 <= max(angles):  # 右
                    right_hand_direction.append(3)
                elif angles[3] < 45 <= max(angles):  # 上
                    right_hand_direction.append(4)
                if len(right_hand_direction) >= 10:
                    counter = Counter(right_hand_direction)  # 使用Counter计算每个数字的出现次数
                    most_common_digit = counter.most_common(1)[0][0]  # 找到出现次数最多的数字
                    print("Most common digit:", most_common_digit)
                    return most_common_digit
        if time.time() - atime > test_time:
            cv2.destroyAllWindows()
            return 0
        if video_model == 1:
            cv2.imshow('hand_direction', frame)
            if cv2.waitKey(1) & 0xFF == 27:  # 每帧滞留20毫秒后消失,ESC键退出
                break
if __name__ == '__main__':
    Cap = cv2.VideoCapture(0)
# 检测 显示
    b = detect_hand_direction(Cap, last_dire=2, test_time=10)
    print(b)

总结:
运行下来,cvzone模型本身是谷歌的mediapipe中应用,检测效果非常好,利用起来占用资源也很少,已经应用在了树莓派等linux平台,端上运行速度可以接受,但是由于我项目本身的需求,对于各种手指指向判断时候,容易受到遮挡的影响,比如某个手势中手掌会遮挡大部分手指,就不会识别到手掌。当然cvzone中的手掌识别主要是为了追踪手掌,所以在随后的研究中将使用特定的手势训练,而不是获取手指关键点坐标来推算手指手势。文章来源地址https://www.toymoban.com/news/detail-768072.html

到了这里,关于树莓派4B Python3.7.3 Opencv+Mediapipe 手指方向识别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 使用树莓派4b和OpenCV做机械臂夹取

    文章目录 前言 一、基本功能 二、主要代码 1.图像处理部分 2.舵机驱动部分  本人第一次在csdn上发技术类文章,原谅在此多说一些废话。项目是自己的毕设,比较简单还望不要见笑,如果发现有什么问题欢迎指正。发文章的目的一方面是希望用自己微薄的能力的帮助有需要的

    2023年04月08日
    浏览(36)
  • 基于树莓派4B的OpenCV安装与简单应用(真速通版)

    前言: 本文为手把手教学树莓派4B的OpenCV安装与简单应用( 真速通版本 ),树莓派4B最为目前最新款的树莓派家族一员深受创客和开发者喜爱。树莓派4B作为一款搭载 Cortex-A72 系列芯片的板载电脑,其不仅可以作为简单的 MCU 进行控制方面开发,更可以凭借其高计算性能进行

    2024年02月16日
    浏览(73)
  • 树莓派4b安装opencv4.6.0并开启ffmpeg视频加速(2022.10.27)

    按ctrl + o ,enter保存,ctrl + x 关闭; 将以下内容写入配置文件(为pip配置阿里和豆瓣源):(保存并退出同上)

    2023年04月16日
    浏览(44)
  • 树莓派4B系统一键安装opencv,再也不要用编译安装啦!(支持buster、bullseye)

    首先第一步,需要配置好国内镜像软件源(原生源通不过),已经换源的可以跳过 。这里选择清华源为例。 点击链接看到使用帮助:https://mirrors.tuna.tsinghua.edu.cn/help/raspbian/,选择对应的系统版本,这里使用Buster为例 输入命令修改文件 /etc/apt/sources.list 和 /etc/apt/sources.list.d/

    2024年02月12日
    浏览(38)
  • 树莓派4B使用opencv获取Camera Module 3摄像头图像(解决无法直接获取图像的问题)

    莓派4B在使用官方的Camera Module 3摄像头时,无法通过opencv直接获取到图像,具体问题表现在 opencv可以打开摄像头但是无法获取到图像信息,导致imshow等方法因无法获取图像数据进而报错 ,只能使用picamera2库进行图像的获取和和处理,对不熟悉picamera2库的同学不够友好; [INF

    2024年04月27日
    浏览(52)
  • MediaPipe人体姿态、手指关键点检测

    Mediapipe是google的一个开源项目,用于构建机器学习管道 提供了16个预训练模型的案例:人脸检测、Face Mesh、虹膜、手、姿态、人体、人物分割、头发分割、目标检测、Box Tracking、Instant Motion Tracking、3D目标检测、特征匹配、AutoFlip、MediaSequence、YouTube-8M 肢体识别本质上还是分类

    2024年02月08日
    浏览(56)
  • 树莓派自带的python3.9->python3.7

    1.卸载python3.9: sudo apt-get remove python3 卸载之后一些包可以使用sudo apt autoremove这个命令删除 卸载成功如果出现问题后续再来更新(出现问题后后续安装python也会失败) (先不要安装先看) 2.安装python3.7: 我们运行python项目的时候需要下载很多项目的包对环境进行配置 而pyt

    2023年04月18日
    浏览(30)
  • [ Python+OpenCV+Mediapipe ] 实现手势控制音量

    目录 一、写在前面 二、本文内容 三、开发环境  四、代码实现 4.1引入所需包 4.2 定义一个类并初始化 4.3 定义绘制一界面并实现音量控制的主方法 五、看一看实际效果吧 六、完整代码 七、小结  八、感谢        本文所用例子为个人学习的小结,如有不足之处请各位多多

    2024年02月22日
    浏览(55)
  • 【树莓派4B为例的树莓派接口认识】

    1:SOC芯片 树莓派采用博通(Broadcom)BCM2711芯片作为SOC芯片,芯片上集成了CPU、GPU、DSP及SDRAM内存等,其中CPU和GPU共享内存,可以在系统中手工修改内存占比。4代的树莓派将内存变为了可选择的。 2:以太网接口 以太网接口让树莓派能以有线的方式接入计算机网络,这让我们

    2024年02月15日
    浏览(28)
  • MediaPipe+OpenCV 实现实时手势识别(附Python源码)

    MediaPipe官网:https://developers.google.com/mediapipe MediaPipe仓库:https://github.com/google/mediapipe MediaPipe 是一个由 Google 开发的开源跨平台机器学习框架,用于构建视觉和感知应用程序。它提供了一系列预训练的机器学习模型和工具,使开发者能够轻松地构建基于计算机视觉和机器学习的

    2024年02月07日
    浏览(45)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包