229 lines
9.0 KiB
Python
Executable File
229 lines
9.0 KiB
Python
Executable File
#!/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() |