checkhandpi/src/process_video_3d.py
2025-08-11 13:15:21 +08:00

168 lines
5.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import cv2
import numpy as np
import time
import os
# 导入我们的3D手部检测模块
from src.hand_detection_3d import load_mediapipe_model, process_frame_3d
# 尝试导入 Picamera2如果不可用则使用标准OpenCV
try:
from picamera2 import Picamera2
PICAMERA_AVAILABLE = True
except ImportError:
PICAMERA_AVAILABLE = False
def process_camera_3d(camera_id=0, output_path=None, use_picamera=True):
"""
使用摄像头进行3D手部检测 - 简化版本
参数:
camera_id: 摄像头ID (默认为0)
output_path: 输出视频文件路径 (可选)
use_picamera: 是否优先使用Picamera2 (树莓派摄像头)
"""
# 加载MediaPipe手部检测模型
hands_model = load_mediapipe_model(max_num_hands=1)
# 初始化摄像头
cap = None
picam2 = None
if use_picamera and PICAMERA_AVAILABLE:
# 使用 Picamera2 (树莓派摄像头)
try:
print("正在初始化 Picamera2...")
picam2 = Picamera2()
video_config = picam2.create_video_configuration(main={"size": (640, 480)})
picam2.configure(video_config)
picam2.start()
print("✅ Picamera2 启动成功")
frame_width, frame_height = 640, 480
except Exception as e:
print(f"❌ Picamera2 启动失败: {e}")
print("⚠️ 回退到 OpenCV VideoCapture")
picam2 = None
use_picamera = False
if not use_picamera or not PICAMERA_AVAILABLE:
# 使用标准 OpenCV VideoCapture
cap = cv2.VideoCapture(camera_id)
if not cap.isOpened():
print(f"无法打开摄像头 ID: {camera_id}")
return
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = 30
# 创建视频写入器(如果需要保存)
video_writer = None
if output_path:
fourcc = cv2.VideoWriter_fourcc(*'XVID')
video_writer = cv2.VideoWriter(output_path, fourcc, fps, (frame_width, frame_height))
# 前一帧的手部数据
prev_hand_data = None
# 初始化性能计数器
frame_count = 0
start_time = time.time()
print("控制说明:")
print("- 移动手部显示控制信号")
print("- 拇指和食指捏合显示抓取状态")
print("- 按 Ctrl+C 退出")
try:
while True:
# 读取一帧
ret = False
frame = None
if picam2:
try:
frame = picam2.capture_array()
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
ret = True
except Exception as e:
print(f"Picamera2 读取帧失败: {e}")
break
else:
ret, frame = cap.read()
if not ret or frame is None:
break
frame_count += 1
# 处理帧并获取三轴控制信号
control_signal, prev_hand_data = process_frame_3d(frame, hands_model, prev_hand_data)
# 显示控制信号
if control_signal and frame_count % 30 == 0: # 每秒显示一次
print_control_signal(control_signal)
# 写入输出视频
if video_writer:
video_writer.write(frame)
except KeyboardInterrupt:
print("\n收到中断信号,正在退出...")
except Exception as e:
print(f"程序运行时出错: {e}")
finally:
print("正在清理资源...")
# 释放资源
if picam2:
try:
picam2.stop()
picam2.close()
except:
pass
if cap:
try:
cap.release()
except:
pass
if video_writer:
try:
video_writer.release()
print(f"✅ 视频已保存: {output_path}")
except:
pass
# 显示统计信息
elapsed_time = time.time() - start_time
if frame_count > 0:
avg_fps = frame_count / elapsed_time
print(f"📊 处理了 {frame_count}平均FPS: {avg_fps:.1f}")
print("✅ 程序已退出")
def print_control_signal(control_signal):
"""显示手部控制信号信息"""
print(f"手部控制信号:")
print(f" X轴角度: {control_signal['x_angle']:.1f}°")
print(f" Y轴角度: {control_signal['y_angle']:.1f}°")
print(f" Z轴角度: {control_signal['z_angle']:.1f}°")
print(f" 抓取状态: {'抓取' if control_signal['grip'] == 1 else '释放'}")
print(f" 动作: {control_signal['action']}")
print("-------------------------------")
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description='简化版3D手部检测')
parser.add_argument('--camera-id', '-i', type=int, default=0, help='摄像头ID (默认为0)')
parser.add_argument('--output', '-o', help='输出视频文件路径')
args = parser.parse_args()
process_camera_3d(
camera_id=args.camera_id,
output_path=args.output
)