尝试实现手势控制计算机(持续跟进)
基于语言python,主要运用的包有cv2等
1.在python中实现摄像头的图像获取
安装opencv:
1. 安装依赖
pip install --upgrade setuptools
pip install numpy Matplotlib
2.安装opencv python版
pip install opencv-python
实现摄像头图像获取代码
#-*- coding:utf-8 -*-
import cv2
import time
cap = cv2.VideoCapture(0)#调取摄像头,0表示系统默认摄像头
while True:
ret,photo = cap.read()#读取图像
cv2.imshow('please take our photo!',photo)#将图像传送自窗口
key = cv2.waitKey(2)#设置等待时间,若为0图像定格
if key == ord(" "):#输入空格截图
filename = time.strftime('%Y%m%d-%H%M%S')+".jpg"#文件名为当前时间
cv2.imwrite(filename,photo)#保存位置
if key == ord('q'):#输入q退出
break
3.第一次尝试
想用去背景后获取二值图像,然后检测凸包的方式来识别手势,效果很差
实时去掉背景代码
#-*- coding:utf-8 -*-
import cv2
import time
cap = cv2.VideoCapture(0)#调取摄像头,0表示系统默认摄像头
#构建3*3的椭圆核
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
#创建BackgroundSubtractorMOG2(OpenCV自带的一种背景消减方法
fgbg = cv2.createBackgroundSubtractorMOG2(detectShadows=False)
while True:
ret,frame = cap.read()#读取图像
fgmask = fgbg.apply(frame)
fgmask = cv2.morphologyEx(fgmask,cv2.MORPH_OPEN,kernel)
im,contours,hierarchy = cv2.findContours(fgmask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
frame = cv2.rectangle(frame,(150,100),(300,250),(0,255,0),2)
# for c in contours:
# # 计算各轮廓的周长
# perimeter = cv2.arcLength(c, True)
# if perimeter > 188:
# # 找到一个直矩形(不会旋转)
# x, y, w, h = cv2.boundingRect(c)
# # 画出这个矩形
# cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow('frame', frame)
cv2.imshow('fgmask', fgmask)
key = cv2.waitKey(30)#设置等待时间,若为0图像定格
if key == ord(" "): # 输入空格截图
# filename = time.strftime('%Y%m%d-%H%M%S') + ".jpg" # 文件名为当前时间
filename = "test.jpg"
cv2.imwrite(filename, fgmask[100:250,150:300]) # 保存位置
elif key == 27:
break
cap.release()
cv2.destroyAllWindows()#释放并销毁窗口
比对手势形状代码(完全行不通)
# -*- coding:utf-8 -*-
import numpy as np
import cv2
from matplotlib import pyplot as plt
im = cv2.imread('test1.jpg')#需要识别的图
im2 = cv2.imread('ex2.jpg')#标准例图
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))#3*3的椭圆核
img = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)#用这个方式转换的原因是最后输出时希望能看到彩色的的轮廓图
img2 = cv2.cvtColor(im2,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(img,127,255,0)
ret,thresh2 = cv2.threshold(img2,127,255,0)#将图像二值化
dst = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel)
dst2 = cv2.morphologyEx(thresh2,cv2.MORPH_OPEN,kernel)#将图像进行开运算
img,contours,hierarchy = cv2.findContours(dst,1,2)
max = 0
maxl = -1
for i in range(len(contours)):
if cv2.contourArea(contours[i]) > max :
max = cv2.contourArea(contours[i])
maxl = i
print(maxl)
print(len(contours))
cnt = contours[maxl]#找到需识别图中最大的轮廓,即手的轮廓
img,contours,hierarchy = cv2.findContours(dst2,1,2)
cnt2 = contours[len(contours)-1]#对照例图中手的轮廓
cv2.drawContours(im,[cnt],0,(0,255,0),3)
ret = cv2.matchShapes(cnt,cnt2,1,0.0)
print(ret)#将两轮廓进行比对
# cv2.imshow('img',img)
# cv2.imshow('thresh',thresh)
cv2.imshow('im',im)
cv2.waitKey(0)
识别凸包代码(准确度低)
# -*- coding:utf-8 -*-
import numpy as np
import cv2
from matplotlib import pyplot as plt
im = cv2.imread('test.jpg')
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))#3*3的椭圆核
img = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)#用这个方式转换的原因是最后输出时希望能看到彩色的的轮廓图
ret,thresh = cv2.threshold(img,127,255,0)
dst = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel)
img,contours,hierarchy = cv2.findContours(dst,1,2)
max = 0
maxl = -1
for i in range(len(contours)):
if cv2.contourArea(contours[i]) > max :
max = cv2.contourArea(contours[i])
maxl = i
print(maxl)
print(len(contours))
cnt = contours[maxl]#找到需识别图中最大的轮廓,即手的轮廓
#显示凸包
hull = cv2.convexHull(cnt,returnPoints=True)
print(hull)
cv2.polylines(im, [hull], True, (0, 255, 0), 2)
#凸性检测
# hull = cv2.convexHull(cnt,returnPoints=False)
# defect = cv2.convexityDefects(cnt,hull)
#
# for i in range(defect.shape[0]):
# s,e,f,d = defect[i,0]
# start = tuple(cnt[s][0])
# end = tuple(cnt[e][0])
# far = tuple(cnt[f][0])
# # cv2.line(im,start,end,[0,255,0],2)
# # cv2.circle(im,start,5,[0,0,255],-1)
# # cv2.circle(im,end,5,[0,0,255],-1)
# cv2.circle(im,far,5,[0,0,255],-1)
M = cv2.moments(cnt)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
cv2.circle(im,(cx,cy),5,[0,0,255],-1)
cv2.imshow('img',im)
cv2.waitKey(0)
分析原因,是因为
1)背景杂质太多,且由于使用了笔记本自带摄像头,无法单独识别到手
2)光线不均匀,导致背景减除时无法准确识别到整个手的完整轮廓
综上,该方法在要求实现条件更为广泛的情况下不太行得通