scan.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import time
  2. import threading
  3. import cv2.cv2 as cv2
  4. import PIL
  5. from conf import Config
  6. import qrcode
  7. from tool.typing import *
  8. class HGSCapture:
  9. """ 摄像头扫描 """
  10. def __init__(self, capnum: int = Config.capture_num, *args, **kwargs):
  11. args = *args, *Config.capture_arg
  12. if cv2.CAP_DSHOW not in args:
  13. args = *args, cv2.CAP_DSHOW
  14. self._capture = cv2.VideoCapture(int(capnum), *args, **kwargs)
  15. self._frame = None
  16. self._lock = threading.RLock()
  17. def get_image(self):
  18. """ 获取摄像头图像 """
  19. try:
  20. self._lock.acquire()
  21. ret, frame = self._capture.read()
  22. if ret:
  23. self._frame = frame
  24. finally:
  25. self._lock.release()
  26. return ret
  27. def get_frame(self):
  28. """ 获取 frame """
  29. try:
  30. self._lock.acquire()
  31. frame = self._frame
  32. finally:
  33. self._lock.release()
  34. return frame
  35. class QRCode:
  36. def __init__(self, data, get_time: Optional[time_t] = None):
  37. self._data: str = data
  38. if get_time is None:
  39. get_time = time.time()
  40. self._time: time_t = get_time
  41. def __repr__(self):
  42. return f"QR:'{self._data}'"
  43. def get_data(self):
  44. return self._data
  45. def get_time(self):
  46. return self._time
  47. def save_img(self, image: str) -> bool:
  48. try:
  49. with open(image, "wb") as f:
  50. img = self.make_img()
  51. img.save(f)
  52. except (IOError, FileExistsError, FileNotFoundError):
  53. return False
  54. else:
  55. return True
  56. def make_img(self) -> PIL.Image:
  57. qr = qrcode.QRCode(
  58. version=None,
  59. error_correction=qrcode.constants.ERROR_CORRECT_H,
  60. box_size=10,
  61. border=4
  62. )
  63. qr.add_data(self._data)
  64. qr.make(fit=True)
  65. return qr.make_image()
  66. class HGSQRCoder:
  67. """ 二维码扫描仪 """
  68. def __init__(self, cap: HGSCapture):
  69. self._cap = cap
  70. self._last_qr: Optional[QRCode] = None
  71. self._lock = threading.RLock()
  72. def get_qr_code(self) -> Optional[QRCode]:
  73. try:
  74. self._lock.acquire()
  75. re = self.is_qr_code()
  76. last_qr = self._last_qr
  77. finally:
  78. self._lock.release()
  79. if re:
  80. return last_qr
  81. return None
  82. def is_qr_code(self) -> bool:
  83. try:
  84. self._lock.acquire()
  85. frame = self._cap.get_frame()
  86. gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  87. coder = cv2.QRCodeDetector()
  88. try:
  89. data, points, straight_qrcode = coder.detectAndDecode(gray)
  90. except cv2.error:
  91. return False
  92. old_qr: Optional[QRCode] = self._last_qr
  93. if len(data) > 0:
  94. self._last_qr = QRCode(data)
  95. return old_qr is None or data != old_qr.get_data()
  96. elif len(data) == 0 and old_qr is not None:
  97. if time.time() - old_qr.get_time() >= 1.5: # 时间间隔大于2s 自动取消
  98. self._last_qr = QRCode(data)
  99. return False
  100. finally:
  101. self._lock.release()