530 lines
22 KiB
Python
530 lines
22 KiB
Python
import time
|
|
from pymouse import PyMouse
|
|
import cv2
|
|
import mediapipe as mp
|
|
import math
|
|
import util
|
|
import detect
|
|
import win32gui
|
|
import win32con
|
|
import sys
|
|
|
|
|
|
def hand_angle(hand_):
|
|
'''
|
|
获取对应手相关向量的二维角度,根据角度确定手势
|
|
'''
|
|
angle_list = []
|
|
# ---------------------------- thumb 大拇指角度
|
|
angle_ = util.Util.vector_2d_angle(
|
|
((int(hand_[2][0]) - int(hand_[3][0])), (int(hand_[2][1]) - int(hand_[3][1]))),
|
|
((int(hand_[3][0]) - int(hand_[4][0])), (int(hand_[3][1]) - int(hand_[4][1])))
|
|
)
|
|
angle_list.append(angle_)
|
|
# ---------------------------- index 食指角度
|
|
angle_ = util.Util.vector_2d_angle(
|
|
((int(hand_[5][0]) - int(hand_[6][0])), (int(hand_[5][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_ = util.Util.vector_2d_angle(
|
|
((int(hand_[9][0]) - int(hand_[10][0])), (int(hand_[9][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_ = util.Util.vector_2d_angle(
|
|
((int(hand_[13][0]) - int(hand_[14][0])), (int(hand_[13][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_ = util.Util.vector_2d_angle(
|
|
((int(hand_[17][0]) - int(hand_[18][0])), (int(hand_[17][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 judge_zero(is_finger_straight):
|
|
return not is_finger_straight[1] and not is_finger_straight[2] and \
|
|
not is_finger_straight[3] and not is_finger_straight[4]
|
|
|
|
|
|
def judge_two(is_finger_straight):
|
|
return is_finger_straight[1] and is_finger_straight[2] and \
|
|
not is_finger_straight[3] and not is_finger_straight[4]
|
|
|
|
|
|
def judge_three(is_finger_straight):
|
|
return is_finger_straight[1] and is_finger_straight[2] and \
|
|
is_finger_straight[3] and not is_finger_straight[4]
|
|
|
|
|
|
def judge_four(is_finger_straight):
|
|
return is_finger_straight[1] and is_finger_straight[2] and \
|
|
is_finger_straight[3] and is_finger_straight[4]
|
|
|
|
|
|
def judge_five(is_finger_straight):
|
|
return is_finger_straight[1] and is_finger_straight[2] and \
|
|
is_finger_straight[3] and is_finger_straight[4]
|
|
|
|
|
|
class Identify:
|
|
def __init__(self, control_flag, array):
|
|
self.rgb_image = None
|
|
self.control_flag = control_flag
|
|
self.array = array
|
|
self.mouse = PyMouse()
|
|
self.left_hand_flag = False
|
|
self.right_hand_flag = False
|
|
self.catch_person_flag = False
|
|
self.position_x = 0
|
|
self.position_y = 0
|
|
self.image = []
|
|
self.image_height = 0
|
|
self.image_width = 0
|
|
self.person_results = []
|
|
self.identify_results = []
|
|
self.left_hand_points = []
|
|
self.right_hand_points = []
|
|
self.left_hands = []
|
|
self.right_hands = []
|
|
self.left_angle_list = []
|
|
self.right_angle_list = []
|
|
self.is_left_finger_straight = [False, False, False, False, False]
|
|
self.is_right_finger_straight = [False, False, False, False, False]
|
|
self.is_identify = False
|
|
self.last_control_flag = 0
|
|
self.page_up_count = 0
|
|
self.page_down_count = 0
|
|
self.end_count = 0
|
|
self.pencil_count = 0
|
|
self.step_up = 0
|
|
self.step_down = 0
|
|
self.last_wrist_point = (0, 0)
|
|
self.now_time = 0
|
|
self.lase_time = 0
|
|
self.flag = 0
|
|
self.mp_drawing = mp.solutions.drawing_utils
|
|
self.mp_hands = mp.solutions.hands
|
|
self.mp_poses = mp.solutions.pose
|
|
self.ml_identify = []
|
|
self.hands = self.mp_hands.Hands(
|
|
static_image_mode=False,
|
|
max_num_hands=2,
|
|
min_detection_confidence=0.75,
|
|
min_tracking_confidence=0.75)
|
|
self.poses = self.mp_poses.Pose(
|
|
min_detection_confidence=0.5,
|
|
min_tracking_confidence=0.5)
|
|
self.mp_face = mp.solutions.face_detection
|
|
self.face_detection = self.mp_face.FaceDetection(min_detection_confidence=0.5)
|
|
|
|
def begin(self, over_flag):
|
|
capture = cv2.VideoCapture(0)
|
|
last_time = 0
|
|
self.ml_identify = detect.YOLOV5()
|
|
screen_width = self.mouse.screen_size()[0]
|
|
time1 = time.time()
|
|
x1, y1, x2, y2 = 0, 0, 0, 0
|
|
count = 0
|
|
while 1:
|
|
count += 1
|
|
if over_flag.value == 1:
|
|
sys.exit(0)
|
|
ret, self.image = capture.read()
|
|
self.image = cv2.resize(self.image, (320, 240), interpolation=cv2.INTER_LINEAR)
|
|
# fps = 1 / (self.now_time - self.lase_time)
|
|
# self.lase_time = self.now_time
|
|
# print("fps = " + str(fps))
|
|
# self.ml_identify.infer(image=self.image)
|
|
# continue
|
|
# self.catch_person_flag = True
|
|
# if not self.catch_person_flag:
|
|
# self.catch_person_flag = True
|
|
if not self.catch_person_flag:
|
|
self.person_results.clear()
|
|
self.left_hands.clear()
|
|
self.right_hands.clear()
|
|
self.deal_with_image()
|
|
self.find_points()
|
|
x1, y1, x2, y2 = self.find_target_person()
|
|
# print("no no no no no no no no no no no no no")
|
|
else:
|
|
# print("in True")
|
|
# print(x1, y1, x2, y2)
|
|
self.deal_with_image()
|
|
self.image = self.image[y1:y2, x1:x2]
|
|
|
|
# self.identify_results = self.hands.process(self.image)
|
|
|
|
self.is_identify = False
|
|
self.left_hand_flag = False
|
|
self.right_hand_flag = False
|
|
for i in range(5):
|
|
self.is_left_finger_straight[i] = False
|
|
self.is_right_finger_straight[i] = False
|
|
self.left_hand_points.clear()
|
|
self.right_hand_points.clear()
|
|
self.get_hand_points()
|
|
# print("---------------------")
|
|
# print(self.left_hand_flag)
|
|
# print(self.left_hand_points)
|
|
# print(self.right_hand_flag)
|
|
# print(self.right_hand_points)
|
|
self.judge_finger_straight()
|
|
flag = self.judge_control()
|
|
if flag:
|
|
self.flag = flag
|
|
# print("this flag = " + str(flag))
|
|
now_time = time.time()
|
|
self.array[0] = self.position_x
|
|
self.array[1] = self.position_y
|
|
self.array[2] = x2 - x1
|
|
self.array[3] = y2 - y1
|
|
if now_time - last_time < 1:
|
|
continue
|
|
last_time = now_time
|
|
self.catch_person_flag = not self.judge_catch_over()
|
|
# print("**************")
|
|
# for i in range(5):
|
|
# print(self.is_finger_straight[i])
|
|
# x = position[0]
|
|
# y = position[1]
|
|
|
|
# control_flag = flag
|
|
self.control_flag.value = self.flag
|
|
# print("self.v.value = " + str(self.flag))
|
|
# print("final_control_flag = " + str(self.flag))
|
|
self.flag = 0
|
|
|
|
cv2.namedWindow("Video")
|
|
WindowName = "Video"
|
|
cv2.imshow(WindowName, self.image)
|
|
hwnd = win32gui.FindWindow(None, WindowName) # 获取句柄,然后置顶
|
|
CVRECT = cv2.getWindowImageRect(WindowName)
|
|
win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, screen_width - 320, 0, CVRECT[2], CVRECT[3],
|
|
win32con.SWP_SHOWWINDOW)
|
|
# cv2.imshow("Video", self.image)
|
|
if cv2.waitKey(1) & 0xFF == ord('q'):
|
|
break
|
|
capture.release()
|
|
cv2.destroyAllWindows()
|
|
|
|
def judge_catch_over(self):
|
|
if not self.left_hand_flag:
|
|
return False
|
|
if not self.right_hand_flag:
|
|
return False
|
|
if not judge_zero(self.is_left_finger_straight):
|
|
return False
|
|
if not judge_zero(self.is_right_finger_straight):
|
|
return False
|
|
if util.Util.get_distance(self.left_hand_points[6], self.right_hand_points[6]) / \
|
|
util.Util.get_distance(self.left_hand_points[5], self.left_hand_points[9]) > 2.5:
|
|
return False
|
|
return True
|
|
|
|
def find_points(self):
|
|
if self.identify_results.multi_handedness:
|
|
for i in range(len(self.identify_results.multi_handedness)):
|
|
if self.identify_results.multi_handedness[i].classification[0].label == "Left":
|
|
left_hand_points = []
|
|
for hand_landmarks in self.identify_results.multi_hand_landmarks[i].landmark:
|
|
if self.image_height == 0:
|
|
self.image_height, self.image_width, c = self.image.shape
|
|
cx, cy = int(hand_landmarks.x * self.image_width), int(hand_landmarks.y * self.image_height)
|
|
left_hand_points.append((cx, cy))
|
|
# self.mp_drawing.draw_landmarks(
|
|
# self.image, self.identify_results.multi_hand_landmarks[i], self.mp_hands.HAND_CONNECTIONS)
|
|
# if self.identify_results.multi_handedness[i].classification[0].score > 0.5:
|
|
# self.left_hand_flag = True
|
|
# self.is_identify = True
|
|
self.left_hands.append(left_hand_points)
|
|
else:
|
|
right_hand_points = []
|
|
for hand_landmarks in self.identify_results.multi_hand_landmarks[i].landmark:
|
|
if self.image_height == 0:
|
|
self.image_height, self.image_width, c = self.image.shape
|
|
cx, cy = int(hand_landmarks.x * self.image_width), int(hand_landmarks.y * self.image_height)
|
|
right_hand_points.append((cx, cy))
|
|
# self.is_identify = True
|
|
# self.mp_drawing.draw_landmarks(
|
|
# self.image, self.identify_results.multi_hand_landmarks[i], self.mp_hands.HAND_CONNECTIONS)
|
|
# if self.identify_results.multi_handedness[i].classification[0].score > 0.5:
|
|
# self.right_hand_flag = True
|
|
# self.is_identify = True
|
|
self.right_hands.append(right_hand_points)
|
|
|
|
def find_target_person(self):
|
|
target_scopes = self.ml_identify.infer(image=self.image)
|
|
for result in target_scopes:
|
|
# cv2.rectangle(self.image, (result[0], result[1]), (result[2], result[3]), (0, 0, 255), 2)
|
|
one_person_result = [result, [], []]
|
|
for left_hand in self.left_hands:
|
|
if util.Util.is_in_rectangle(left_hand[0], result):
|
|
one_person_result[1] = left_hand
|
|
break
|
|
for right_hand in self.right_hands:
|
|
if util.Util.is_in_rectangle(right_hand[0], result):
|
|
one_person_result[2] = right_hand
|
|
break
|
|
self.person_results.append(one_person_result)
|
|
if self.person_results:
|
|
person_result = self.find_catch_pose()
|
|
if self.catch_person_flag:
|
|
return person_result[0]
|
|
else:
|
|
return 0, 0, 0, 0
|
|
else:
|
|
return 0, 0, 0, 0
|
|
|
|
def find_catch_pose(self):
|
|
max_distance = 0
|
|
max_index = 0
|
|
for i in range(len(self.person_results)):
|
|
person_result = self.person_results[i]
|
|
if not person_result[1]:
|
|
continue
|
|
if not person_result[2]:
|
|
continue
|
|
standard_distance = util.Util.get_distance(person_result[1][7], person_result[1][8])
|
|
if standard_distance == 0:
|
|
continue
|
|
if util.Util.get_distance(person_result[1][4], person_result[2][4]) / standard_distance > 2:
|
|
continue
|
|
if util.Util.get_distance(person_result[1][8], person_result[2][8]) / standard_distance > 1:
|
|
continue
|
|
distance = util.Util.get_distance(person_result[1][0], person_result[1][8])
|
|
if distance > max_distance:
|
|
max_distance = distance
|
|
max_index = i
|
|
self.catch_person_flag = True
|
|
return self.person_results[max_index]
|
|
|
|
def deal_with_image(self):
|
|
self.image = cv2.flip(self.image, 1)
|
|
self.rgb_image = cv2.cvtColor(self.image, cv2.COLOR_BGR2RGB)
|
|
self.identify_results = self.hands.process(self.rgb_image)
|
|
|
|
def get_hand_points(self):
|
|
if not self.identify_results.multi_handedness:
|
|
return 0
|
|
for i in range(len(self.identify_results.multi_handedness)):
|
|
if self.identify_results.multi_handedness[i].classification[0].label == "Left":
|
|
for hand_landmarks in self.identify_results.multi_hand_landmarks[i].landmark:
|
|
if self.image_height == 0:
|
|
self.image_height, self.image_width, c = self.image.shape
|
|
cx, cy = int(hand_landmarks.x * self.image_width), int(hand_landmarks.y * self.image_height)
|
|
self.left_hand_points.append((cx, cy))
|
|
# self.mp_drawing.draw_landmarks(
|
|
# self.image, self.identify_results.multi_hand_landmarks[i], self.mp_hands.HAND_CONNECTIONS)
|
|
if self.identify_results.multi_handedness[i].classification[0].score > 0.5:
|
|
self.left_hand_flag = True
|
|
self.is_identify = True
|
|
|
|
else:
|
|
for hand_landmarks in self.identify_results.multi_hand_landmarks[i].landmark:
|
|
if self.image_height == 0:
|
|
self.image_height, self.image_width, c = self.image.shape
|
|
cx, cy = int(hand_landmarks.x * self.image_width), int(hand_landmarks.y * self.image_height)
|
|
self.right_hand_points.append((cx, cy))
|
|
# self.is_identify = True
|
|
# self.mp_drawing.draw_landmarks(
|
|
# self.image, self.identify_results.multi_hand_landmarks[i], self.mp_hands.HAND_CONNECTIONS)
|
|
if self.identify_results.multi_handedness[i].classification[0].score > 0.5:
|
|
self.right_hand_flag = True
|
|
self.is_identify = True
|
|
|
|
def judge_finger_straight(self):
|
|
if self.is_identify:
|
|
if self.left_hand_flag:
|
|
self.left_angle_list = hand_angle(hand_=self.left_hand_points)
|
|
for i in range(5):
|
|
self.is_left_finger_straight[i] = util.Util.is_straight(self.left_angle_list[i])
|
|
if self.right_hand_flag:
|
|
self.right_angle_list = hand_angle(hand_=self.right_hand_points)
|
|
for i in range(5):
|
|
self.is_right_finger_straight[i] = util.Util.is_straight(self.right_angle_list[i])
|
|
|
|
def judge_one(self, is_finger_straight):
|
|
if self.left_hand_flag:
|
|
self.position_x = self.left_hand_points[8][0]
|
|
self.position_y = self.left_hand_points[8][1]
|
|
# elif self.right_hand_flag:
|
|
# self.position_x = self.right_hand_points[8][0]
|
|
# self.position_y = self.right_hand_points[8][1]
|
|
return is_finger_straight[1] and not is_finger_straight[2] and \
|
|
not is_finger_straight[3] and not is_finger_straight[4]
|
|
|
|
def judge_step_one(self, is_left):
|
|
if is_left:
|
|
if judge_five(self.is_left_finger_straight) and self.left_hand_points[8][0] < self.left_hand_points[0][
|
|
0] and \
|
|
self.left_hand_points[12][0] < self.left_hand_points[0][0] and \
|
|
self.left_hand_points[16][0] < self.left_hand_points[0][0] and self.left_hand_points[20][0] < \
|
|
self.left_hand_points[0][0]:
|
|
return True
|
|
else:
|
|
if judge_five(self.is_right_finger_straight) and self.right_hand_points[8][0] > self.right_hand_points[0][
|
|
0] and \
|
|
self.right_hand_points[12][0] > self.right_hand_points[0][0] and \
|
|
self.right_hand_points[16][0] > self.right_hand_points[0][0] and self.right_hand_points[20][0] > \
|
|
self.right_hand_points[0][0]:
|
|
return True
|
|
return False
|
|
|
|
def judge_step_two(self, is_left):
|
|
if is_left:
|
|
if judge_five(self.is_left_finger_straight) and self.left_hand_points[8][0] > self.left_hand_points[0][
|
|
0] and \
|
|
self.left_hand_points[12][0] > self.left_hand_points[0][0] and \
|
|
self.left_hand_points[16][0] > self.left_hand_points[0][0] and self.left_hand_points[20][0] > \
|
|
self.left_hand_points[0][0]:
|
|
return True
|
|
else:
|
|
if judge_five(self.is_right_finger_straight) and self.right_hand_points[8][0] < self.right_hand_points[0][
|
|
0] and \
|
|
self.right_hand_points[12][0] < self.right_hand_points[0][0] and \
|
|
self.right_hand_points[16][0] < self.right_hand_points[0][0] and self.right_hand_points[20][0] < \
|
|
self.right_hand_points[0][0]:
|
|
return True
|
|
return False
|
|
|
|
def judge_step_three(self):
|
|
if self.left_hand_flag:
|
|
if self.left_hand_points[20][1] < self.left_hand_points[0][1]:
|
|
return True
|
|
else:
|
|
if self.right_hand_points[20][1] < self.right_hand_points[0][1]:
|
|
return True
|
|
return False
|
|
|
|
def judge_page_up(self):
|
|
if not self.right_hand_flag:
|
|
return False
|
|
if self.step_up == 0:
|
|
self.lase_time = time.time()
|
|
if self.step_up == 0 and self.judge_step_three():
|
|
self.step_up = 1
|
|
if self.step_up == 1 and self.judge_step_one(False):
|
|
self.step_up = 2
|
|
elif self.step_up == 2 and self.judge_step_two(False):
|
|
self.step_up = 3
|
|
# elif self.step_up == 2 and judge_zero(self.is_right_finger_straight):
|
|
# self.step_up = 3
|
|
# elif self.step_up == 3:
|
|
# self.step_up = 0
|
|
now_time = time.time()
|
|
if now_time - self.lase_time > 3:
|
|
self.lase_time = now_time
|
|
self.step_up = 0
|
|
return False
|
|
else:
|
|
if self.step_up == 3:
|
|
self.lase_time = now_time
|
|
self.step_up = 0
|
|
return True
|
|
return False
|
|
|
|
def judge_page_down(self):
|
|
if not self.left_hand_flag:
|
|
return False
|
|
if self.step_down == 0:
|
|
self.lase_time = time.time()
|
|
if self.step_down == 0 and self.judge_step_three():
|
|
self.step_down = 1
|
|
# print("step = 1")
|
|
if self.step_down == 1 and self.judge_step_one(True):
|
|
self.step_down = 2
|
|
# print("step = 2")
|
|
elif self.step_down == 2 and self.judge_step_two(True):
|
|
self.step_down = 3
|
|
# print("step = 3")
|
|
now_time = time.time()
|
|
if now_time - self.lase_time > 3:
|
|
self.lase_time = now_time
|
|
self.step_down = 0
|
|
return False
|
|
else:
|
|
if self.step_down == 3:
|
|
self.lase_time = now_time
|
|
self.step_down = 0
|
|
return True
|
|
return False
|
|
|
|
def judge_end(self):
|
|
if not self.left_hand_flag:
|
|
self.end_count = 0
|
|
return False
|
|
if not judge_zero(self.is_left_finger_straight):
|
|
self.end_count = 0
|
|
return False
|
|
self.end_count += 1
|
|
if self.end_count > 10:
|
|
self.end_count = 0
|
|
return True
|
|
return False
|
|
|
|
def judge_system_over(self):
|
|
if not self.judge_one(self.is_left_finger_straight):
|
|
return False
|
|
if not self.judge_one(self.is_right_finger_straight):
|
|
return False
|
|
standard_distance = util.Util.get_distance(self.left_hand_points[7], self.right_hand_points[8])
|
|
if standard_distance == 0:
|
|
return False
|
|
# print(util.Util.get_distance(self.left_hand_points[8], self.right_hand_points[8]) / standard_distance)
|
|
if util.Util.get_distance(self.left_hand_points[8], self.right_hand_points[8]) / standard_distance < 1:
|
|
return True
|
|
return False
|
|
|
|
# def judge_pencil(self):
|
|
# if not self.judge_one(self.is_left_finger_straight):
|
|
# return False
|
|
# if self.right_hand_flag:
|
|
# return False
|
|
# self.pencil_count += 1
|
|
# if self.pencil_count > 5:
|
|
# self.pencil_count = 0
|
|
|
|
def judge_control(self):
|
|
if self.is_identify:
|
|
# print("len = " + str(len(self.identify_results.multi_handedness)))
|
|
# print("left is " + str(self.left_hand_flag))
|
|
# print("right is " + str(self.right_hand_flag))
|
|
if judge_two(self.is_left_finger_straight):
|
|
# print("1")
|
|
return 1
|
|
elif self.judge_page_up():
|
|
# print("2")
|
|
return 2
|
|
elif self.judge_page_down():
|
|
# print("3")
|
|
return 3
|
|
elif self.judge_one(self.is_left_finger_straight) and not self.right_hand_flag:
|
|
# print("4")
|
|
return 4
|
|
elif self.judge_one(self.is_left_finger_straight) and judge_zero(self.is_right_finger_straight):
|
|
# print("5")
|
|
return 5
|
|
elif self.judge_end():
|
|
# print("6")
|
|
return 6
|
|
elif self.judge_system_over():
|
|
# print("7")
|
|
return 7
|
|
# else:
|
|
# # print("other")
|
|
# else:
|
|
# print("no_hand_points")
|
|
return 0
|
|
|
|
#
|
|
# identify = Identify()
|
|
# identify.begin()
|