代码拉取完成,页面将自动刷新
import cv2
import numpy as np
import math
import random
def callback(): # 注意这里createTrackbar会向其传入参数即滑动条地址(几乎用不到),所以必须写一个参数
pass
def QMainWindow():
cap = cv2.VideoCapture(0)
cv2.namedWindow('frame')
cv2.resizeWindow('frame', 600, 800)
cv2.createTrackbar("change", "frame", 100, 255, callback) #活动条
while (cap.isOpened()):
ret, image = cap.read() # 读取摄像头每帧图片
image = cv2.flip(image, 1) #反转
cv2.rectangle(image, (100, 100), (300, 300), (0, 0, 255), 0) # 用红线画出手势识别框
# 滑动条控制颜色 可通过滑动条来调整亮度,提高识别率
value = cv2.getTrackbarPos('change', 'frame')
image_dst = np.uint8(image / 100 * value)
roi = image_dst[100:300, 100:300] # 选取图片中固定位置作为手势输入
kernel = np.ones((2, 2), np.uint8)
# 进行高斯滤波
lower_skin = np.array([0, 28, 70], dtype=np.uint8)
upper_skin = np.array([20, 255, 255], dtype=np.uint8)
mask = cv2.inRange(roi, lower_skin, upper_skin) #设阈值,去除背景部分第一个参数:hsv指的是原图
# lower_red指的是图像中低于这个lower_red的值,图像值变为0
#upper_red指的是图像中高于这个upper_red的值,图像值变为0
# 在lower_red~upper_red之间的值变成255
mask = cv2.dilate(mask, kernel, iterations=4)
mask = cv2.GaussianBlur(mask, (3, 3), 100)
# 基于hsv的肤色检测
hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
# 进行高斯滤波
mask = cv2.inRange(hsv, lower_skin, upper_skin)
mask = cv2.dilate(mask, kernel, iterations=4) #膨胀运算
mask = cv2.GaussianBlur(mask, (5, 5), 100)
# 找出轮廓image:参数是寻找轮廓的图像;
# mode:参数表示轮廓的检索模式,有四种(本文介绍的都是新的cv2接口):
# cv2.RETR_TREE:建立一个等级树结构的轮廓。
# method:轮廓的近似办法:
# cv2.CHAIN_APPROX_SIMPLE:压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
contours, h = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 返回一个list,list中每个元素都是图像中的一个轮廓
cnt = max(contours, default=0, key=lambda x: cv2.contourArea(x)) #面积
# epsilon = 0.0005 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, 0.05, True) #多边形拟合曲线
hull = cv2.convexHull(cnt) #计算几何之凸包 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)
# 定义凹凸点个数初始值为0
l = 0
try:
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(image_dst, "Please put hand in the window", (0, 50), font, 2, (0, 0, 255), 3,
cv2.LINE_AA)
else:
if arearatio < 12:
cv2.putText(image_dst, '0', (0, 50), font, 2, (0, 0, 255), 3, cv2.LINE_AA)
elif arearatio < 17.5:
cv2.putText(image_dst, "1", (0, 50), font, 2, (0, 0, 255), 3, cv2.LINE_AA)
else:
cv2.putText(image_dst, '1', (0, 50), font, 2, (0, 0, 255), 3, cv2.LINE_AA)
elif l == 2:
cv2.putText(image_dst, '2', (0, 50), font, 2, (0, 0, 255), 3, cv2.LINE_AA)
elif l == 3:
if arearatio < 27:
cv2.putText(image_dst, '3', (0, 50), font, 2, (0, 0, 255), 3, cv2.LINE_AA)
else:
cv2.putText(image_dst, '3', (0, 50), font, 2, (0, 0, 255), 3, cv2.LINE_AA)
elif l == 4:
cv2.putText(image_dst, '4', (0, 50), font, 2, (0, 0, 255), 3, cv2.LINE_AA)
elif l == 5:
cv2.putText(image_dst, '5', (0, 50), font, 2, (0, 0, 255), 3, cv2.LINE_AA)
# cv2.imshow('frame',frame)
cv2.imshow('mask', mask)
cv2.imshow('frame', image_dst)
key = cv2.waitKey(25) & 0xFF
if key == ord('q'): # 键盘q键退出
break
except:
pass
cv2.destroyAllWindows()
cap.release()
QMainWindow()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。