test_camera_fps.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #!/usr/bin/env python3
  2. """
  3. Quick utility to measure the actual frame rate obtainable from a USB/IP camera.
  4. Usage:
  5. python test_camera_fps.py --input 0 --frames 300 --width 640 --height 480 --fps 30
  6. It attempts to set the desired resolution/FPS, reads the specified number of
  7. frames, and prints the achieved FPS along with any read failures.
  8. """
  9. import argparse
  10. import time
  11. import cv2
  12. def parse_args():
  13. parser = argparse.ArgumentParser(description="Measure camera FPS with OpenCV")
  14. parser.add_argument("--input", type=str, default="0", help="Camera index or URL")
  15. parser.add_argument("--frames", type=int, default=200, help="How many frames to capture")
  16. parser.add_argument("--width", type=int, default=640, help="Requested frame width")
  17. parser.add_argument("--height", type=int, default=480, help="Requested frame height")
  18. parser.add_argument("--fps", type=float, default=30.0, help="Requested FPS (hint to driver)")
  19. parser.add_argument("--backend", type=str, default="", help="Optional OpenCV backend name (e.g., 'dshow')")
  20. return parser.parse_args()
  21. def open_capture(source, backend):
  22. if backend:
  23. backend_map = {
  24. "dshow": cv2.CAP_DSHOW,
  25. "msmf": cv2.CAP_MSMF,
  26. "ffmpeg": cv2.CAP_FFMPEG,
  27. }
  28. backend_flag = backend_map.get(backend.lower())
  29. if backend_flag is None:
  30. raise ValueError(f"Unsupported backend '{backend}'. Choose from {list(backend_map)}")
  31. return cv2.VideoCapture(source, backend_flag)
  32. return cv2.VideoCapture(source)
  33. def main():
  34. opt = parse_args()
  35. source = int(opt.input) if opt.input.isdigit() else opt.input
  36. cap = open_capture(source, opt.backend)
  37. if not cap.isOpened():
  38. raise RuntimeError(f"Failed to open camera source: {opt.input}")
  39. # Try to set desired properties (may be ignored by some drivers)
  40. cap.set(cv2.CAP_PROP_FRAME_WIDTH, opt.width)
  41. cap.set(cv2.CAP_PROP_FRAME_HEIGHT, opt.height)
  42. cap.set(cv2.CAP_PROP_FPS, opt.fps)
  43. actual_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
  44. actual_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
  45. actual_fps = cap.get(cv2.CAP_PROP_FPS)
  46. print(f"Requested: {opt.width}x{opt.height} @{opt.fps:.1f} FPS")
  47. print(f"Driver reports: {actual_width:.0f}x{actual_height:.0f} @{actual_fps:.1f} FPS")
  48. total = 0
  49. failures = 0
  50. start = time.time()
  51. while total < opt.frames:
  52. ok, _ = cap.read()
  53. if not ok:
  54. failures += 1
  55. continue
  56. total += 1
  57. elapsed = time.time() - start
  58. cap.release()
  59. achieved_fps = total / elapsed if elapsed > 0 else 0.0
  60. print(f"Captured {total} frames in {elapsed:.2f} s => {achieved_fps:.2f} FPS")
  61. if failures:
  62. print(f"Read failures: {failures}")
  63. if __name__ == "__main__":
  64. main()