Integração do MediaPipe e YOLOv8: Aplicação Avançada de Visão Computacional
Descubra como combinar MediaPipe e YOLOv8 para criar uma aplicação completa de visão computacional.
I
InSkillCoach
· min
Integração do MediaPipe e YOLOv8: Aplicação Avançada de Visão Computacional
Guia completo para criar uma aplicação que combina detecção de pose com MediaPipe e detecção de objetos com YOLOv8.
1. Configuração Inicial
# Instalação das dependências
pip install mediapipe ultralytics opencv-python numpy
# Import das bibliotecas
import mediapipe as mp
from ultralytics import YOLO
import cv2
import numpy as np
import time
from threading import Thread
from queue import Queue
2. Arquitetura da Aplicação
2.1 Classes Base
class PoseDetector:
def __init__(self):
self.mp_pose = mp.solutions.pose
self.pose = self.mp_pose.Pose(
min_detection_confidence=0.5,
min_tracking_confidence=0.5
)
self.mp_draw = mp.solutions.drawing_utils
def detect(self, image):
# Conversão para RGB
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# Detecção da pose
results = self.pose.process(image_rgb)
# Desenhar os pontos de referência
if results.pose_landmarks:
self.mp_draw.draw_landmarks(
image,
results.pose_landmarks,
self.mp_pose.POSE_CONNECTIONS
)
return image, results.pose_landmarks
class ObjectDetector:
def __init__(self):
self.model = YOLO('yolov8n.pt')
def detect(self, image):
# Detecção de objetos
results = self.model(image)
# Processamento dos resultados
for result in results:
boxes = result.boxes
for box in boxes:
# Coordenadas da caixa
x1, y1, x2, y2 = box.xyxy[0]
x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
# Confiança
confidence = float(box.conf[0])
# Classe
class_id = int(box.cls[0])
class_name = self.model.names[class_id]
# Desenhar a caixa
cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
# Adicionar o texto
label = f"{class_name} {confidence:.2f}"
cv2.putText(image, label, (x1, y1 - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
return image
3. Processamento Multi-thread
3.1 Gerenciador de Frames
class FrameManager:
def __init__(self, max_queue_size=2):
self.frame_queue = Queue(maxsize=max_queue_size)
self.result_queue = Queue(maxsize=max_queue_size)
def add_frame(self, frame):
if not self.frame_queue.full():
self.frame_queue.put(frame)
def get_frame(self):
if not self.frame_queue.empty():
return self.frame_queue.get()
return None
def add_result(self, result):
if not self.result_queue.full():
self.result_queue.put(result)
def get_result(self):
if not self.result_queue.empty():
return self.result_queue.get()
return None
3.2 Workers
class PoseWorker(Thread):
def __init__(self, frame_manager, detector):
super().__init__()
self.frame_manager = frame_manager
self.detector = detector
self.running = True
def run(self):
while self.running:
frame = self.frame_manager.get_frame()
if frame is not None:
# Detecção de pose
processed_frame, landmarks = self.detector.detect(frame)
self.frame_manager.add_result((processed_frame, landmarks))
class ObjectWorker(Thread):
def __init__(self, frame_manager, detector):
super().__init__()
self.frame_manager = frame_manager
self.detector = detector
self.running = True
def run(self):
while self.running:
frame = self.frame_manager.get_frame()
if frame is not None:
# Detecção de objetos
processed_frame = self.detector.detect(frame)
self.frame_manager.add_result((processed_frame, None))
4. Aplicação Principal
4.1 Configuração
class Application:
def __init__(self):
# Inicialização dos detectores
self.pose_detector = PoseDetector()
self.object_detector = ObjectDetector()
# Inicialização do gerenciador de frames
self.frame_manager = FrameManager()
# Inicialização dos workers
self.pose_worker = PoseWorker(self.frame_manager, self.pose_detector)
self.object_worker = ObjectWorker(self.frame_manager, self.object_detector)
# Configuração da câmera
self.cap = cv2.VideoCapture(0)
# Variáveis de controle
self.running = True
self.current_mode = 'both' # 'pose', 'object', 'both'
4.2 Loop Principal
def run(self):
# Início dos workers
self.pose_worker.start()
self.object_worker.start()
while self.running:
success, frame = self.cap.read()
if not success:
continue
# Adição do frame ao gerenciador
self.frame_manager.add_frame(frame.copy())
# Recuperação dos resultados
pose_result = self.frame_manager.get_result()
object_result = self.frame_manager.get_result()
# Exibição dos resultados
if pose_result is not None and object_result is not None:
pose_frame, pose_landmarks = pose_result
object_frame, _ = object_result
# Combinação dos resultados
if self.current_mode == 'both':
# Sobreposição dos resultados
combined_frame = cv2.addWeighted(
pose_frame, 0.5, object_frame, 0.5, 0
)
cv2.imshow('Combined Detection', combined_frame)
elif self.current_mode == 'pose':
cv2.imshow('Pose Detection', pose_frame)
else:
cv2.imshow('Object Detection', object_frame)
# Gerenciamento das teclas
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
self.running = False
elif key == ord('p'):
self.current_mode = 'pose'
elif key == ord('o'):
self.current_mode = 'object'
elif key == ord('b'):
self.current_mode = 'both'
# Limpeza
self.cleanup()
4.3 Limpeza
def cleanup(self):
# Parada dos workers
self.pose_worker.running = False
self.object_worker.running = False
self.pose_worker.join()
self.object_worker.join()
# Liberação dos recursos
self.cap.release()
cv2.destroyAllWindows()
5. Funcionalidades Avançadas
5.1 Análise das Interações
def analyze_interaction(pose_landmarks, object_detections):
if pose_landmarks is None or object_detections is None:
return None
# Extração dos pontos-chave da pose
left_hand = np.array([
pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_WRIST.value].x,
pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_WRIST.value].y
])
right_hand = np.array([
pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_WRIST.value].x,
pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_WRIST.value].y
])
# Análise das interações com os objetos detectados
interactions = []
for detection in object_detections:
box_center = np.array([
(detection[0] + detection[2]) / 2,
(detection[1] + detection[3]) / 2
])
# Cálculo das distâncias
left_distance = np.linalg.norm(left_hand - box_center)
right_distance = np.linalg.norm(right_hand - box_center)
# Detecção das interações
if left_distance < 0.1 or right_distance < 0.1:
interactions.append({
'object': detection[4],
'hand': 'left' if left_distance < right_distance else 'right',
'distance': min(left_distance, right_distance)
})
return interactions
5.2 Visualização Avançada
def visualize_results(frame, pose_landmarks, object_detections, interactions):
# Desenhar os pontos de referência da pose
if pose_landmarks:
mp_draw.draw_landmarks(
frame,
pose_landmarks,
mp_pose.POSE_CONNECTIONS
)
# Desenhar as caixas de detecção de objetos
for detection in object_detections:
x1, y1, x2, y2 = detection[:4]
cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2)
# Visualizar as interações
if interactions:
for interaction in interactions:
# Desenhar uma linha entre a mão e o objeto
hand_point = left_hand if interaction['hand'] == 'left' else right_hand
cv2.line(
frame,
(int(hand_point[0] * frame.shape[1]), int(hand_point[1] * frame.shape[0])),
(int(box_center[0] * frame.shape[1]), int(box_center[1] * frame.shape[0])),
(0, 0, 255),
2
)
return frame
6. Otimização de Desempenho
6.1 Gerenciamento de Memória
def optimize_memory():
# Configuração para uso otimizado da memória
pose_detector = PoseDetector()
object_detector = ObjectDetector()
# Redução do tamanho dos frames
def resize_frame(frame):
return cv2.resize(frame, (640, 480))
# Limpeza periódica das filas
def cleanup_queues():
while not frame_manager.frame_queue.empty():
frame_manager.frame_queue.get()
while not frame_manager.result_queue.empty():
frame_manager.result_queue.get()
6.2 Aceleração por GPU
def enable_gpu_acceleration():
# Configuração para uso da GPU
import torch
if torch.cuda.is_available():
# Configuração do YOLO para a GPU
object_detector.model.to('cuda')
# Configuração do MediaPipe para a GPU
pose_detector.pose = mp_pose.Pose(
min_detection_confidence=0.5,
min_tracking_confidence=0.5,
model_complexity=1,
enable_segmentation=False
)
7. Boas Práticas
-
Gerenciamento de Recursos
- Usar multi-threading para as detecções
- Implementar um sistema de cache
- Limpar a memória regularmente
-
Otimização
- Reduzir o tamanho dos frames
- Usar a aceleração por GPU
- Ajustar as frequências de detecção
-
Interface do Usuário
- Fornecer controles intuitivos
- Exibir as métricas de desempenho
- Permitir a troca de modo em tempo real
Conclusão
Pontos-chave:
- Integração eficiente do MediaPipe e do YOLOv8
- Processamento multi-thread para melhor desempenho
- Análise das interações entre pose e objetos
- Interface do usuário flexível
Recomendações:
- Otimizar o uso de memória
- Usar a aceleração por GPU
- Implementar um tratamento robusto de erros
- Adicionar funcionalidades de personalização
Sobre InSkillCoach
Especialista em treinamento e tecnologias
Coach especializado em tecnologias avançadas e IA, apoiado pela GNeurone Inc.
Certificações:
- AWS Certified Solutions Architect – Professional
- Certificações Google Cloud
- Microsoft Certified: DevOps Engineer Expert
- Certified Kubernetes Administrator (CKA)
- CompTIA Security+
720
96
Comentários
Os comentários são alimentados pelo GitHub Discussions
Conecte-se com o GitHub para participar da discussão