文章目录
问题
近日在做项目的时候,需要使用多线程来合成画面,然后一个子线程通过 OpenCV
中的 imshow()
模块显示在窗口上。
但是遇到一个问题:虽然程序能够正常运行,但是没有窗口,在 Dock 栏上只有一个白色的图标表明有这个程序在运行。翻阅了好多的博客,许多都说加入下面的代码就能够正常显示画面。
cv2.namedWindow("Flag Operating System")cv2.imshow("Flag Operating System", image)key = cv2.waitKey(1)
我加上了,但是依旧没有反应,这就奇怪了,按道理使用 imshow
就应该能创建窗口。我把 waitKey(1)
中的1
改成了 0
,这时窗口是出现了,但是是黑屏,画面不刷新。
最终,在经历了近两天的查找与修改,终于发现问题出现在多线程上!!!
大概的意思是:OpenCV-Python
的 imshow()
方法不能在子线程上使用,也就是说子线程里使用这个方法无法正确地创建、刷新画面。
解决方法与程序框架
为了解决这个问题,需要加入一个 Queue
将子线程里面的 frame
画面提取到主线程里,然后再在主线程里面显示。大体的程序框架见下面的程序所示。
import queueimport threading# 处理画面的子线程class RenderFrame(threading.Thread): def __init__(self, thread_name, render_queue): threading.Thread.__init__(self, name=thread_name) self.render_data = render_queue # 完成合成的帧缓存列队... ... Your Code ...... def run(self) -> None:... ... Your Code ... ... while True: ... ...frame # 这个是 OpenCV 处理完的画面,将这个画面存入缓存列队 self.render_data.put(image) # 将处理完的画面存入缓存列队 def main(): render_frame_queue = queue.Queue() # 创建一个渲染完成的缓冲队列 ''' 用于缓存 RenderFrame 合成出来的画面,用作缓存列队 ''' display_frame = RenderFrame("RenderFrame", render_frame_queue) display_frame.start() # 开始线程 # 在主线程处理渲染完成的画面 ''' 由于 OpenCV 的限制,无法在子线程中使用 nameWindow 或者 imshow 等方法 只能新建一个多线程列队将渲染完成的信息加入到列队,然后再在主线程中展示出来 ''' while True: frame = render_frame_queue.get() start_time = time.time() # 如果获取的帧不为空 cv2.namedWindow('Window', cv2.WINDOW_KEEPRATIO) cv2.imshow('Window', frame) cv2.waitKey(1) end_time = time.time() print("FPS: ", 1 / (end_time - start_time)) # break cv2.destroyAllWindows() display_frame.join()if __name__ == '__main__': main()
来源地址:https://blog.csdn.net/qq_17790209/article/details/129292431