尝试实现手势控制计算机(持续跟进)

基于语言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)光线不均匀,导致背景减除时无法准确识别到整个手的完整轮廓

综上,该方法在要求实现条件更为广泛的情况下不太行得通

 

posted @ 2018-07-05 15:57  Zodiac7  阅读(580)  评论(0编辑  收藏  举报