基于OpenCV的手势识别完整项目(Python3.7)

您所在的位置:网站首页 云台识别不了手势 基于OpenCV的手势识别完整项目(Python3.7)

基于OpenCV的手势识别完整项目(Python3.7)

2024-07-10 01:44| 来源: 网络整理| 查看: 265

这是我的本科毕设题目,刚开始接触机器学习这方面,感谢CSDN和GitHub上的大佬,网上类似项目很多,方法也有很多,自己顺带进行了整理,边做毕设边分享一下自己学习心得吧,也算是梳理一下所学知识,各大佬有什么好的建议还请指出,不吝赐教。

项目简介:基于Win10 + Python3.7的环境,利用Python的OpenCV、Sklearn和PyQt5等库搭建了一个较为完整的手势识别系统,用于识别日常生活中1-10的静态手势。

整个项目的资源:https://download.csdn.net/download/qq_41562704/11471042(包含手势库和已训练的模型,可以直接运行使用)

环境:Win10 + Python3.7 + OpenCV3.4.5,各个库的安装就不多说了

最终的效果图如图所示:

 

整个项目分为四个部分,即预处理,特征提取,模型训练,界面设计

预处理

1.获取手势

2.图像预处理

2.1去噪

2.2 肤色检测 + 二值化处理

2.3 形态学处理

2.4 轮廓提取

特征提取

3 傅里叶算子提取

4 建立特征库

4.1 数据增强

4.2 计算手势库的特征

模型训练

5 训练SVM模型

界面设计

6 PyQt设计界面

预处理

这部分需要完成摄像头录制手势后,提取出手的轮廓线

这部分参考资料:

https://blog.csdn.net/ifruoxi/article/details/78091954(获取手势,基于Python)

https://blog.csdn.net/qq_22527639/article/details/81501565(肤色检测:方法全,理论介绍的也很全面,基于C++)

https://blog.csdn.net/shadow_guo/article/details/43602051(基于RGB空间肤色检测,基于Python)

https://blog.csdn.net/weixin_40893939/article/details/84527037(基于HSV空间和YCrCb空间肤色检测,基于Python)

https://blog.csdn.net/Eastmount/article/details/83581277(腐蚀膨胀理论介绍,基于Python)

https://blog.csdn.net/dz4543/article/details/80655067(轮廓提取,基于Python)

1.获取手势

主要是调用OpenCV,创建main.py和 picture.py

main.py 当前负责录像,picture负责处理图像

main.py

import cv2 import picture as pic font = cv2.FONT_HERSHEY_SIMPLEX #设置字体 size = 0.5 #设置大小 width, height = 300, 300 #设置拍摄窗口大小 x0,y0 = 300, 100 #设置选取位置 cap = cv2.VideoCapture(0) #开摄像头 if __name__ == "__main__": while(1): ret, frame = cap.read() #读取摄像头的内容 frame = cv2.flip(frame, 2) roi = pic.binaryMask(frame, x0, y0, width, height) #取手势所在框图并进行处理 key = cv2.waitKey(1) & 0xFF#按键判断并进行一定的调整 #按'j''l''u''j'分别将选框左移,右移,上移,下移 #按'q'键退出录像 if key == ord('i'): y0 += 5 elif key == ord('k'): y0 -= 5 elif key == ord('l'): x0 += 5 elif key == ord('j'): x0 -= 5 if key == ord('q'): break cv2.imshow('frame', frame) #播放摄像头的内容 cap.release() cv2.destroyAllWindows() #关闭所有窗口 2.图像预处理

预处理在picture.py中完成。

预处理的主要步骤为:去噪 -> 肤色检测 -> 二值化 -> 形态学处理 -> 轮廓提取,其中最麻烦的两项为肤色检测和轮廓提取。

2.1去噪

即滤波,主要是为了实现对图像噪声的消除,增强图像的效果,其实个人感觉这里滤波的作用不是很明显,也可以选择不滤波,在肤色检测后会有二次滤波。

#以3*3的模板进行均值滤波 blur = cv2.blur(roi, (3,3)) #以3*3的模板进行高斯滤波,最后一个参数表示x与y方向的标准差,给0的话,函数会自己运算 blur = cv2.GaussianBlur(roi, (3,3), 0) #中值滤波 blur = cv2.medianBlur(roi,5) #双边滤波,9为区域的直径,后面两个参数是空间高斯函数标准差和灰度值相似性高斯函数标准差 blur = cv2.bilateralFilter(img,9,75,75)

均值滤波器、高斯滤波器、中值滤波器、双边滤波器都可以进行使用。推荐使用双边滤波器,该滤波器考虑了图像的空间关系,也考虑图像的灰度关系。双边滤波同时使用了空间高斯权重和灰度相似性高斯权重,确保了边界不会被模糊掉。不过我在处理中直接省去了去噪这个过程。

