Spaces:
Sleeping
Sleeping
| import cv2 | |
| import mediapipe as mp | |
| import numpy as np | |
| from .models import get_mediapipe_options, load_custom_models | |
| from .animal_detector import AnimalDetector | |
| class GestureProcessor: | |
| def __init__(self): | |
| self.clf, self.label_encoder = load_custom_models() | |
| self.options = get_mediapipe_options() | |
| self.recognizer = mp.tasks.vision.GestureRecognizer.create_from_options(self.options) | |
| # Conexões com cores para cada parte da mão | |
| # Formato: (ponto1, ponto2, cor_BGR) | |
| self.CONNECTIONS = [ | |
| # Polegar - Vermelho | |
| ((0,1), (0, 0, 255)), | |
| ((1,2), (0, 0, 255)), | |
| ((2,3), (0, 0, 255)), | |
| ((3,4), (0, 0, 255)), | |
| # Indicador - Verde | |
| ((0,5), (0, 255, 0)), | |
| ((5,6), (0, 255, 0)), | |
| ((6,7), (0, 255, 0)), | |
| ((7,8), (0, 255, 0)), | |
| # Médio - Azul | |
| ((9,10), (255, 0, 0)), | |
| ((10,11), (255, 0, 0)), | |
| ((11,12), (255, 0, 0)), | |
| # Anelar - Amarelo | |
| ((13,14), (0, 255, 255)), | |
| ((14,15), (0, 255, 255)), | |
| ((15,16), (0, 255, 255)), | |
| # Mindinho - Magenta | |
| ((0,17), (255, 0, 255)), | |
| ((17,18), (255, 0, 255)), | |
| ((18,19), (255, 0, 255)), | |
| ((19,20), (255, 0, 255)), | |
| # Palma - Ciano | |
| ((5,9), (255, 255, 0)), | |
| ((9,13), (255, 255, 0)), | |
| ((13,17), (255, 255, 0)) | |
| ] | |
| # Inicializa o detector de animais | |
| try: | |
| self.animal_detector = AnimalDetector() | |
| self.animals_enabled = True | |
| except Exception as e: | |
| print(f"Aviso: Detector de animais não disponível: {e}") | |
| self.animal_detector = None | |
| self.animals_enabled = False | |
| def process_frame(self, frame, draw_landmarks=True, detect_animals=True): | |
| labels = [] | |
| animals = [] | |
| gesture_image = None | |
| frame = cv2.flip(frame, 1) | |
| h, w, _ = frame.shape | |
| rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) | |
| # Detecção de animais (antes de desenhar as landmarks) | |
| if detect_animals and self.animals_enabled and self.animal_detector: | |
| try: | |
| animal_detections = self.animal_detector.detect(rgb_frame, confidence_threshold=0.4) | |
| if animal_detections: | |
| frame = self.animal_detector.draw_detections(frame, animal_detections) | |
| animals = [ | |
| { | |
| 'animal': det['class'], | |
| 'confidence': det['confidence'] | |
| } | |
| for det in animal_detections | |
| ] | |
| except Exception as e: | |
| print(f"Erro na detecção de animais: {e}") | |
| mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=rgb_frame) | |
| timestamp_ms = int(cv2.getTickCount() / cv2.getTickFrequency() * 1000) | |
| recognition_result = self.recognizer.recognize_for_video(mp_image, timestamp_ms) | |
| if recognition_result.hand_landmarks: | |
| for i, hand_landmarks in enumerate(recognition_result.hand_landmarks): | |
| # 1. Desenho condicional | |
| if draw_landmarks: | |
| # Linhas coloridas por parte da mão | |
| for (conn, color) in self.CONNECTIONS: | |
| p1, p2 = hand_landmarks[conn[0]], hand_landmarks[conn[1]] | |
| cv2.line(frame, (int(p1.x*w), int(p1.y*h)), (int(p2.x*w), int(p2.y*h)), color, 2, cv2.LINE_AA) | |
| # Pontos Brancos | |
| for lm in hand_landmarks: | |
| cv2.circle(frame, (int(lm.x*w), int(lm.y*h)), 4, (255, 255, 255), -1, cv2.LINE_AA) | |
| # 2. Predição (Sempre roda) | |
| # --- PREDIÇÃO (Sempre ativa) --- | |
| try: | |
| hand_label = recognition_result.handedness[i][0].category_name | |
| h_val = 0 if hand_label == 'Left' else 1 | |
| # Monta o vetor de características | |
| feat = [h_val] | |
| for lm in hand_landmarks: feat.extend([lm.x, lm.y, lm.z]) | |
| features = np.array(feat).reshape(1, -1) | |
| # PEGA A PROBABILIDADE REAL DO MODELO | |
| probabilities = self.clf.predict_proba(features)[0] | |
| prediction_idx = np.argmax(probabilities) | |
| # CALCULA A CONFIANÇA REAL (0.0 a 1.0) | |
| confidence_raw = float(probabilities[prediction_idx]) | |
| gesture_name = self.label_encoder.inverse_transform([prediction_idx])[0] | |
| labels.append({ | |
| "hand": hand_label, | |
| "gesture": gesture_name, | |
| # FORMATA PARA EXIBIR 1 CASA DECIMAL (ex: 98.5) | |
| "confidence": round(confidence_raw * 100, 1) | |
| }) | |
| except Exception as e: | |
| print(f"Erro na predição: {e}") | |
| if len(labels) == 2 and labels[0]['gesture'] == labels[1]['gesture']: | |
| gesture_image = f"{labels[0]['gesture']}.png" | |
| return frame, labels, gesture_image, animals |