Python实现AI视频识别——手势控制[通俗易懂]

Python实现AI视频识别——手势控制[通俗易懂]用opencv识别手势实现原理代码importcv2importmediapipeasmpclasshandDetector():#经典OOP#设置初始条件def__init__(self,mode=False,maxHands=2,detectionCon=0.5,trackCon=0.5):self.mode=modeself.maxHands=maxHands#最多同时出现几只手

大家好,又见面了,我是你们的朋友全栈君。

用opencv识别手势

实现原理

用opencv库拍摄一帧图片,用mediapipe库识别人手和标识点,然后用opencv在视频上添加标识的信息,最后用opencv合成一个动态视频输出

代码

import cv2
import mediapipe as mp


class handDetector():  # 经典OOP
    # 设置初始条件
    def __init__(self, mode=False, maxHands=2, detectionCon=0.5, trackCon=0.5):
        self.mode = mode
        self.maxHands = maxHands  # 最多同时出现几只手
        self.detectionCon = detectionCon  # 检测可信度
        self.trackCon = trackCon  # 跟踪可信度

        self.mpHands = mp.solutions.hands  # 用mediapipe找手
        self.hands = self.mpHands.Hands(self.mode, self.maxHands,
                                        self.detectionCon, self.trackCon)
        self.mpDraw = mp.solutions.drawing_utils

    # 在图片里里找到手并返回这一帧图片
    def findHands(self, img, draw=True):
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 数字化视频输入
        self.results = self.hands.process(imgRGB)  # 处理视频找手

        if self.results.multi_hand_landmarks:  # 如果找到了手上的标识点
            for handLms in self.results.multi_hand_landmarks:
                if draw:  # 在识别出的手上把标记点画出来
                    self.mpDraw.draw_landmarks(img, handLms, self.mpHands.HAND_CONNECTIONS)
        return img

    # 找到手之后把手的关节位置投射上去并且记录数据
    def findPosition(self, img, handNo=0, draw=True):
        lmList = []  # 记录手上标识点
        if self.results.multi_hand_landmarks:
            myHand = self.results.multi_hand_landmarks[handNo]
            # 遍历识别数据,处理后输出
            for idNum, lm in enumerate(myHand.landmark):
                h, w, c = img.shape  # 高度,深度,通道数
                cx, cy = int(lm.x * w), int(lm.y * h)  # 坐标位置
                lmList.append([idNum, cx, cy])  # 可以在这里print一下看看长什么样
                if draw:  # 在识别出的点位置画个蓝点
                    cv2.circle(img, (cx, cy), 15, (0, 0, 255), cv2.FILLED)
        return lmList


def main():
    wCam, hCam = 640, 480  # 摄像头拍摄大小
    cap = cv2.VideoCapture(0)  # 创建类用来拍摄
    cap.set(3, wCam)  # 比例设置
    cap.set(4, hCam)
    detector = handDetector(detectionCon=0.8)  # 最低准确度

    tipIds = [4, 8, 12, 16, 20]  # 指头的序号

    while True:
        success, img = cap.read()  # 获取一帧
        img = detector.findHands(img)  # 找手并返回标记好的图片
        lmList = detector.findPosition(img, draw=False)  # 标点然后返回数据

        if len(lmList) != 0:  # 如果找到了手且上面有标记好的点
            fingers = []

            # 大拇指的弯曲角度
            # 如果大拇指的第4个标记点像素位置低于第3个标记点,那它就是弯的
            if lmList[tipIds[0]][1] > lmList[tipIds[0] - 1][1]:
                fingers.append(1)
            else:
                fingers.append(0)

            # 其它四个指头角度判定
            for idNum in range(1, 5):
                if lmList[tipIds[idNum]][2] < lmList[tipIds[idNum] - 2][2]:
                    fingers.append(1)
                else:
                    fingers.append(0)
            print(fingers)

            # 简单的手指二进制,用五根指头代表五位长的二进制数
            output = 0
            if fingers[0] == 1:  # 拇指竖起来
                output += 1
            if fingers[1] == 1:  # 食指竖起来
                output += 2
            if fingers[2] == 1:  # 中指竖起来
                output += 4
            if fingers[3] == 1:  # 无名指竖起来
                output += 8
            if fingers[4] == 1:  # 小指竖起来
                output += 16
            # 处理视频,画个方框,上面写识别到的数字
            cv2.rectangle(img, (20, 225), (250, 425), (0, 0, 0), cv2.FILLED)
            cv2.putText(img, str(output), (45, 375), cv2.FONT_HERSHEY_PLAIN,
                        10, (255, 255, 255), 25)

        cv2.imshow("Image", img)  # 显示处理好的一帧图片
        cv2.waitKey(1)  # 相当于帧数了,这个是1ms一帧,1s60帧


