camera.py 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. from PyQt5.QtCore import pyqtSignal
  2. from PyQt5.QtCore import QObject
  3. from PyQt5.QtCore import QTimer
  4. from PyQt5.QtGui import QImage
  5. import cv2
  6. class CameraDevice(QObject):
  7. frame_ready = pyqtSignal(QImage)
  8. def __init__(self, device_id=0):
  9. super().__init__()
  10. self.capture = cv2.VideoCapture(device_id)
  11. self.timer = QTimer()
  12. if not self.capture.isOpened():
  13. raise ValueError("Device not found")
  14. self.timer.timeout.connect(self.read_frame)
  15. self.timer.setInterval(1000 / (self.fps or 30))
  16. self.timer.start()
  17. def __del__(self):
  18. self.timer.stop()
  19. self.capture.release()
  20. @property
  21. def fps(self):
  22. """Frames per second."""
  23. return int(self.capture.get(cv2.CAP_PROP_FPS))
  24. @property
  25. def size(self):
  26. """Returns the size of the video frames: (width, height)."""
  27. width = int(self.capture.get(cv2.CAP_PROP_FRAME_WIDTH))
  28. height = int(self.capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
  29. return (width, height)
  30. def read_frame(self):
  31. """Read frame into QImage and emit it."""
  32. success, frame = self.capture.read()
  33. if success:
  34. img = _convert_array_to_qimage(frame)
  35. self.frame_ready.emit(img)
  36. else:
  37. raise ValueError("Failed to read frame")
  38. def _convert_array_to_qimage(a):
  39. height, width, channels = a.shape
  40. bytes_per_line = channels * width
  41. cv2.cvtColor(a, cv2.COLOR_BGR2RGB, a)
  42. return QImage(a.data, width, height, bytes_per_line, QImage.Format_RGB888)