Python使用Opencv图像处理方法完成手势识别(二)

news2024/12/23 19:42:53

Opencv完成手势识别

  • 根据坐标识别
    • 寻找最低点
    • 计算其他点与最低点的距离
    • 通过距离阈值判断手指根数和手势
  • 效果展现
  • 完整代码

当我们把手近似出来后会得到一组轮廓的点坐标,我自己手势识别的思路就是根据点坐标来判断手势。

根据坐标识别

寻找最低点

所谓寻找最低点,就是寻找手掌最下面点的坐标
在这里插入图片描述

比如这幅图,最左下角的点就是手掌的最低点,获得的方法是使用numpy的np.argmax函数,将维度设置为图片高的维度,获得最大的高就是获得最低的点。

maxindex = np.argmax(allpoint)

计算其他点与最低点的距离

在这里插入图片描述

获取成功之后就将最低点与其他点的距离计算出来:

#pt1点一
#pt2点二
def get_distance(pt1, pt2):
    distance = ((pt2[0] - pt1[0]) ** 2 + (pt2[1] - pt1[1]) ** 2) ** (0.5)
    return distance
for point in allpoint:
    distance = self.get_distance(self.allpoint[maxindex [1], :], point)
    if distance > 300:
        cv2.line(img,all_point[maxindex [1],:],point,bgr,4,16)

通过距离阈值判断手指根数和手势

然后通过这个距离阈值排除两根手指中间的点:
在这里插入图片描述
可以发现左边的图片线的数量比右边少了几根双指中间的。
最后我们只需要通过手指线的根数来判断手势就行了。

效果展现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

完整代码

import cv2
import numpy as np
import random

