下面是详细讲解Python如何利用OpenCV实现手势识别的完整攻略。
1. 准备工作
在开始手势识别之前,我们需要确保OpenCV已经安装在我们的系统上。可以使用以下命令来检查:
$ python3
Python 3.7.3 (default, Apr 3 2019, 05:39:12)
[GCC 8.3.0] on linux
>>> import cv2
>>> cv2.__version__
'4.1.0'
如果OpenCV已经在我们的系统上安装并准备好使用,我们可以继续下一步。
2. 开始编写代码
2.1 导入必要的库
在开始编写代码之前,我们需要导入一些必要的Python库。
import cv2
import numpy as np
import math
2.2 读取视频并提取手势
我们需要读取从摄像头中获取的实时视频,并对每一帧进行处理。在处理每一帧期间,我们需要提取手势并将其显示在窗口中。以下是代码片段:
cap = cv2.VideoCapture(0)
while True:
_, img = cap.read()
cv2.imshow("Original", img)
# 处理每一帧
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
_, thresh = cv2.threshold(blur, 20, 255, cv2.THRESH_BINARY_INV)
cv2.imshow("Thresh", thresh)
# 寻找轮廓并绘制
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
try:
hierarchy = hierarchy[0]
except:
hierarchy = []
num_defects = 0
for i in range(len(contours)):
cnt = contours[i]
area = cv2.contourArea(cnt)
if area < 5000:
continue
# 近似边缘
epsilon = 0.0005 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
# 凸包
hull = cv2.convexHull(cnt)
# 指尖检测
defects = cv2.convexityDefects(cnt, cv2.convexHull(cnt, returnPoints=False))
cv2.drawContours(thresh, [cnt], 0, (0, 255, 0), 2)
cv2.drawContours(thresh, [approx], 0, (0, 0, 255), 2)
2.3 提取指尖并绘制轮廓
接下来,我们需要提取手势中每个手指的指尖,并在轮廓上进行标记。以下是代码片段:
for i in range(defects.shape[0]):
s, e, f, d = defects[i][0]
start = tuple(cnt[s][0])
end = tuple(cnt[e][0])
far = tuple(cnt[f][0])
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)
angle = math.acos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c)) * 57
if angle <= 90:
num_defects += 1
cv2.circle(img, far, 3, [255, 0, 0], -1)
cv2.line(img, start, end, [0, 255, 0], 2)
if num_defects == 0:
cv2.putText(img, "One", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, 2)
elif num_defects == 1:
cv2.putText(img, "Two", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, 2)
elif num_defects == 2:
cv2.putText(img, "Three", (5, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, 2)
elif num_defects == 3:
cv2.putText(img, "Four", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, 2)
elif num_defects == 4:
cv2.putText(img, "Five", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, 2)
cv2.imshow("Gesture", img)
2.4 运行程序并调试
我们的程序已经准备好使用了,我们可以使用以下命令运行程序:
$ python3 gesture_recognition.py
在调试期间,你可能需要修改一些值和参数来使程序工作正常。
3. 示例说明
以下是两个示例说明:
3.1 利用手势控制鼠标移动
我们可以利用手势来控制鼠标的移动。具体步骤如下:
- 打开摄像头并读取每一帧数据。
- 如果我们的双手放在视觉范围内,则在视频的中心位置绘制一个绿色的圆。
- 如果我们提高一只手,那么我们的程序将把它视为鼠标指针。我们可以使用手部的运动来控制鼠标的移动。
以下是代码示例:
# 启动摄像头
cap = cv2.VideoCapture(0)
while True:
# 读取摄像头中的数据
_, img = cap.read()
img = cv2.flip(img, 1)
# 将图片转为灰色并进行模糊处理
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (15, 15), 0)
# 检测我们的手
_, thresh = cv2.threshold(blurred, 50, 255, cv2.THRESH_BINARY_INV)
# 绘制绿色圆圈
cv2.circle(img, (320, 240), 15, (0, 255, 0), 2)
# 检测手部运动来控制鼠标的移动
# ...
cv2.imshow("Gesture", img)
# 按'q'键退出
if cv2.waitKey(10) & 0xFF == ord('q'):
break
# 释放摄像头并销毁窗口
cap.release()
cv2.destroyAllWindows()
3.2 利用手势控制电灯开关
我们可以利用手势来控制电灯的开关。具体步骤如下:
- 打开摄像头并读取每一帧数据。
- 如果我们的右手在视频中平且手指朝下,则关闭电灯;如果我们的右手在视频中竖着,则打开电灯。
以下是代码示例:
# 启动摄像头
cap = cv2.VideoCapture(0)
while True:
# 读取摄像头中的数据
_, img = cap.read()
img = cv2.flip(img, 1)
# 将图片转为灰色并进行模糊处理
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (15, 15), 0)
# 检测我们的手势
_, thresh = cv2.threshold(blurred, 50, 255, cv2.THRESH_BINARY_INV)
# 寻找手的轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 检测每个手的手指数目
finger_count = 0
for i in range(len(contours)):
cnt = contours[i]
if cv2.contourArea(cnt) > 5000:
hull = cv2.convexHull(cnt, returnPoints=False)
defects = cv2.convexityDefects(cnt, hull)
if defects is not None:
for j in range(defects.shape[0]):
s, e, f, d = defects[j][0]
start = tuple(cnt[s][0])
end = tuple(cnt[e][0])
far = tuple(cnt[f][0])
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)
angle = math.acos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c)) * 57
if angle <= 90:
finger_count += 1
if finger_count == 0:
cv2.putText(img, 'Light Off', (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 2, 255)
else:
cv2.putText(img, 'Light On', (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 2, 255)
cv2.imshow("Gesture", img)
# 按'q'键退出
if cv2.waitKey(10) & 0xFF == ord('q'):
break
# 释放摄像头并销毁窗口
cap.release()
cv2.destroyAllWindows()
以上是如何利用OpenCV实现手势识别的完整攻略,希望对您有所帮助!
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python如何利用opencv实现手势识别 - Python技术站