checkhand/create_test_video.py
2025-08-11 12:24:21 +08:00

229 lines
9.0 KiB
Python
Executable File
Raw Permalink 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.

#!/usr/bin/env python3
"""
创建测试视频
生成包含手部动作的测试视频用于系统测试
"""
import cv2
import numpy as np
import os
import argparse
def create_test_video(output_path, duration=10, fps=30):
"""
创建测试视频
参数:
output_path: 输出视频路径
duration: 视频时长(秒)
fps: 帧率
"""
# 视频参数
width, height = 640, 480
total_frames = duration * fps
# 创建视频写入器
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
print(f"正在创建测试视频: {output_path}")
print(f"分辨率: {width}x{height}, 帧率: {fps}, 时长: {duration}")
for frame_idx in range(total_frames):
# 创建背景
frame = np.zeros((height, width, 3), dtype=np.uint8)
frame[:] = (40, 40, 40) # 深灰色背景
# 计算进度
progress = frame_idx / total_frames
# 绘制模拟手部(圆形)
center_x = int(width * 0.3 + width * 0.4 * np.sin(progress * 4 * np.pi))
center_y = int(height * 0.3 + height * 0.4 * np.cos(progress * 2 * np.pi))
# 主手部圆形
cv2.circle(frame, (center_x, center_y), 30, (255, 200, 100), -1)
# 绘制5个手指小圆形
finger_positions = [
(center_x - 20, center_y - 35), # 拇指
(center_x - 10, center_y - 40), # 食指
(center_x, center_y - 42), # 中指
(center_x + 10, center_y - 40), # 无名指
(center_x + 20, center_y - 35) # 小指
]
for i, (fx, fy) in enumerate(finger_positions):
# 手指颜色渐变
color = (200 + i * 10, 150 + i * 20, 100 + i * 15)
cv2.circle(frame, (fx, fy), 8, color, -1)
# 绘制手腕
wrist_x, wrist_y = center_x, center_y + 40
cv2.circle(frame, (wrist_x, wrist_y), 15, (180, 150, 120), -1)
# 连接手掌和手腕
cv2.line(frame, (center_x, center_y), (wrist_x, wrist_y), (200, 180, 150), 8)
# 添加文字信息
time_text = f"时间: {frame_idx/fps:.1f}s"
position_text = f"位置: ({center_x}, {center_y})"
cv2.putText(frame, time_text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
cv2.putText(frame, position_text, (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
cv2.putText(frame, "测试视频 - 模拟手部动作", (10, height - 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
# 写入帧
out.write(frame)
# 显示进度
if frame_idx % (fps * 2) == 0: # 每2秒显示一次进度
print(f"进度: {progress*100:.1f}%")
# 释放资源
out.release()
print(f"✅ 测试视频创建完成: {output_path}")
def create_gesture_test_video(output_path, duration=15, fps=30):
"""
创建手势测试视频
包含不同的手势动作
"""
width, height = 640, 480
total_frames = duration * fps
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
print(f"正在创建手势测试视频: {output_path}")
gestures = [
"张开手掌",
"握拳",
"OK手势",
"指向手势",
"抓取动作"
]
frames_per_gesture = total_frames // len(gestures)
for frame_idx in range(total_frames):
frame = np.zeros((height, width, 3), dtype=np.uint8)
frame[:] = (50, 50, 50)
# 确定当前手势
gesture_idx = frame_idx // frames_per_gesture
if gesture_idx >= len(gestures):
gesture_idx = len(gestures) - 1
current_gesture = gestures[gesture_idx]
# 手部基本位置
center_x = width // 2
center_y = height // 2
# 根据手势绘制不同形状
if current_gesture == "张开手掌":
# 绘制张开的手掌
cv2.circle(frame, (center_x, center_y), 40, (255, 200, 100), -1)
# 五个分开的手指
for i, angle in enumerate([-60, -30, 0, 30, 60]):
finger_x = center_x + int(50 * np.cos(np.radians(angle)))
finger_y = center_y - int(50 * np.sin(np.radians(angle)))
cv2.circle(frame, (finger_x, finger_y), 12, (200, 180, 150), -1)
elif current_gesture == "握拳":
# 绘制握拳
cv2.circle(frame, (center_x, center_y), 35, (255, 200, 100), -1)
# 手指弯曲(小圆圈)
for i, angle in enumerate([-45, -22, 0, 22, 45]):
finger_x = center_x + int(25 * np.cos(np.radians(angle)))
finger_y = center_y - int(15 * np.sin(np.radians(angle)))
cv2.circle(frame, (finger_x, finger_y), 8, (180, 150, 120), -1)
elif current_gesture == "OK手势":
# 绘制OK手势
cv2.circle(frame, (center_x, center_y), 35, (255, 200, 100), -1)
# 拇指和食指形成圆圈
cv2.circle(frame, (center_x - 15, center_y - 20), 8, (200, 180, 150), -1)
cv2.circle(frame, (center_x - 5, center_y - 25), 8, (200, 180, 150), -1)
# 其他手指伸直
for i, angle in enumerate([15, 30, 45]):
finger_x = center_x + int(40 * np.cos(np.radians(angle)))
finger_y = center_y - int(40 * np.sin(np.radians(angle)))
cv2.circle(frame, (finger_x, finger_y), 10, (200, 180, 150), -1)
elif current_gesture == "指向手势":
# 绘制指向手势
cv2.circle(frame, (center_x, center_y), 30, (255, 200, 100), -1)
# 食指伸出
cv2.circle(frame, (center_x, center_y - 45), 10, (200, 180, 150), -1)
# 其他手指弯曲
for i, angle in enumerate([-30, 15, 30]):
finger_x = center_x + int(20 * np.cos(np.radians(angle)))
finger_y = center_y - int(10 * np.sin(np.radians(angle)))
cv2.circle(frame, (finger_x, finger_y), 8, (180, 150, 120), -1)
elif current_gesture == "抓取动作":
# 绘制抓取动作
cv2.circle(frame, (center_x, center_y), 32, (255, 200, 100), -1)
# 拇指和食指靠近
thumb_x = center_x - 20
thumb_y = center_y - 20
index_x = center_x - 10
index_y = center_y - 30
cv2.circle(frame, (thumb_x, thumb_y), 9, (200, 180, 150), -1)
cv2.circle(frame, (index_x, index_y), 9, (200, 180, 150), -1)
# 连接线表示抓取
cv2.line(frame, (thumb_x, thumb_y), (index_x, index_y), (255, 255, 255), 2)
# 添加文字信息
cv2.putText(frame, f"手势: {current_gesture}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
cv2.putText(frame, f"时间: {frame_idx/fps:.1f}s", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
cv2.putText(frame, "手势测试视频", (10, height - 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 255), 2)
out.write(frame)
if frame_idx % (fps * 2) == 0:
print(f"进度: {frame_idx/total_frames*100:.1f}% - 当前手势: {current_gesture}")
out.release()
print(f"✅ 手势测试视频创建完成: {output_path}")
def main():
parser = argparse.ArgumentParser(description='创建手部检测测试视频')
parser.add_argument('--type', choices=['basic', 'gesture', 'both'], default='both',
help='视频类型 (basic: 基础移动, gesture: 手势, both: 两种都创建)')
parser.add_argument('--duration', type=int, default=10, help='视频时长(秒)')
parser.add_argument('--fps', type=int, default=30, help='帧率')
parser.add_argument('--output-dir', default='data/videos', help='输出目录')
args = parser.parse_args()
# 确保输出目录存在
os.makedirs(args.output_dir, exist_ok=True)
if args.type in ['basic', 'both']:
basic_path = os.path.join(args.output_dir, 'test_basic.mp4')
create_test_video(basic_path, args.duration, args.fps)
if args.type in ['gesture', 'both']:
gesture_path = os.path.join(args.output_dir, 'test_gesture.mp4')
create_gesture_test_video(gesture_path, args.duration + 5, args.fps)
print("\n🎉 测试视频创建完成!")
print("\n📁 创建的文件:")
for file in os.listdir(args.output_dir):
if file.endswith('.mp4'):
file_path = os.path.join(args.output_dir, file)
size = os.path.getsize(file_path) / (1024 * 1024) # MB
print(f" {file} ({size:.1f} MB)")
print("\n🚀 使用方法:")
print(" ./start_service.sh --test-video data/videos/test_basic.mp4")
print(" ./start_service.sh --test-video data/videos/test_gesture.mp4")
if __name__ == '__main__':
main()