一、实时传输数据
在真实情况下,人脸数据的信息采集传输应是实时的,而不是用对话框形式传输一张图片,所以我们需将摄像头采集的数据,与发送网络请求关联起来。
二、核心代码
-
在窗口创建时就获取 accesstoken 值,在 myWindow 类中初始化函数( __init__ )添加:
self.get_accesstoken()
-
创建一个线程类(detectThread),用与执行人脸检测的 post 请求
在发送网络请求,等待返回结果时,会存在一定的等待时间,程序在这里就会阻塞,会存在一定的卡顿现象
采用多线程解决卡顿现象
a.
对象初始化时就应该获取 accesstoken 值def __init__(self, token): super(detectThread, self).__init__() self.access_token = token
b.
重写 run 函数(该函数执行结束,将代表线程结束)def run(self): print("run") self.exec_()
c.
获取窗口某一时刻的图片数据,发送网络请求:def detect_data(self, base64_image): # 请求地址 request_url = "https://aip.baidubce.com/rest/2.0/face/v3/detect" # 请求参数 params = { "image": base64_image, "image_type": "BASE64", "face_field": "age,beauty,gender,glasses,face_type" } # 获取的access_token access_token = self.access_token # 合并的网络请求地址 request_url = request_url + "?access_token=" + access_token # 通过json格式请求 headers = { 'content-type': 'application/json'} # 发送网络post请求,就会存在一定的返回结果等待时间,程序就会阻塞,存在一定的卡顿现象 response = requests.post(request_url, data=params, headers=headers) if response: data = response.json() print(data)
参数 base64_image:从窗口传递的某一时刻的图片数据
某一时刻指发送网络的时间,如每 1000ms发送一次网络请求,则只会每隔1000ms传递一次参数
-
修改 myWindow 类
a.
实现主窗口与线程之间图片数据实时传输的大致流程b.
自定义一个信号与槽detect_data_signal = pyqtSignal(str)
c.
创建一个用于发送人脸请求的线程,并且 detect_data函数关联该自定义信号def create_thread(self): self.detect_thread = detectThread(self.access_token) self.detect_thread.start() self.detect_data_signal.connect(self.detect_thread.detect_data)
d.
修改 on_actionopen 函数def on_actionopen(self): # 启动摄像头 self.camera_data = camera() # 启动定时器,进行定时,每个多长时间获取摄像头信号进行显示 self.timeshow = QTimer(self) self.timeshow.start(50) # 计数 self.count = 0 # 每隔50毫秒将产生一个信号timeout self.timeshow.timeout.connect(self.show_camera) # 每8000ms调用一次人脸检测 # 创建检测线程 self.create_thread() # 获取要检测的数据 self.detection_time = QTimer(self) self.detection_time.start(8000) self.detection_time.timeout.connect(self.get_cameradata)
当点击 “启动签到” 时,就创建一个新的线程,并且每隔8000ms获取一次摄像头数据(调用 get_cameradata 函数)
e.
新建一个 get_cameradata 函数,用于获取摄像头信息,并且发送一个自定义信号def get_cameradata(self): # 摄像头获取画面 camera_img = self.camera_data.read_camera() # 把摄像头画面转换成图片 _, enc = cv2.imencode('.jpg', camera_img) # 设置为base64编码格式 base64_image = base64.b64encode(enc.tobytes()) # 产生信号,传递数据 self.detect_data_signal.emit(str(base64_image))
三、效果如下
可以发现中间还是有些卡顿现象,原因是由窗口产生一个信号直接调用线程中的网络请求检测函数(detect_data)
返回的结果如下:
{
'error_code': 222203, 'error_msg': 'image check fail', 'log_id': 1545256500165, 'timestamp': 1603251891, 'cached': 0, 'result': None}
能有返回结果,说明用这样的方式进行网络通信已经没有问题了。返回结果错误是因为 base64_image 格式的错误。同时还存在些小问题,留到下一次总结!
总结5传送门:人脸课堂签到管理系统(总结五) 解决画面卡顿问题