84 lines
2.8 KiB
Python
84 lines
2.8 KiB
Python
import mediapipe as mp
|
|
import cv2, numpy as np, time, fitz
|
|
from helper import compute_distance
|
|
from config import PINCH_THRESHOLD, RELEASE_THRESHOLD
|
|
|
|
# ----- Initialize Hand Detector -----
|
|
mp_hands = mp.solutions.hands
|
|
mp_draw = mp.solutions.drawing_utils
|
|
hands = mp_hands.Hands(
|
|
static_image_mode=False,
|
|
max_num_hands=2,
|
|
min_detection_confidence=0.7,
|
|
min_tracking_confidence=0.5
|
|
)
|
|
|
|
start_pt = None # measurement start point
|
|
measuring = False # measurement in progress
|
|
|
|
def detect_hands(frame):
|
|
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
|
rgb.flags.writeable = False
|
|
results = hands.process(rgb)
|
|
|
|
return results
|
|
|
|
|
|
def check_hand(hand, frame_vis, object_calibrating):
|
|
h, w, _ = frame_vis.shape
|
|
|
|
fingertip_idx = None
|
|
fingertip_mid = None
|
|
|
|
mp_draw.draw_landmarks(frame_vis, hand, mp_hands.HAND_CONNECTIONS)
|
|
# get index and middle finger tips and PIP joints
|
|
idx_tip = hand.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP]
|
|
mid_tip = hand.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_TIP]
|
|
ix, iy = int(idx_tip.x * w), int(idx_tip.y * h)
|
|
mx, my = int(mid_tip.x * w), int(mid_tip.y * h)
|
|
fingertip_idx = (ix, iy)
|
|
fingertip_mid = (mx, my)
|
|
|
|
# draw fingertips
|
|
cv2.circle(frame_vis, fingertip_idx, 8, (255,255,0), -1)
|
|
cv2.circle(frame_vis, fingertip_mid, 8, (0,255,0), -1)
|
|
|
|
measuring, start_pt = is_measuring(frame_vis, hand, object_calibrating)
|
|
|
|
return fingertip_idx, measuring, start_pt
|
|
|
|
def is_measuring(frame_vis, hand, object_calibrating):
|
|
global measuring, start_pt
|
|
h, w, _ = frame_vis.shape
|
|
|
|
idx_tip = hand.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP]
|
|
idx_pip = hand.landmark[mp_hands.HandLandmark.INDEX_FINGER_PIP]
|
|
mid_tip = hand.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_TIP]
|
|
mid_pip = hand.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_PIP]
|
|
|
|
ix, iy = int(idx_tip.x * w), int(idx_tip.y * h)
|
|
mx, my = int(mid_tip.x * w), int(mid_tip.y * h)
|
|
fingertip_idx = (ix, iy)
|
|
fingertip_mid = (mx, my)
|
|
|
|
# check extension
|
|
index_ext = idx_tip.y < idx_pip.y
|
|
middle_ext = mid_tip.y < mid_pip.y
|
|
|
|
# if measurement in progress but fingers no longer both extended, stop measuring
|
|
if measuring and not (index_ext and middle_ext):
|
|
measuring = False
|
|
|
|
# pinch distance
|
|
pinch = compute_distance(fingertip_idx, fingertip_mid)
|
|
cv2.putText(frame_vis, f"Pinch: {int(pinch)} px", (10,30), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0),2)
|
|
|
|
# measurement gesture
|
|
if not object_calibrating and index_ext and middle_ext:
|
|
if pinch < PINCH_THRESHOLD and not measuring:
|
|
measuring = True
|
|
start_pt = fingertip_idx
|
|
elif pinch > RELEASE_THRESHOLD and measuring:
|
|
measuring = False
|
|
|
|
return measuring, start_pt |