235 lines
8.4 KiB
Python
235 lines
8.4 KiB
Python
|
#!/usr/bin/env python3
|
|||
|
# -*- coding: utf-8 -*-
|
|||
|
"""
|
|||
|
OpenCV后端优化验证脚本
|
|||
|
测试DirectShow后端相对于MSMF的性能提升
|
|||
|
"""
|
|||
|
|
|||
|
import sys
|
|||
|
import os
|
|||
|
import time
|
|||
|
import logging
|
|||
|
|
|||
|
# 添加项目路径
|
|||
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|||
|
|
|||
|
from devices.camera_manager import CameraManager
|
|||
|
from devices.utils.config_manager import ConfigManager
|
|||
|
|
|||
|
# 配置日志
|
|||
|
logging.basicConfig(
|
|||
|
level=logging.INFO,
|
|||
|
format='%(asctime)s - %(levelname)s - %(message)s'
|
|||
|
)
|
|||
|
logger = logging.getLogger(__name__)
|
|||
|
|
|||
|
def test_backend_performance(backend_name, test_name):
|
|||
|
"""
|
|||
|
测试指定后端的性能
|
|||
|
|
|||
|
Args:
|
|||
|
backend_name: 后端名称 (directshow, msmf)
|
|||
|
test_name: 测试名称
|
|||
|
|
|||
|
Returns:
|
|||
|
dict: 性能数据
|
|||
|
"""
|
|||
|
print(f"\n{'='*60}")
|
|||
|
print(f"📷 测试 {test_name} 后端性能")
|
|||
|
print(f"{'='*60}")
|
|||
|
|
|||
|
# 创建配置管理器并设置后端
|
|||
|
config_manager = ConfigManager()
|
|||
|
|
|||
|
# 获取原始配置
|
|||
|
original_config = config_manager.get_device_config('camera')
|
|||
|
|
|||
|
# 设置测试后端
|
|||
|
test_config = {
|
|||
|
'backend': backend_name
|
|||
|
}
|
|||
|
config_manager.set_camera_config(test_config)
|
|||
|
|
|||
|
try:
|
|||
|
# 创建相机管理器
|
|||
|
camera = CameraManager(None, config_manager)
|
|||
|
|
|||
|
# 测试初始化性能
|
|||
|
start_time = time.time()
|
|||
|
success = camera.initialize()
|
|||
|
total_time = (time.time() - start_time) * 1000
|
|||
|
|
|||
|
if success:
|
|||
|
print(f"✅ 相机初始化成功: {total_time:.1f}ms")
|
|||
|
|
|||
|
# 获取实际后端信息
|
|||
|
if camera.cap:
|
|||
|
backend_info = camera.cap.getBackendName() if hasattr(camera.cap, 'getBackendName') else 'Unknown'
|
|||
|
actual_width = int(camera.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
|||
|
actual_height = int(camera.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
|||
|
actual_fps = camera.cap.get(cv2.CAP_PROP_FPS)
|
|||
|
print(f"🎯 实际后端: {backend_info}")
|
|||
|
print(f"📐 实际分辨率: {actual_width}x{actual_height}@{actual_fps:.1f}fps")
|
|||
|
|
|||
|
# 测试首帧获取
|
|||
|
frame_start = time.time()
|
|||
|
ret, frame = camera.cap.read() if camera.cap else (False, None)
|
|||
|
frame_time = (time.time() - frame_start) * 1000
|
|||
|
|
|||
|
if ret and frame is not None:
|
|||
|
print(f"🖼️ 首帧获取: {frame_time:.1f}ms, 帧大小: {frame.shape}")
|
|||
|
else:
|
|||
|
print(f"❌ 首帧获取失败")
|
|||
|
frame_time = -1
|
|||
|
|
|||
|
# 测试连续帧性能
|
|||
|
print(f"🎬 测试连续帧获取性能...")
|
|||
|
frame_times = []
|
|||
|
for i in range(10):
|
|||
|
frame_start = time.time()
|
|||
|
ret, frame = camera.cap.read() if camera.cap else (False, None)
|
|||
|
if ret:
|
|||
|
frame_times.append((time.time() - frame_start) * 1000)
|
|||
|
time.sleep(0.01) # 小延迟
|
|||
|
|
|||
|
if frame_times:
|
|||
|
avg_frame_time = sum(frame_times) / len(frame_times)
|
|||
|
min_frame_time = min(frame_times)
|
|||
|
max_frame_time = max(frame_times)
|
|||
|
print(f"📈 连续帧性能: 平均 {avg_frame_time:.1f}ms, 最快 {min_frame_time:.1f}ms, 最慢 {max_frame_time:.1f}ms")
|
|||
|
else:
|
|||
|
avg_frame_time = -1
|
|||
|
print(f"❌ 连续帧测试失败")
|
|||
|
|
|||
|
# 清理资源
|
|||
|
camera.cleanup()
|
|||
|
print(f"🧹 相机资源已释放")
|
|||
|
|
|||
|
return {
|
|||
|
'backend': backend_name,
|
|||
|
'success': True,
|
|||
|
'init_time': total_time,
|
|||
|
'first_frame_time': frame_time,
|
|||
|
'avg_frame_time': avg_frame_time,
|
|||
|
'backend_info': backend_info if camera.cap else 'Unknown',
|
|||
|
'resolution': f"{actual_width}x{actual_height}@{actual_fps:.1f}fps" if camera.cap else "未知"
|
|||
|
}
|
|||
|
else:
|
|||
|
print(f"❌ 初始化失败")
|
|||
|
return {
|
|||
|
'backend': backend_name,
|
|||
|
'success': False,
|
|||
|
'init_time': total_time,
|
|||
|
'first_frame_time': -1,
|
|||
|
'avg_frame_time': -1,
|
|||
|
'backend_info': 'Failed',
|
|||
|
'resolution': "失败"
|
|||
|
}
|
|||
|
|
|||
|
except Exception as e:
|
|||
|
print(f"❌ 测试异常: {e}")
|
|||
|
return {
|
|||
|
'backend': backend_name,
|
|||
|
'success': False,
|
|||
|
'init_time': -1,
|
|||
|
'first_frame_time': -1,
|
|||
|
'avg_frame_time': -1,
|
|||
|
'backend_info': 'Exception',
|
|||
|
'resolution': "异常",
|
|||
|
'error': str(e)
|
|||
|
}
|
|||
|
finally:
|
|||
|
# 恢复原始配置
|
|||
|
try:
|
|||
|
restore_config = {
|
|||
|
'backend': original_config['backend']
|
|||
|
}
|
|||
|
config_manager.set_camera_config(restore_config)
|
|||
|
except Exception as e:
|
|||
|
print(f"⚠️ 恢复配置失败: {e}")
|
|||
|
|
|||
|
def main():
|
|||
|
"""
|
|||
|
主函数:测试不同后端的性能
|
|||
|
"""
|
|||
|
print("\n" + "="*80)
|
|||
|
print("🚀 OpenCV后端性能优化验证")
|
|||
|
print("="*80)
|
|||
|
|
|||
|
# 测试用例
|
|||
|
test_cases = [
|
|||
|
('directshow', 'DirectShow (推荐)'),
|
|||
|
('msmf', 'MSMF (默认)')
|
|||
|
]
|
|||
|
|
|||
|
results = []
|
|||
|
|
|||
|
# 执行测试
|
|||
|
for backend, name in test_cases:
|
|||
|
result = test_backend_performance(backend, name)
|
|||
|
results.append(result)
|
|||
|
time.sleep(1) # 测试间隔
|
|||
|
|
|||
|
# 汇总结果
|
|||
|
print(f"\n\n{'='*80}")
|
|||
|
print(f"📊 后端性能优化验证汇总")
|
|||
|
print(f"{'='*80}")
|
|||
|
|
|||
|
# 表格头
|
|||
|
print(f"{'后端':<12} {'状态':<8} {'初始化':<12} {'首帧':<12} {'连续帧':<12} {'实际后端':<15}")
|
|||
|
print("-" * 80)
|
|||
|
|
|||
|
successful_results = [r for r in results if r['success']]
|
|||
|
|
|||
|
for result in results:
|
|||
|
status = "✅成功" if result['success'] else "❌失败"
|
|||
|
init_time = f"{result['init_time']:.1f}ms" if result['init_time'] > 0 else "失败"
|
|||
|
first_frame = f"{result['first_frame_time']:.1f}ms" if result['first_frame_time'] > 0 else "失败"
|
|||
|
avg_frame = f"{result['avg_frame_time']:.1f}ms" if result['avg_frame_time'] > 0 else "失败"
|
|||
|
backend_info = result['backend_info'][:14] if len(result['backend_info']) > 14 else result['backend_info']
|
|||
|
|
|||
|
print(f"{result['backend']:<12} {status:<8} {init_time:<12} {first_frame:<12} {avg_frame:<12} {backend_info:<15}")
|
|||
|
|
|||
|
# 性能分析
|
|||
|
if len(successful_results) >= 2:
|
|||
|
print(f"\n📈 性能分析:")
|
|||
|
|
|||
|
# 找到最快的后端
|
|||
|
fastest = min(successful_results, key=lambda x: x['init_time'])
|
|||
|
slowest = max(successful_results, key=lambda x: x['init_time'])
|
|||
|
|
|||
|
print(f"🏆 最快后端: {fastest['backend']} - {fastest['init_time']:.1f}ms")
|
|||
|
print(f"🐌 最慢后端: {slowest['backend']} - {slowest['init_time']:.1f}ms")
|
|||
|
|
|||
|
if fastest['init_time'] > 0 and slowest['init_time'] > 0:
|
|||
|
improvement = ((slowest['init_time'] - fastest['init_time']) / slowest['init_time']) * 100
|
|||
|
print(f"💡 性能提升: {improvement:.1f}% (使用最快后端)")
|
|||
|
|
|||
|
print(f"\n📋 详细性能对比:")
|
|||
|
for result in successful_results:
|
|||
|
if result != fastest:
|
|||
|
slowdown = ((result['init_time'] - fastest['init_time']) / fastest['init_time']) * 100
|
|||
|
print(f" {result['backend']}: 比最快后端慢 {slowdown:.1f}% ({result['init_time']:.1f}ms vs {fastest['init_time']:.1f}ms)")
|
|||
|
|
|||
|
print(f"\n🎯 建议:")
|
|||
|
if successful_results:
|
|||
|
fastest = min(successful_results, key=lambda x: x['init_time'])
|
|||
|
print(f"✅ 推荐使用 {fastest['backend']} 后端以获得最佳性能")
|
|||
|
print(f"📝 配置建议: 在配置文件中设置 backend = {fastest['backend']}")
|
|||
|
|
|||
|
if fastest['init_time'] > 5000:
|
|||
|
print(f"⚠️ 性能评级: 需要优化 (> 5秒)")
|
|||
|
elif fastest['init_time'] > 2000:
|
|||
|
print(f"⚠️ 性能评级: 一般 (2-5秒)")
|
|||
|
else:
|
|||
|
print(f"✅ 性能评级: 良好 (< 2秒)")
|
|||
|
else:
|
|||
|
print(f"❌ 所有后端测试失败,请检查相机连接")
|
|||
|
|
|||
|
print(f"\n{'='*80}")
|
|||
|
print(f"测试完成")
|
|||
|
print(f"{'='*80}")
|
|||
|
|
|||
|
if __name__ == "__main__":
|
|||
|
import cv2 # 需要导入cv2用于相机操作
|
|||
|
main()
|