前言
 目标检测代码对视频进行拆帧检测耗时较长,在界面加入该功能后,界面经常崩溃卡死,下面记录解决的过程。
设计思路
 在参考了一些资料后,尝试了两种解决方法。
①新建线程去进行视频检测,与界面互不干扰。需要解决的问题是如何知道线程中的检测是否结束。
②逐帧检测强制更新GUI将结果显示到相应控件。该方法对电脑的性能有要求。如果检测速度较快,可以选择该方法。我的垃圾a卡深度学习都跑的很呛,电脑性能不错的话可以尝试。
方案一
使用pyqtSignal()-高级自定义信号与槽获取检测是否结束
参考资料
1.定义回传数据方法
1 2 3 4 5 6 7
| def callbacklog(self, msg): self.text = time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime()) + msg + "\n" print(self.text) self.textEdit.setText(self.text)
|
2.启动线程,连接自定义的信号
1 2 3 4 5
| def start_detect(self): th1 = Thread_detect(self) th1.start() th1._signal.connect(self.callbacklog)
|
3.线程中发送信号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
class Thread_detect(QThread): _signal = pyqtSignal(str) def run(self): start = time.perf_counter() ... cap = cv2.VideoCapture(videoName) FrameNumber = cap.get(7) n = 1 self._signal.emit("正在检测中") timeF = 5 fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter(r'路径', fourcc, 18.0, (int(cap.get(3)), int(cap.get(4)))) while (True): ref, frame = cap.read() self._signal.emit("当前进度:"+str(n)+'/'+str(FrameNumber)) if (n % timeF == 0): ...
n = n + 1 if n == FrameNumber: ... end = time.perf_counter() self._signal.emit('视频检测完毕,共%.2f分钟' % ((end - start) / 60.0)) cap.release() out.release() cv2.destroyAllWindows() break
|
 由于电脑性能限制,放弃了实时检测,当检测结束后保存视频,之后在选择播放检测结果。
方案二
逐帧检测,将结果更新到label中。
解决卡顿的关键就是QApplication.processEvents()
直接上代码吧,基本都注释了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| def show_img(self, img): showImg = QImage(img.data, img.shape[1], img.shape[0], img.shape[1] * 3, QImage.Format_RGB888) self.label_image.setPixmap(QPixmap.fromImage(showImg))
def on_pushButton_start_clicked(self): self.cap = cv2.VideoCapture(videoName) FrameNumber = self.cap.get(7) fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter(r'路径', fourcc, 18.0, (int(self.cap.get(3)), int(self.cap.get(4)))) n = 1 if self.cap.isOpened(): self.pushButton_detect.setEnabled(False)
self.video_flg = True while self.video_flg: ret, self.img_scr = self.cap.read() self.img_scr = cv2.cvtColor(self.img_scr, cv2.COLOR_BGR2RGB) print("当前帧数",n) if( n % 10 == 0): ...
self.show_img(img) frame = cv2.cvtColor(self.img_scr, cv2.COLOR_RGB2BGR) out.write(frame.astype('uint8')) n = n+1 if n == FrameNumber: print('视频检测完毕') self.pushButton_detect.setEnabled(True) self.cap.release() out.release() cv2.destroyAllWindows() break QApplication.processEvents() else: self.textEdit.setText('路径错误!!!\n请检查')
|
总结
 之前实在没有接触过,本来用强制更新GUI的方法解决,但是垃圾电脑它速度不行,眨眼补帧都不行。后来选择线程去检测视频,没有查到python中判断线程状态的内置函数,于是就用textEdit控件接收到检测完毕信号,然后在播放保存的检测结果。