if __name__ == "__main__":  # 这样就不会导入这个文件时直接跑程序啦
    main()

运行结果

笔者直接在Python3自带的IDLE里跑这个程序的时候,会出现奇怪的闪退。以下运行结果是在PyCharm里跑的:
31
28

功能拓展

在手指本身的十进制基础上,笔者把手指计数变成了二进制,能表示32个数字。如果用两只手来计数的话可以表示1024个数字。
手指计数的判定比较简单,是直接比较x坐标的高低而不是其之间的夹角。这个也许可以用三角函数和向量乘积来计算并更加精确地判定角度。
手指除了用来表示数字还可以用来做手语。如果有一个手语动作库,那么本程序可以很好地被用来帮助不会手语的人理解手语。
用手指表示数字还有别的待开发用途,比如用手势来控制音量和屏幕亮度等等。
感兴趣的同学可以尝试实现以上功能。有任何问题和想法欢迎私信和评论区留言!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/141675.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • jmeter线程组的属性_netty线程模型详解

    jmeter线程组的属性_netty线程模型详解情境:最近用winform做一个小程序,主要是用来执行一些sql语句,无奈数据量太大,执行一次要二十分钟左右,执行期间界面根本不能再进行其它操作,就连最小化窗口都不行,一动就跟死机差不多了.因此到网上搜了一下,找到.net后台线程的概念.(高手请绕道!)前台线程和后台线程之间的选择.NETFramework中的所有线程都被指定为前台线程或后台线程。这两种线程唯一的区别是—后台线程不会

    2022年10月11日
    1
  • pycharm最新激活码(注册激活)「建议收藏」

    (pycharm最新激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~S…

    2022年3月26日
    135
  • java 直播技术_视频直播的技术原理和实现思路方案整理

    java 直播技术_视频直播的技术原理和实现思路方案整理直播模型及其实现一个通用的直播模型一般包括三个模块:主播方、服务器端和播放端。首先是主播方,它是产生视频流的源头,由一系列流程组成:第一,通过一定的设备来采集数据;第二,将采集的这些视频进行一系列的处理,比如水印、美颜和特效滤镜等处理;第三,将处理后的结果视频编码压缩成可观看可传输的视频流;第四,分发推流,即将压缩后的视频流通过网络通道传输出去。其次是播放端,播放端功能有两个层面,第一个层面是关键…

    2022年7月24日
    12
  • 数据库表设计 基本思路[通俗易懂]

    数据库表设计 基本思路[通俗易懂]好的数据结构会影响速度。好的数据库表设计会影响数据库操作效率。特别是数据多的时候,如果表的结构不好的话操作的时候条件(where后的内容)会变的非常复杂。SQL是关系数据库中用到的一种语言。所以,为了简化SQL,表的关系(内部和外部)要尽量设计的合理。下面有几个可以参照的步骤:1)找出那个表要描述的东西;2)列出你想通过这个表得到的相关信息的列表;3)通过上面的信息列表,将信息

    2022年6月20日
    30
  • Mac激活idea【2021免费激活】

    (Mac激活idea)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月29日
    313
  • 张飞日记(转&收藏)

    张飞日记(转&收藏)(第一回)    我写这个流水帐的时候,大哥和二哥都在睡觉,军师也在睡觉。    赤兔马站在我窗外,也在睡觉。    小时侯我就研究马为什么会站着睡觉,研究了很长一段时间后,我发现没有答案。而苦恼的是我的童年唯一能记起的事就是这个了。    长大以后有段时间我开始研究大哥和二哥为什么要睡在一张床上,同样也没有答案。    这个世界有太多的事是没有答案的,军师对我说过。…

    2022年7月11日
    14

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号