class Img_handle:
    def __init__(self,area_min,lenth_min,distance,drawtype=0,area_max=100000,lenth_max=100000):
        #default area_min=20000 lenth_min=1000 distance=300
			#writer:csdn月明Mo
			#area_min 轮廓面积最小值
			#area_max 轮廓面积最大值
			#lenth_min 轮廓周长最小值
			#lenth_max 轮廓周长最大值
			#distance 距离阈值
			#drawtype 手势描绘类型,0为近似描绘 1为直线描绘
        self.area_min=area_min
        self.area_max=area_max
        self.lenth_min=lenth_min
        self.lenth_max=lenth_max
        self.distance=distance
        self.allpoint = []
        self.highHSV = np.array([15, 255, 255])
        self.lowHSV = np.array([0, 50, 50])
        self.drawtype=drawtype
	
	#writer:csdn月明Mo
	#Hsv阈值改变函数
    def change_Hsv(self,lowHSV,highHSV):
        self.highHSV=highHSV
        self.lowHSV=lowHSV

	#writer:csdn月明Mo
	#图片不失真resize函数
    def resize_img(self,size=list,img=None):
        size = [size[1], size[0], size[2]]
        mask = np.zeros(size, dtype=np.uint8)
        h, w = self.img.shape[0:2]
        dwh = min([size[0] / h, size[1] / w])
        self.img = cv2.resize(self.img, None, fx=dwh, fy=dwh)
        if h > w:
            dxy = int((size[1] - self.img.shape[1]) / 2)
            mask[:, dxy:self.img.shape[1] + dxy, :] = self.img
        else:
            dxy = int((size[0] - self.img.shape[0]) / 2)
            mask[dxy:self.img.shape[0] + dxy, :, :] = self.img
        return mask

	#writer:csdn月明Mo
	#图片处理函数
    def img_handle(self):

        self.img = cv2.cvtColor(self.img, cv2.COLOR_BGR2HSV)

        cv2.GaussianBlur(self.img, [5, 5], 0)

        self.img = cv2.inRange(self.img, self.lowHSV, self.highHSV)

        kernel = np.ones([3, 3], dtype=np.uint8)
        self.img = cv2.morphologyEx(self.img, cv2.MORPH_CLOSE, kernel, iterations=1)
        kernel = np.ones([3, 3], dtype=np.uint8)
        self.img = cv2.morphologyEx(self.img, cv2.MORPH_DILATE, kernel, iterations=1)

        contours, num = cv2.findContours(self.img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        for contour in contours:
            area = cv2.contourArea(contour)
            lenth = cv2.arcLength(contour, True)
            if self.area_max >area > self.area_min and self.lenth_max >lenth > self.lenth_min:

                epsilon = 0.02 * cv2.arcLength(contour, True)
                self.allpoint = cv2.approxPolyDP(contour, epsilon, True)

                self.allpoint = self.allpoint.reshape(len(self.allpoint), 2)
                self.allpoint = np.array(self.allpoint, dtype=np.int32)
                if self.drawtype==0:

                    b = random.randint(0, 255)
                    g = random.randint(0, 255)
                    r = random.randint(0, 255)

                    cv2.polylines(self.output_img, [self.allpoint], True, [b, g, r], 4, 16)
                    
	#writer:csdn月明Mo
	#距离计算函数
    def get_distance(self, pt1, pt2):
        distance = ((pt2[0] - pt1[0]) ** 2 + (pt2[1] - pt1[1]) ** 2) ** (0.5)
        return distance

	#writer:csdn月明Mo
	#手势判断函数
    def detect(self):
        num = 0
        if np.any(self.allpoint):
            maxindex  = np.argmax(self.allpoint, axis=0)
            for point in self.allpoint:
                distance = self.get_distance(self.allpoint[maxindex [1], :], point)
                if distance > self.distance:
                    if self.drawtype ==1:

                        b = random.randint(0, 255)
                        g = random.randint(0, 255)
                        r = random.randint(0, 255)

                        cv2.line(self.output_img,self.allpoint[maxindex [1],:],point,[b, g, r],4,16)
                    num += 1
            if num == 1:
                cv2.putText(self.output_img, 'one', [10, 50], cv2.FONT_HERSHEY_SIMPLEX, 2, [0, 0, 255], thickness=4)
            elif num == 2:
                cv2.putText(self.output_img, 'two', [10, 50], cv2.FONT_HERSHEY_SIMPLEX, 2, [0, 0, 255], thickness=4)
            elif num == 3:
                cv2.putText(self.output_img, 'there', [10, 50], cv2.FONT_HERSHEY_SIMPLEX, 2, [0, 0, 255], thickness=4)
            elif num == 4:
                cv2.putText(self.output_img, 'four', [10, 50], cv2.FONT_HERSHEY_SIMPLEX, 2, [0, 0, 255], thickness=4)
            elif num == 5:
                cv2.putText(self.output_img, 'five', [10, 50], cv2.FONT_HERSHEY_SIMPLEX, 2, [0, 0, 255], thickness=4)

	#writer:csdn月明Mo
	#获取手势函数
    def get_hand(self,img):
        self.img = img
        if self.img.shape[0] != 480 and self.img.shape[1] != 640:
            self.img = self.resize_img([640,480,3])
        self.output_img=np.copy(self.img)
        self.img_handle()
        self.detect()
        return self.output_img


def main():
    video=cv2.VideoCapture(0)
    hand=Img_handle(20000,1000,280)
    while video.isOpened():
        res,img=video.read()
        if res== True:
            newimg=hand.get_hand(img)
            cv2.imshow('frams1', newimg)
        if cv2.waitKey(1)==ord('q'):
            break

    cv2.destroyAllWindows()
    video.release()

if __name__=='__main__':
    main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/71868.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅谈Nacos注册中心集群分布式架构设计

前言 Nacos的压测性能是非常好的,这里是Nacos官方的压测报告。3节点(CPU 16核,内存32G)规模集群,压测容量服务数可达60W,实例注册数达110W,集群运行持续稳定,达到预期;注册/查询实例TPS达到 13…

ModStartBlog v6.3.0 任务调度重构,UEditor 升级

系统介绍 ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用,支持后台一键快速安装,让开发者能快的实现业务功能开发。 系统完全开源,基于 Apache 2.0 开源协议。 功能特性 丰富的模块市场,后台一键…

跨设备链路聚合 M-LAG

M-LAG(Multichassis Link Aggregation Group)即跨设备链路聚合组,是一种实现跨设备链路聚合的机制,如下图所示,将SwitchA和SwitchB通过peer-link链路连接并以同一个状态和Switch进行链路聚合协商,从而把链路…

学校介绍静态HTML网页设计作品 DIV布局学校官网模板代码 DW大学网站制作成品下载 HTML5期末大作业

🎉精彩专栏推荐 💭文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业: 【📚毕设项目精品实战案例 (10…

iOS app上架app store流程详解​

前提条件​ 在有效期内的苹果开发者账号(类型为个人或者公司账号)。还有一种情况,就是你的Apple ID被添加到公司开发者账号团队里面,这样也是可以的,但是需要叫管理员给你开通相应的账号权限,如下截图&…

[附源码]Python计算机毕业设计Django在线图书销售系统

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,我…

Vue | 有关Vue2路由知识点的一些总结,以及Vue3路由做出了哪些调整?

目录 Vue2: 1. 路由: 2. 路由规则: 3. 实现切换(active-class可配置高亮样式) 4. 指定展示位置 5. 路由的query参数 6. params传参: 7. 多级路由 8. 路由的props配置 9. 的replace属性 10. 编…

Android databinding之BindingMethod与BindingMethods介绍与使用(五)

一、介绍 前面几篇文章已介绍了很多data binding的用法,今天我将会介绍一个新的方法绑定BindingMethod的用法。 BindingMethod,从名字可以看出是绑定方法的,绑定的一般都是和布局有关,通过绑定来提高布局可扩展性。 二、使用 Bin…

把盏言欢,款款而谈,ChatGPT结合钉钉机器人(outgoing回调)打造人工智能群聊/单聊场景,基于Python3.10

就像黑火药时代里突然诞生的核弹一样,OpenAI的ChatGPT语言模型的横空出世,是人工智能技术发展史上的一个重要里程碑。这是一款无与伦比、超凡绝伦的模型,能够进行自然语言推理和对话,并且具有出色的语言生成能力。 好吧&#xff…

资产扫描神器ARL增强改造

拉取项目首先从GitHub克隆到服务器上。git clone https://github.com/ki9mu/ARL-plus-docker/修改配置文件因为ARL在配置文件里设置了黑名单,有时候项目为GOV或者EDU之类的时候无法进行扫描,所以在这里修改一下配置文件就可以解除限制。cd ARL-plus-dock…

Spring Boot3.0 GA系列全新版本-全新体验-学习案例1

SpringBoot3.0 GA 2022-11-24这是伟大的一天,Spring Boot进入了3.0时代,并会叩开JDK全面升级的浪潮 文章目录SpringBoot3.0 GA技术支持一、新建第一个mode?1.1、打开IDEA,新建项目1.2、选择 版本 和 依赖1.3、查看项目结构1.4、配…

vscode配置remote ssh

1. 安装插件 设置界面 右键最左边tab栏: 主体: vscode 插件: Remote SSH Linux主体: vscode-server 插件: C/C, CMake, CMake Tools, CodeLLDB, Rainbow Brackets, vscode-proto3, SVN 虚拟化主体: multipass linux发行版(比如ubuntu) 补充: multipass实例本地端口…

【C++ unordered_set set 和 unordered_map 和 map】

文章目录前言简单介绍哈希表,哈希结构什么时候用哈希表unordered_map操作likou第一题 两数之和unordered_set 基础操作unordered_set 实现总结前言 今天重新打开力扣,看到以前的签到题两数之和,以前的方法是双指针暴力解法,偶然看…

asp.net校园二手物品交易网站

目录 摘 要 Ⅰ Abstract Ⅱ 第一章 概述 1 1.1网站的开发背景 1 1.1.1学生二手物品交易置换网站的开发背景 1 1.1.2学生二手物品交易活动的现状 1 1.2 学生二手物品交易置换网站的研究方向和内容 2 1.2.1研究方向 2 1.2.2研究内容 2 1.3 学生二手物品交易置换网站的设计目标 2…

transformer中QKV的通俗理解(剩女与备胎的故事)

用vit的时候读了一下transformer的思想,前几天面试结束之后发现对QKV又有点忘记了, 写一篇文章来记录一下 参考链接: 哔哩哔哩:在线激情讲解transformer&Attention注意力机制(上)在线激情讲解transformer&Attention注意力机制(上&…

SpringCloud全系列知识(5)——微服务的部署(Docker)

微服务的部署(Docker) 一 初识Docker 1.项目部署问题 大型项目组件较多,运行环境较为复杂,部署和维护困难依赖关系复杂,容易出现兼容性问题开发,测试,生产环境有差异 2.解决依赖的兼容问题 …

[附源码]Python计算机毕业设计Django疫情期间小学生作业线上管理系统

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,我…

差分方程解的稳定性

Heine定理 存在的充要条件是: 取定义域内的任意数列,有 差分的定义 考虑离散型变量 一阶差分为: 二阶差分为: 线性差分方程的解 非齐次差分方程的解 满足初始条件的n阶非齐次线性差分方程 的解是存在且唯一的 非齐次线性差分方程的通解结构:齐次差分方程的解 线性相关与…

提升规则自治能力与原生分析能力、支持视频流接入处理

11 月, eKuiper 团队转入 1.8.0 版本的开发周期之中,目前已完成了一部分实用的新功能:添加了视频流 source,将边缘流式处理能力扩展到视频流领域,可以处理摄像头的视频流或者网络中的直播视频流;发布了通用…

[附源码]Python计算机毕业设计Django智能家电商城

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…