如何在Python的OpenCV窗口标题中动态更新FPS
OpenCV窗口标题显示FPS避免重复创建窗口
我正在用Python+OpenCV做视频相关开发,已经实现了在窗口左上角显示FPS,现在想把FPS移到窗口标题上。原代码如下:
import cv2 import datetime import imutils def GetCoord(event, x, y, flags, param): if event == cv2.EVENT_LBUTTONDOWN: print("X: {} | Y: {}".format(x, y)) winName = "My Project" cv2.namedWindow(winName) cv2.setMouseCallback(winName, GetCoord) cap = cv2.VideoCapture(0) fps_start_time = datetime.datetime.now() fps = 0 total_frames = 0 while True: ret, frame = cap.read() frame = imutils.resize(frame, width=800) total_frames = total_frames + 1 fps_end_time = datetime.datetime.now() time_diff = fps_end_time - fps_start_time if time_diff.seconds == 0: fps = 0.0 else: fps = (total_frames / time_diff.seconds) fps_text = "FPS: {:.2f}".format(fps) cv2.putText(frame, fps_text, (5, 30), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0, 0, 255), 1) cv2.imshow(winName, frame) key = cv2.waitKey(1) if key == ord('q'): break cv2.destroyAllWindows()
我尝试改成下面的代码,结果程序不断创建新窗口,运行异常:
cv2.imshow(winName + " FPS: {}".format(fps_text), frame)
问题原因
每次调用cv2.imshow()时传入新的窗口名称,OpenCV会判定为需要创建新窗口,循环执行时就会不断生成新窗口,导致程序异常。
正确实现方式
不要修改cv2.imshow()的窗口名,而是使用cv2.setWindowTitle()方法修改已创建窗口的标题,具体步骤:
- 保留初始创建的窗口名
winName,循环中继续用cv2.imshow(winName, frame)显示画面; - 计算出FPS后,用
cv2.setWindowTitle()将窗口标题设置为原名称+FPS信息; - 若不需要在画面内显示FPS,可删除
cv2.putText()代码行。
修改后的完整代码:
import cv2 import datetime import imutils def GetCoord(event, x, y, flags, param): if event == cv2.EVENT_LBUTTONDOWN: print("X: {} | Y: {}".format(x, y)) winName = "My Project" cv2.namedWindow(winName) cv2.setMouseCallback(winName, GetCoord) cap = cv2.VideoCapture(0) fps_start_time = datetime.datetime.now() fps = 0 total_frames = 0 while True: ret, frame = cap.read() if not ret: break # 防止读取帧失败导致报错 frame = imutils.resize(frame, width=800) total_frames += 1 fps_end_time = datetime.datetime.now() time_diff = fps_end_time - fps_start_time # 改用包含微秒的总秒数计算,避免前几秒秒数为0的问题 total_seconds = time_diff.total_seconds() if total_seconds == 0: fps = 0.0 else: fps = total_frames / total_seconds fps_text = "FPS: {:.2f}".format(fps) # 更新窗口标题 cv2.setWindowTitle(winName, f"{winName} {fps_text}") # 不需要画面内显示FPS则删除此行 # cv2.putText(frame, fps_text, (5, 30), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0, 0, 255), 1) cv2.imshow(winName, frame) key = cv2.waitKey(1) if key == ord('q'): break cap.release() # 释放摄像头资源 cv2.destroyAllWindows()
额外优化
- 原代码用
time_diff.seconds计算FPS,前几秒可能因秒数为0导致FPS显示异常,改用total_seconds = time_diff.total_seconds()包含微秒,计算更准确; - 添加
cap.release()释放摄像头资源,避免程序退出后资源占用。
内容的提问来源于stack exchange,提问作者S Andrew
相关产品推荐
相关产品推荐

