# Client主进程 # 读取摄像头数据并显示 import MultiFunc_V2 as Func import cv2 import threading import numpy as np import time import queue rtsp_ulr = 0 #"rtsp://192.168.1.206:554" # rtsp_ulr = "rtsp://admin:123456@192.168.1.123/video1" # 自定义无缓存读视频类 class NetCameraCapture: """Customized VideoCapture, always read latest frame """ def __init__(self, camera_id): # "camera_id" is a int type id or string name self.cap = cv2.VideoCapture(camera_id) self.q = queue.Queue(maxsize=3) self.stop_threads = False # to gracefully close sub-thread th = threading.Thread(target=self._reader) th.daemon = True # 设置工作线程为后台运行 th.start() # 实时读帧,只保存最后一帧 def _reader(self): while not self.stop_threads: if self.cap.isOpened(): # 判断是否已经打开 ret, frame = self.cap.read() if not ret: break if not self.q.empty(): try: self.q.get_nowait() except queue.Empty: pass self.q.put(frame) def read(self): return True, self.q.get() def get(self, id): return self.cap.get(id) def release(self): self.stop_threads = True self.cap.release() class ClientThread(threading.Thread): def __init__(self): self._running = True # 定义线程状态变量 super().__init__() def terminate(self): self._running = False def run(self): while self._running: if GlobalVar.event1.isSet(): GlobalVar.faces, temp_name = Func.function(GlobalVar.frame) # 如果识别结果为空,且少于15张图片(约0.5s),则不更新name if len(temp_name) < 2 and GlobalVar.i < 15: # 识别结果为空 GlobalVar.i = GlobalVar.i + 1 else: GlobalVar.name = temp_name GlobalVar.i = 0 time.sleep(0.02) class GlobalVar: event1 = threading.Event() # 用于主进程读取摄像头图像时,不会同时取用图像 frame = [] faces = np.array([]) t = ClientThread() # 图片处理的子线程 sk = Func.ClientNetworkThread() # 与服务器通信的子线程 width = 0 # 图片宽度 height = 0 # 图片高度 name = "" # 识别结果 i = 0 def init(): GlobalVar.event1.clear # 开启线程 GlobalVar.t.start() GlobalVar.sk.start() def draw_frame(): font = cv2.FONT_HERSHEY_COMPLEX cv2.putText(GlobalVar.frame, "Press 'q': Quit", (20, GlobalVar.height - 30), font, 0.8, (84, 255, 159), 1, cv2.LINE_AA) # 显示人脸识别结果 cv2.putText(GlobalVar.frame, GlobalVar.name, (20, GlobalVar.height - 80), font, 0.8, (84, 255, 159), 1, cv2.LINE_AA) if len(GlobalVar.faces) != 0: cv2.putText(GlobalVar.frame, "Faces: " + str(len(GlobalVar.faces)), (20, 50), font, 1, (0, 0, 255), 1, cv2.LINE_AA) for kk, d in enumerate(GlobalVar.faces): # 绘制矩形框 # cv2.rectangle(GlobalVar.frame, tuple([d.left(), d.top()]), tuple([d.right(), d.bottom()]), cv2.rectangle(GlobalVar.frame, (d[0], d[1]), (d[2], d[3]), (0, 255, 255), 2) # 显示人脸识别结果 cv2.putText(GlobalVar.frame, GlobalVar.name, (d[0], d[1] - 10), font, 0.8, (0, 255, 255), 1, cv2.LINE_AA) else: cv2.putText(GlobalVar.frame, "Faces: " + str(0), (20, 50), font, 1, (0, 0, 255), 1, cv2.LINE_AA) def demo(): # 初始化 init() # 创建 cv2 摄像头对象 # 获取摄像机来捕获实时流 参数0表示本台设备的序号为0的采集设备(camera) # capture = cv2.VideoCapture(0) # 使用网络摄像头 capture = NetCameraCapture(rtsp_ulr) # 获取捕获图像分辨率 GlobalVar.width, GlobalVar.height = int(capture.get(3)), int(capture.get(4)) print("图像尺寸:", GlobalVar.width, "x", GlobalVar.height, "px") i = 0 s1 = time.time() while i < 1000: i = i + 1 GlobalVar.event1.clear() # 置为false,不允许子进程读取图片 ret, GlobalVar.frame = capture.read() # if frame is read correctly ret is True if not ret: print("Can't receive frame (stream end?). Exiting ...") exit() GlobalVar.event1.set() # 置为true,允许子进程读取图片 # 在图片上绘制文字和框 draw_frame() # 窗口显示 show with opencv cv2.imshow("Face Recognition", GlobalVar.frame) if cv2.waitKey(1) == ord('q') or cv2.waitKey(1) == ord('Q'): # 关闭摄像头 释放窗口 capture.release() cv2.destroyAllWindows() GlobalVar.t.terminate() break s2 = time.time() print(i, " 张图片共用时:", (s2 - s1)) GlobalVar.t.terminate() GlobalVar.sk.terminate() if __name__ == "__main__": demo()