2.2 肤色检测 + 二值化处理

picture.py

方法一:基于RGB颜色空间

判断条件:

在均匀光照下,R>95 AND G>40 B>20 AND MAX(R,G,B)-MIN(R,G,B)>15 AND ABS(R-G)>15 AND R>G AND R>B;

在侧光拍摄环境下,R>220 AND G>210 AND B>170 AND ABS(R-G)B AND G>B

import cv2 import numpy as np def binaryMask(frame, x0, y0, width, height): cv2.rectangle(frame,(x0,y0),(x0+width, y0+height),(0,255,0)) #画出截取的手势框图 roi = frame[y0:y0+height, x0:x0+width] #获取手势框图 cv2.imshow("roi", roi) #显示手势框图 res = skinMask(roi) #进行肤色检测 cv2.imshow("res", res) #显示肤色检测后的图像 return res ##########方法一################### ##########BGR空间的手势识别######### def skinMask(roi): rgb = cv2.cvtColor(roi, cv2.COLOR_BGR2RGB) #转换到RGB空间 (R,G,B) = cv2.split(rgb) #获取图像每个像素点的RGB的值,即将一个二维矩阵拆成三个二维矩阵 skin = np.zeros(R.shape, dtype = np.uint8) #掩膜 (x,y) = R.shape #获取图像的像素点的坐标范围 for i in range(0, x): for j in range(0, y): #判断条件,不在肤色范围内则将掩膜设为黑色,即255 if (abs(R[i][j] - G[i][j]) > 15) and (R[i][j] > G[i][j]) and (R[i][j] > B[i][j]): if (R[i][j] > 95) and (G[i][j] > 40) and (B[i][j] > 20) \ and (max(R[i][j],G[i][j],B[i][j]) - min(R[i][j],G[i][j],B[i][j]) > 15): skin[i][j] = 255 elif (R[i][j] > 220) and (G[i][j] > 210) and (B[i][j] > 170): skin[i][j] = 255 res = cv2.bitwise_and(roi,roi, mask = skin) #图像与运算 return res

效果图:

方法二:基于HSV颜色空间

判断条件:0=50

肤色检测的方式不同影响的是skinMask,之后的代码只是修改skinMask函数,picture.py中其他代码不需要改动。

##########方法二################### ########HSV颜色空间H范围筛选法###### def skinMask(roi): low = np.array([0, 48, 50]) #最低阈值 high = np.array([20, 255, 255]) #最高阈值 hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) #转换到HSV空间 mask = cv2.inRange(hsv,low,high) #掩膜,不在范围内的设为255 res = cv2.bitwise_and(roi,roi, mask = mask) #图像与运算 return res

效果图:

方法三:椭圆肤色检测模型

在YCrCb空间,肤色像素点会聚集到一个椭圆区域。先定义一个椭圆模型,然后将每个RGB像素点转换到YCrCb空间比对是否在椭圆区域,是的话判断为皮肤。

##########方法三################### #########椭圆肤色检测模型########## def skinMask(roi): skinCrCbHist = np.zeros((256,256), dtype= np.uint8) cv2.ellipse(skinCrCbHist, (113,155),(23,25), 43, 0, 360, (255,255,255), -1) #绘制椭圆弧线 YCrCb = cv2.cvtColor(roi, cv2.COLOR_BGR2YCR_CB) #转换至YCrCb空间 (y,Cr,Cb) = cv2.split(YCrCb) #拆分出Y,Cr,Cb值 skin = np.zeros(Cr.shape, dtype = np.uint8) #掩膜 (x,y) = Cr.shape for i in range(0, x): for j in range(0, y): if skinCrCbHist [Cr[i][j], Cb[i][j]] > 0: #若不在椭圆区间中 skin[i][j] = 255 res = cv2.bitwise_and(roi,roi, mask = skin) return res

效果图:

 

方法四:YCrCb颜色空间的Cr分量+Otsu法阈值分割算法

针对YCrCb中Cr分量的处理,对CR通道单独进行Otsu处理,Otsu方法opencv里用threshold,Otsu算法是对图像的灰度级进行聚类。

################方法四#################### ####YCrCb颜色空间的Cr分量+Otsu法阈值分割算法 def skinMask(roi): YCrCb = cv2.cvtColor(roi, cv2.COLOR_BGR2YCR_CB) #转换至YCrCb空间 (y,cr,cb) = cv2.split(YCrCb) #拆分出Y,Cr,Cb值 cr1 = cv2.GaussianBlur(cr, (5,5), 0) _, skin = cv2.threshold(cr1, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) #Ostu处理 res = cv2.bitwise_and(roi,roi, mask = skin) return res

效果图:

方法五:Cr,Cb范围筛选法

该方法与方法一、二类似,不同的只是颜色空间不相同

判断条件:133



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3