Python+OpenCV3简单手势识别

文章目录

  • 安装相关库
  • 原理简述
  • 代码
  • 效果实现

今天教大家一个有趣的玩法,如何利用Python+opencv3实现简单的手势识别。当然网上也有相关教程,但绝大多数给出的代码拿来之后你是不能直接用的,这对于拿来主义的同学来说简直太“禽兽”了。所以今天我也会给出所有代码,只要配置好环境就可以运行。话不多说接下来就进入正题。

安装相关库

这个安装库的重要性就不用我多说了,但凡是想直接用人家的代码,就要安装人家运行所需的全部库。

pip install opencv-python

pip install opencv-contrib-python

pip install numpy

原理简述

第一步: 加载图片,无论你是用cv2导入一张静态手势图片还是用摄像头导入实时图片都可以。
第二步: 肤色检测,基于HSV颜色空间H,S,V范围筛选法 HSV中 7 第三步: 进行高斯滤波
第四步: 边缘轮廓检测
第五步: 求出手势的凹凸点
第六步: 利用凹凸点个数判断当前手势,例如:0个凹凸点就是拳头,4个凹点就是布也就是5。

代码

接下来就是你们最开心的 时刻了-看代码。哈,你们高兴的太早了,我的代码注释很少的。所以。。。。我尽量添上注释。

我明说了,代码虽然可以运行,但有BUG,要在一个地方加异常判断,否则如果没检测到手的话程序就会报错退出,至于在哪加相信也不难,你们好好优化吧。问我,我可是要收费的。手动dog

# _*_ coding: UTF-8 _*_
import cv2
import numpy as np
import math
cap = cv2.VideoCapture(0)

while(cap.isOpened()):
    ret,frame = cap.read() # 读取摄像头每帧图片
    
    frame = cv2.flip(frame,1)
    kernel = np.ones((2,2),np.uint8)
    roi = frame[100:300,100:300] # 选取图片中固定位置作为手势输入

    cv2.rectangle(frame,(100,100),(300,300),(0,0,255),0) # 用红线画出手势识别框
    # 基于hsv的肤色检测
    hsv = cv2.cvtColor(roi,cv2.COLOR_BGR2HSV)
    lower_skin = np.array([0,28,70],dtype=np.uint8)
    upper_skin = np.array([20, 255, 255],dtype=np.uint8)
    
    # 进行高斯滤波
    mask = cv2.inRange(hsv,lower_skin,upper_skin)
    mask = cv2.dilate(mask,kernel,iterations=4)
    mask = cv2.GaussianBlur(mask,(5,5),100)
    
    # 找出轮廓
    contours,h = cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    cnt = max(contours,key=lambda x:cv2.contourArea(x))
    epsilon = 0.0005*cv2.arcLength(cnt,True)
    approx = cv2.approxPolyDP(cnt,epsilon,True)
    hull = cv2.convexHull(cnt)
    areahull = cv2.contourArea(hull)
    areacnt = cv2.contourArea(cnt)
    arearatio = ((areahull-areacnt)/areacnt)*100
    # 求出凹凸点
    hull = cv2.convexHull(approx,returnPoints=False)
    defects = cv2.convexityDefects(approx,hull)
    l=0 #定义凹凸点个数初始值为0 
    for i in range(defects.shape[0]):
        s,e,f,d, = defects[i,0]
        start = tuple(approx[s][0])
        end = tuple(approx[e][0])
        far = tuple(approx[f][0])
        pt = (100,100)

        a = math.sqrt((end[0]-start[0])**2+(end[1]-start[1])**2)
        b = math.sqrt((far[0] - start[0]) ** 2 + (far[1] - start[1]) ** 2)
        c = math.sqrt((end[0]-far[0])**2+(end[1]-far[1])**2)
        s = (a+b+c)/2
        ar = math.sqrt(s*(s-a)*(s-b)*(s-c))
	# 手指间角度求取
        angle = math.acos((b**2 + c**2 -a**2)/(2*b*c))*57

        if angle<=90 and d>20:
            l+=1
            cv2.circle(roi,far,3,[255,0,0],-1)
        cv2.line(roi,start,end,[0,255,0],2) # 画出包络线
    l+=1
    font = cv2.FONT_HERSHEY_SIMPLEX
    # 下面的都是条件判断,也就是知道手势后你想实现神么功能就写下面判断里就行了。
    if l==1:
        if areacnt<2000:
            cv2.putText(frame,"put hand in the window",(0,50),font,2,(0,0,255),3,cv2.LINE_AA)
        else:
            if arearatio<12:
                cv2.putText(frame,'0',(0,50),font,2,(0,0,255),3,cv2.LINE_AA)
            elif arearatio<17.5:
                cv2.putText(frame,"1",(0,50),font,2,(0,0,255),3,cv2.LINE_AA)
            else:
                cv2.putText(frame,'1',(0,50),font,2,(0,0,255),3,cv2.LINE_AA)
    elif l==2:
        cv2.putText(frame,'2',(0,50),font,2,(0,0,255),3,cv2.LINE_AA)
    elif l==3:
        if arearatio<27:
            cv2.putText(frame,'3',(0,50),font,2,(0,0,255),3,cv2.LINE_AA)
        else:
            cv2.putText(frame,'3',(0,50),font,2,(0,0,255),3,cv2.LINE_AA)
    elif l==4:
        cv2.putText(frame,'4',(0,50),font,2,(0,0,255),3,cv2.LINE_AA)
    elif l==5:
        cv2.putText(frame,'5',(0,50),font,2,(0,0,255),3,cv2.LINE_AA)
    cv2.imshow('frame',frame)
    cv2.imshow('mask', mask)
    k = cv2.waitKey(25)& 0xff  
    if k == 27:     # 键盘Esc键退出
        break
cv2.destroyAllWindows()
cap.release()

效果实现

由于个人隐私(其实也就没洗头)外加笔记本200万像素的原因,截图我就不漏脸了,怕帅到你们。我漏手就行了。
检测时,注意把手放到红色方框内检测。

Python+OpenCV3简单手势识别_第1张图片
Python+OpenCV3简单手势识别_第2张图片
Python+OpenCV3简单手势识别_第3张图片
Python+OpenCV3简单手势识别_第4张图片
Python+OpenCV3简单手势识别_第5张图片
Python+OpenCV3简单手势识别_第6张图片

娱乐时刻

欧!我的上帝啊,瞧瞧这篇糟糕的文章,简直和隔壁蔡徐坤阿姨打的篮球一样糟糕!要是我的叔叔老八在这里的话,他一定会把奥利给塞你嘴里!我发誓他一定会这么做的!

你可能感兴趣的:(python学习)