1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
|
from typing import List
import cv2
import mediapipe as mp
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QLabel, QDialog, QVBoxLayout
from PyQt5.QtGui import QImage, QPixmap
import sys,time
# Initialize MediaPipe
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_hands = mp.solutions.hands
class HandLandmarkThread(QThread):
change_pixmap_signal = pyqtSignal(QImage)
coordinates_signal = pyqtSignal(list) # Signal to emit coordinates
cameraReadySignal = None
dead_signal = pyqtSignal() # Signal to emit coordinates
running = True
last_query_time = time.time()
def __init__(self, parent = None):
super().__init__(parent)
def setCameraReadySignal(self,sig):
self.cameraReadySignal = sig
def stopRunning(self):
self.running = False
def run(self):
# Start video capture (use 0 for the default webcam)
self.last_query_time = time.time()
cap = cv2.VideoCapture(0)
with mp_hands.Hands(
model_complexity=0,
min_detection_confidence=0.5,
min_tracking_confidence=0.5
) as hands:
st = time.time()
print('cam started',st)
self.cameraReadySignal.emit()
while cap.isOpened() and self.running:
if time.time() > self.last_query_time+5: # No activity for 5 seconds.
self.running = False
success, image = cap.read()
if not success:
continue
# Convert image to RGB for processing
image.flags.writeable = False
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
results = hands.process(image_rgb)
# Draw hand landmarks and emit the coordinates
image.flags.writeable = True
image_bgr = cv2.cvtColor(image_rgb, cv2.COLOR_RGB2BGR)
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
self.last_query_time = time.time()
mp_drawing.draw_landmarks(
image_bgr,
hand_landmarks,
mp_hands.HAND_CONNECTIONS,
mp_drawing_styles.get_default_hand_landmarks_style(),
mp_drawing_styles.get_default_hand_connections_style()
)
# Emit the coordinates of the index finger tip
image_height, image_width, _ = image.shape
#index_finger_tip = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP]
#coords = (index_finger_tip.x * image_width, index_finger_tip.y * image_height)
# Get coordinates for all landmarks
hand_coords = []
for landmark in hand_landmarks.landmark:
x = landmark.x * image_width
y = landmark.y * image_height
hand_coords.append((x, y))
self.coordinates_signal.emit(hand_coords)
break #only need one hand for now.
# Convert to QImage and emit signal to update the UI
qt_image = self.convert_cv_qt(image_bgr)
self.change_pixmap_signal.emit(qt_image)
if (not self.running): # Close
break
cap.release()
self.dead_signal.emit()
def convert_cv_qt(self, cv_img):
"""Convert from an OpenCV image to QImage for display."""
rgb_image = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
h, w, ch = rgb_image.shape
bytes_per_line = ch * w
qt_image = QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888)
return qt_image
def ping(self):
self.last_query_time = time.time()
|