You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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()方法修改已创建窗口的标题,具体步骤:

  1. 保留初始创建的窗口名winName,循环中继续用cv2.imshow(winName, frame)显示画面;
  2. 计算出FPS后,用cv2.setWindowTitle()将窗口标题设置为原名称+FPS信息;
  3. 若不需要在画面内显示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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 17:50:24