之前用MediaPipe做过侦测到中指就打马赛克的主题,
下方有朋友留言提议能不能做「侦测到爱心就放大」的功能,
时隔两天终於做出来啦!! 谢谢这位朋友的建议 (不然我真的快没梗了)
开发环境
程序码
import cv2
import mediapipe as mp
import math
def enlarge(img, left_up, right_down):
new_img = img.copy()
size_w = abs(left_up[0] - right_down[0])
size_h = abs(left_up[1] - right_down[1])
# 得到正方形区域的image
img_rec = img[left_up[1]:right_down[1], left_up[0]:right_down[0]]
try:
# 将此区域放大
img_rec = cv2.resize(img_rec, (size_w*2, size_h*2), interpolation=cv2.INTER_CUBIC)
except:
return None
center = [(left_up[0] + right_down[0])//2, (left_up[1] + right_down[1])//2] # [x, y]
# 将原图中正方形区域取代为放大後的图
for i in range(center[1]-size_h, center[1]+size_h):
for j in range(center[0]-size_w, center[0]+size_w):
try:
new_img[i][j] = img_rec[i - (center[1]-size_h)][j - (center[0]-size_w)]
except:
continue
return new_img
def vector_2d_angle(v1,v2): # 求出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_ = 100000.
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 hand_gesture(angle_list): # 侦测手指是否比爱心
gesture_str = None
if 100000. not in angle_list:
if (angle_list[0]<60) and (angle_list[1]<100) and (angle_list[2]>40) and (angle_list[3]>40) and (angle_list[4]>40):
gesture_str = "love"
return gesture_str
def detect():
mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(
static_image_mode=False,
max_num_hands=1,
min_detection_confidence=0.75,
min_tracking_confidence=0.75)
# 开启视讯镜头读取器
cap = cv2.VideoCapture(0)
while True:
# 侦测影像中的手部
_, frame = cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame= cv2.flip(frame,1)
results = hands.process(frame)
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
keypoint_pos = []
for i in range(21):
x = hand_landmarks.landmark[i].x*frame.shape[1]
y = hand_landmarks.landmark[i].y*frame.shape[0]
keypoint_pos.append((x,y))
if keypoint_pos:
# 得到各手指的夹角资讯
angle_list = hand_angle(keypoint_pos)
# 根据角度判断此手势是否为爱心
gesture_str = hand_gesture(angle_list)
if gesture_str == "love":
left_up = [int(keypoint_pos[8][0]) - 20 , int(keypoint_pos[8][1]) - 10]
right_down = [int(keypoint_pos[3][0]) + 20 , int(keypoint_pos[3][1]) + 10]
frame_processed = enlarge(frame, left_up, right_down)
if frame_processed is not None:
frame = frame_processed
cv2.imshow('MediaPipe Hands', frame)
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
if __name__ == '__main__':
detect()
成果发表会
不知道是不是我拇指太短还是怎样,它有时候会侦测不到我在比爱心(扶额
如果有人知道更准确的判断方法可以跟我说一下吗 感谢><
<<: Day6中秋节最後还是要吃肉肉阿-欧式地中海风马铃薯柠檬炖鸡
本篇同步发布於Blog:[解题] LeetCode - 125 Valid Palindrome 平...
https://bootstrap5.hexschool.com/docs/5.1/getting-...
在上一篇Error Function中,可以看到依照w的不同决定了线的偏差值多寡, 此篇要介绍的是当...
显示工作表每一列的值 wb = load_workbook("Top 10 most St...
前言 昨天谈到敏捷的重点是其背後的精神,而 Scrum 也不例外,但为什麽 Scrum 的导入还是这...