...僵硬...
太久没做Python识别类的项目了,所以今晚想放松放松,不过代码整的有点生疏,不仅写得慢,还不小心把我最爱的Ubuntu给整没了,只能明天重装!因为一些手部指令出来的效果不太好,本人上镜有点不舒服,所以就不上图啦!O(∩_∩)O!
需安装模块:
opencv-python==4.5.4.60
opencv-contrib-python==4.5.5.62
mediapipe==0.8.9.1
opencv-python-headless==4.1.2.30
通过这些模块,可以通过手势识别,做出一些与OpenCV有关的有趣指令,如图片加密解密,添加水印,将图片修改成为灰度图...
# pip install opencv-python-headless==4.1.2.30 -i https://pypi.douban.com/simple
import cv2
import mediapipe as mp
import math
import time
import numpy as np
from PIL import Image, ImageTk
import tkinter as tk
cap = cv2.VideoCapture(0)
mpHands = mp.solutions.hands
hands = mpHands.Hands(
static_image_mode=False,
max_num_hands=2,
model_complexity=1,
min_detection_confidence=0.5,
min_tracking_confidence=0.5
)
mpDraw = mp.solutions.drawing_utils
handLmsStyle = mpDraw.DrawingSpec(color=(255,0,255),thickness=5) # 点
handConStyle = mpDraw.DrawingSpec(color=(0,255,0),thickness=10) # 线
pTime = 0
cTime = 0
def vector_2d_angle(v1,v2):
''' 求解二维向量的角度 '''
v1_x=v1[0]
v1_y=v1[1]
v2_x=v2[0]
v2_y=v2[1]
try:
angle_= math.degrees(math.acos((v1_x*v2_x+v1_y*v2_y)/(((v1_x**2+v1_y**2)**0.5)*((v2_x**2+v2_y**2)**0.5))))
except:
angle_ = 65535.
if angle_ > 180.:
angle_ = 65535.
return angle_
def hand_angle(hand_):
''' 获取对应手相关向量的二维角度,根据角度确定手势'''
angle_list = []
# thumb 大拇指角度
angle_ = vector_2d_angle(
((int(hand_[0][0])- int(hand_[2][0])),(int(hand_[0][1])-int(hand_[2][1]))),
((int(hand_[3][0])- int(hand_[4][0])),(int(hand_[3][1])- int(hand_[4][1])))
)
angle_list.append(angle_)
# index 食指角度
angle_ = vector_2d_angle(
((int(hand_[0][0])-int(hand_[6][0])),(int(hand_[0][1])- int(hand_[6][1]))),
((int(hand_[7][0])- int(hand_[8][0])),(int(hand_[7][1])- int(hand_[8][1])))
)
angle_list.append(angle_)
# middle 中指角度
angle_ = vector_2d_angle(
((int(hand_[0][0])- int(hand_[10][0])),(int(hand_[0][1])- int(hand_[10][1]))),
((int(hand_[11][0])- int(hand_[12][0])),(int(hand_[11][1])- int(hand_[12][1])))
)
angle_list.append(angle_)
# ring 无名指角度
angle_ = vector_2d_angle(
((int(hand_[0][0])- int(hand_[14][0])),(int(hand_[0][1])- int(hand_[14][1]))),
((int(hand_[15][0])- int(hand_[16][0])),(int(hand_[15][1])- int(hand_[16][1])))
)
angle_list.append(angle_)
# pink 小拇指角度
angle_ = vector_2d_angle(
((int(hand_[0][0])- int(hand_[18][0])),(int(hand_[0][1])- int(hand_[18][1]))),
((int(hand_[19][0])- int(hand_[20][0])),(int(hand_[19][1])- int(hand_[20][1])))
)
angle_list.append(angle_)
return angle_list
def h_gesture(angle_list):
'''
# 二维约束的方法定义手势
# fist five gun love one six three thumbup yeah
'''
thr_angle = 65.
thr_angle_thumb = 53.
thr_angle_s = 49.
gesture_str = None
if 65535. not in angle_list:
if (angle_list[0]>5) and (angle_list[1]<thr_angle_s) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):
gesture_str = "one"
elif (angle_list[0]>thr_angle_thumb) and (angle_list[1]<thr_angle_s) and (angle_list[2]<thr_angle_s) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):
gesture_str = "two"
elif (angle_list[0]<thr_angle_s) and (angle_list[1]<thr_angle_s) and (angle_list[2]<thr_angle_s) and (angle_list[3]<thr_angle_s) and (angle_list[4]<thr_angle_s):
gesture_str = "five"
elif (angle_list[0]<thr_angle_s) and (angle_list[1]>thr_angle) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]<thr_angle_s):
gesture_str = "six"
elif (angle_list[0]<thr_angle_s) and (angle_list[1]>thr_angle) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):
gesture_str = "thumbUp"
return gesture_str
# 2.Canny边缘检测
# 读入灰度图像
pic1 = cv2.imread('pic1.png',0)
# 高斯模糊图像降噪 (5,5)卷积核,卷积核越大,对图像越敏感
pic2 = cv2.GaussianBlur(pic1, (5, 5), 0)
# Canny边缘检测,左为低阈值,右为高阈值,阈值越小边缘越多也越杂
pic2canny = cv2.Canny(pic2, 20, 70)
# 闭运算连接断点
kernel = np.ones((2, 2), np.uint8)
jiance = cv2.morphologyEx(pic2canny, cv2.MORPH_CLOSE, kernel)
# 3.旋转图片
pic2 = cv2.imread('pic1.png')
xy = cv2.flip(pic2,-1)
# 4. 加密解密
cst = cv2.cvtColor(pic1,cv2.COLOR_GRAY2RGB)
retval4 = cv2.imwrite("cst.jpg",cst) # 彩色图
img1 = cv2.imread('cst.jpg')
w,h,c = img1.shape
key = np.random.randint(0,256,size=[w,h,c],dtype=np.uint8) # 生成一个和图片一样大小的图片
encryption = cv2.bitwise_xor(img1,key) # 按位异或,相同为0,不同为1
decryption = cv2.bitwise_xor(encryption,key)
while (cap.isOpened()):
ret,frame = cap.read()
if ret:
# 把BGR图像转换为RGB形式
imgRGB = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
frame = cv2.flip(imgRGB,1)
result = hands.process(frame)
print(result.multi_hand_landmarks)
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
imgWidth = frame.shape[1]
imgHeight = frame.shape[0]
if result.multi_hand_landmarks:
for handLms in result.multi_hand_landmarks:
mpDraw.draw_landmarks(frame, handLms, mpHands.HAND_CONNECTIONS, handLmsStyle, handConStyle)
hand_local = []
for i in range(21):
x = handLms.landmark[i].x*frame.shape[1]
y = handLms.landmark[i].y*frame.shape[0]
hand_local.append((x,y))
for j,lm in enumerate(handLms.landmark):
xPos = int(lm.x * imgWidth)
yPos = int(lm.y * imgHeight)
cv2.putText(frame,str(j),(xPos-25,yPos+5),cv2.FONT_HERSHEY_SIMPLEX,0.4,(0,0,255),2)
if j == 4:
cv2.circle(frame,(xPos,yPos),10,(0,0,255),cv2.FILLED)
print(i,xPos,yPos)
if hand_local:
angle_list = hand_angle(hand_local)
gesture_str = h_gesture(angle_list)
cv2.putText(frame,gesture_str,(0,100),0,1.3,(0,0,255),3)
if gesture_str == 'one':
cv2.imwrite('pic1.png',frame)
elif gesture_str == 'two':
cv2.imshow('jxw.png', jiance)
elif gesture_str == 'five':
cv2.imshow("result2", encryption)
cv2.imshow("result3", decryption)
elif gesture_str == 'six':
cv2.imshow("xy", xy)
elif gesture_str == 'thumbUp':
# break
cv2.destroyAllWindows()
cTime = time.time()
fps = 1/(cTime-pTime)
pTime = cTime
cv2.putText(frame,f"FPS:{int(fps)}",(30,50),cv2.FONT_HERSHEY_SIMPLEX,1,(0,60,30),3)
cv2.imshow('img',frame)
k = cv2.waitKey(1)
if k == ord('q'):
break
cap.release()
# 5.GUI编程
"""第一步,实例化object,建立窗口window、"""
window = tk.Tk()
"""第二步,给窗口的可视化起名字"""
window.title('My_Window')
"""第三步,给窗口制定大小,(长 乘(即x) 宽)"""
window.geometry('1000x1000')
"""第四步,创建画布"""
canvas = tk.Canvas(window, bg='white', height=500, width=1000)
wifi_img = Image.open('pic1.png')
wifi_img_up = Image.open('up.gif')
wifi_img_r = Image.open('r.gif')
wifi_img_d = Image.open('d.gif')
wifi_img_l = Image.open('l.gif')
image_file = ImageTk.PhotoImage(wifi_img)
image_file_up = ImageTk.PhotoImage(wifi_img_up)
image_file_r = ImageTk.PhotoImage(wifi_img_r)
image_file_d = ImageTk.PhotoImage(wifi_img_d)
image_file_l = ImageTk.PhotoImage(wifi_img_l)
image = canvas.create_image(500, 0, anchor='n', image=image_file)
"""第五步,放置画布"""
canvas.pack()
"""第六步,触发函数,用来一定指定图形"""
def moveit_up():
canvas.move(image, 0, -6)
def moveit_r():
canvas.move(image, 6, 0)
def moveit_d():
canvas.move(image, 0, 6)
def moveit_l():
canvas.move(image, -6, 0)
"""第七步,设置按钮"""
b = tk.Button(window, image=image_file_up, text="move item", command=moveit_up).place(x=450, y=500)
b = tk.Button(window, image=image_file_r, text="move item", command=moveit_r).place(x=550, y=600)
b = tk.Button(window, image=image_file_d, text="move item", command=moveit_d).place(x=450, y=700)
b = tk.Button(window, image=image_file_l, text="move item", command=moveit_l).place(x=350, y=600)
"""第八步,主窗口循环显示"""
window.mainloop()
cv2.waitKey(0)
cv2.destroyAllWindows()
# 知识点:
"""
高斯降噪、边缘检测
打开摄像头
手部识别
旋转
开运算闭运算
GUI
加密解密
键盘控制
"""
因为要用一只手截图,所以图片中只有一只手,哈哈!
Hello
Good job
文章到这里就结束了!希望大家能多多支持Python(系列)!六个月带大家学会Python,私聊我,可以问关于本文章的问题!以后每天都会发布新的文章,喜欢的点点关注!一个陪伴你学习Python的新青年!不管多忙都会更新下去,一起加油!
Editor:Lonelyroots
网友评论