#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ OpenCV后端性能测试脚本 测试不同OpenCV后端(DirectShow vs MSMF)的性能差异 """ import sys import os import time import logging import cv2 # 添加项目路径 sys.path.append(os.path.dirname(os.path.abspath(__file__))) # 配置日志 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) def test_opencv_backend(backend_name, backend_id, device_index=0, width=1280, height=720, fps=30): """ 测试指定OpenCV后端的性能 Args: backend_name: 后端名称 backend_id: 后端ID device_index: 设备索引 width: 宽度 height: 高度 fps: 帧率 Returns: dict: 性能数据 """ print(f"\n{'='*70}") print(f"测试 {backend_name} 后端 (ID: {backend_id})") print(f"分辨率: {width}x{height}, FPS: {fps}") print(f"{'='*70}") result = { 'backend_name': backend_name, 'backend_id': backend_id, 'success': False, 'init_time': -1, 'config_time': -1, 'first_frame_time': -1, 'total_time': -1, 'actual_resolution': 'N/A', 'error': None } cap = None try: # 1. 测试相机初始化时间 print(f"📷 初始化相机 (后端: {backend_name})...") init_start = time.time() # 创建VideoCapture对象并指定后端 cap = cv2.VideoCapture(device_index, backend_id) if not cap.isOpened(): print(f"❌ 无法打开相机 (后端: {backend_name})") result['error'] = f"无法打开相机 (后端: {backend_name})" return result init_time = (time.time() - init_start) * 1000 result['init_time'] = init_time print(f"✅ 相机初始化成功: {init_time:.1f}ms") # 2. 测试配置时间 print(f"⚙️ 配置相机参数...") config_start = time.time() # 设置分辨率和帧率 cap.set(cv2.CAP_PROP_FRAME_WIDTH, width) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height) cap.set(cv2.CAP_PROP_FPS, fps) # 设置缓冲区大小 cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # 性能优化设置 try: cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0.25) # 手动曝光 cap.set(cv2.CAP_PROP_AUTO_WB, 0) # 禁用自动白平衡 cap.set(cv2.CAP_PROP_EXPOSURE, -6) # 设置曝光值 except Exception as e: print(f"⚠️ 性能优化设置警告: {e}") config_time = (time.time() - config_start) * 1000 result['config_time'] = config_time print(f"✅ 配置完成: {config_time:.1f}ms") # 3. 获取实际分辨率 actual_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) actual_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) actual_fps = cap.get(cv2.CAP_PROP_FPS) result['actual_resolution'] = f"{actual_width}x{actual_height}@{actual_fps:.1f}fps" print(f"🎯 实际参数: {actual_width}x{actual_height}, FPS: {actual_fps:.1f}") # 4. 测试首帧获取时间 print(f"🖼️ 获取首帧...") frame_start = time.time() ret, frame = cap.read() if ret and frame is not None: first_frame_time = (time.time() - frame_start) * 1000 result['first_frame_time'] = first_frame_time print(f"✅ 首帧获取成功: {first_frame_time:.1f}ms, 帧大小: {frame.shape}") else: print(f"❌ 首帧获取失败") result['error'] = "首帧获取失败" return result # 5. 计算总时间 total_time = init_time + config_time + first_frame_time result['total_time'] = total_time result['success'] = True print(f"📊 总耗时: {total_time:.1f}ms ({total_time/1000:.2f}秒)") # 6. 测试连续帧获取性能 print(f"🎬 测试连续帧获取性能...") frame_times = [] test_frames = 10 for i in range(test_frames): frame_start = time.time() ret, frame = cap.read() if ret: frame_time = (time.time() - frame_start) * 1000 frame_times.append(frame_time) else: break if frame_times: avg_frame_time = sum(frame_times) / len(frame_times) max_frame_time = max(frame_times) min_frame_time = min(frame_times) print(f"📈 连续帧性能: 平均 {avg_frame_time:.1f}ms, 最快 {min_frame_time:.1f}ms, 最慢 {max_frame_time:.1f}ms") result['avg_frame_time'] = avg_frame_time result['max_frame_time'] = max_frame_time result['min_frame_time'] = min_frame_time return result except Exception as e: print(f"❌ 测试异常: {e}") result['error'] = str(e) return result finally: if cap: cap.release() print(f"🧹 相机资源已释放") def get_available_backends(): """ 获取可用的OpenCV后端 Returns: list: 可用后端列表 """ backends = [ ('DirectShow', cv2.CAP_DSHOW), ('MSMF', cv2.CAP_MSMF), ('V4L2', cv2.CAP_V4L2), ('GStreamer', cv2.CAP_GSTREAMER), ('Any', cv2.CAP_ANY) ] available_backends = [] for name, backend_id in backends: try: # 尝试创建VideoCapture对象 cap = cv2.VideoCapture(0, backend_id) if cap.isOpened(): available_backends.append((name, backend_id)) cap.release() except Exception: pass return available_backends def main(): """ 主测试函数 """ print("🚀 OpenCV后端性能测试") print(f"OpenCV版本: {cv2.__version__}") # 获取可用后端 print("\n🔍 检测可用的OpenCV后端...") available_backends = get_available_backends() if not available_backends: print("❌ 未找到可用的相机后端") return print(f"✅ 找到 {len(available_backends)} 个可用后端:") for name, backend_id in available_backends: print(f" - {name} (ID: {backend_id})") # 测试参数 test_params = { 'device_index': 0, 'width': 1280, 'height': 720, 'fps': 30 } print(f"\n📋 测试参数: {test_params['width']}x{test_params['height']}@{test_params['fps']}fps") # 执行测试 results = [] for backend_name, backend_id in available_backends: result = test_opencv_backend( backend_name, backend_id, **test_params ) results.append(result) # 等待一下,避免设备冲突 time.sleep(2) # 输出汇总结果 print(f"\n{'='*90}") print("📈 OpenCV后端性能测试汇总") print(f"{'='*90}") print(f"{'后端':<12} {'状态':<8} {'初始化':<10} {'配置':<10} {'首帧':<10} {'总计':<10} {'实际分辨率':<20}") print("-" * 90) successful_results = [] for result in results: status = "✅成功" if result['success'] else "❌失败" init_time = f"{result['init_time']:.1f}ms" if result['init_time'] > 0 else "N/A" config_time = f"{result['config_time']:.1f}ms" if result['config_time'] > 0 else "N/A" frame_time = f"{result['first_frame_time']:.1f}ms" if result['first_frame_time'] > 0 else "N/A" total_time = f"{result['total_time']:.1f}ms" if result['total_time'] > 0 else "N/A" print(f"{result['backend_name']:<12} {status:<8} {init_time:<10} {config_time:<10} {frame_time:<10} {total_time:<10} {result['actual_resolution']:<20}") if result['success']: successful_results.append(result) # 性能分析 if len(successful_results) >= 2: print(f"\n📊 性能分析:") # 找到最快和最慢的后端 fastest = min(successful_results, key=lambda x: x['total_time']) slowest = max(successful_results, key=lambda x: x['total_time']) print(f"🏆 最快后端: {fastest['backend_name']} - {fastest['total_time']:.1f}ms") print(f"🐌 最慢后端: {slowest['backend_name']} - {slowest['total_time']:.1f}ms") if slowest['total_time'] > fastest['total_time']: improvement = ((slowest['total_time'] - fastest['total_time']) / slowest['total_time']) * 100 print(f"💡 性能提升: {improvement:.1f}% (使用最快后端)") # 详细对比 print(f"\n📋 详细性能对比:") for result in successful_results: if result != fastest: if result['total_time'] > fastest['total_time']: slower = ((result['total_time'] - fastest['total_time']) / fastest['total_time']) * 100 print(f" {result['backend_name']}: 比最快后端慢 {slower:.1f}% ({result['total_time']:.1f}ms vs {fastest['total_time']:.1f}ms)") elif len(successful_results) == 1: result = successful_results[0] print(f"\n📊 只有一个后端测试成功: {result['backend_name']} - {result['total_time']:.1f}ms") # 推荐建议 print(f"\n🎯 建议:") if successful_results: fastest = min(successful_results, key=lambda x: x['total_time']) print(f"✅ 推荐使用 {fastest['backend_name']} 后端以获得最佳性能") print(f"📝 配置建议: 在相机初始化时指定后端 cv2.VideoCapture(device_index, cv2.CAP_{fastest['backend_name'].upper()})") if fastest['total_time'] < 3000: print(f"🚀 性能评级: 优秀 (< 3秒)") elif fastest['total_time'] < 5000: print(f"⚡ 性能评级: 良好 (< 5秒)") else: print(f"⚠️ 性能评级: 需要优化 (> 5秒)") else: print(f"❌ 所有后端测试都失败了,请检查相机连接和驱动") print(f"\n{'='*90}") print("测试完成") print(f"{'='*90}") if __name__ == "__main__": main()