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

Python+OpenCV 3.0.0无法关闭最后一个窗口问题求助

解决OpenCV 3.0.0 + Python 2.7无法关闭窗口的问题

我之前在Python 2.7环境下用OpenCV 3.x处理多摄像头窗口时,也碰到过一模一样的销毁窗口失效问题——单个destroyWindow留最后一个窗口,destroyAllWindows完全没反应,试了startWindowThread也没用。结合当时的调试经验,给你几个亲测有效的解决方案:

方案1:重构代码,避免重复创建窗口

你的代码里每次循环都调用cv2.namedWindow,这会导致OpenCV内部重复生成窗口句柄,销毁时出现句柄混乱。把窗口初始化逻辑移到循环外,只创建一次窗口,能大幅降低销毁失败的概率:

import time, cv2
print(cv2.__version__)
cap1 = cv2.VideoCapture(0)
cap2 = cv2.VideoCapture(1)

# 窗口初始化只做一次,不要放进循环
cv2.namedWindow("Camera 1", cv2.WINDOW_NORMAL)
cv2.namedWindow("Camera 2", cv2.WINDOW_NORMAL)
cv2.resizeWindow("Camera 1", 400, 400)
cv2.resizeWindow("Camera 2", 400, 400)
cv2.moveWindow("Camera 1" , 0, 0)
cv2.moveWindow("Camera 2", 400, 0)

cv2.waitKey(10)
while True:
    val1, img1 = cap1.read()
    val2, img2 = cap2.read()
    cv2.imshow("Camera 1", img1)
    cv2.imshow("Camera 2", img2)
    
    if cv2.waitKey(50) & 0xFF == ord('q'):
        break

cap1.release()
cap2.release()

# 先隐藏窗口,再触发销毁
cv2.setWindowProperty("Camera 1", cv2.WND_PROP_VISIBLE, 0)
cv2.setWindowProperty("Camera 2", cv2.WND_PROP_VISIBLE, 0)
cv2.waitKey(10)

cv2.destroyAllWindows()
# 多调用几次waitKey,确保事件循环处理完销毁请求
for _ in range(5):
    cv2.waitKey(1)

time.sleep(1)
print("3")
time.sleep(1)
print("2")
time.sleep(1)
print("1")
time.sleep(1)
print("finish")

方案2:调用系统级API强制关闭窗口

如果方案1还是不行,说明OpenCV的窗口线程已经卡死,这时候可以绕过OpenCV,直接调用系统API关闭窗口:

针对Windows系统

用ctypes调用Windows API发送关闭窗口的消息:

import ctypes
user32 = ctypes.WinDLL('user32', use_last_error=True)

def force_close_window(window_title):
    # 找到窗口句柄
    hwnd = user32.FindWindowA(None, window_title.encode('utf-8'))
    if hwnd:
        # 发送WM_CLOSE消息(0x0010)
        user32.SendMessageA(hwnd, 0x0010, 0, 0)

# 在释放摄像头后调用
cap1.release()
cap2.release()
force_close_window("Camera 1")
force_close_window("Camera 2")

针对Linux系统

用wmctrl命令(需要先安装:sudo apt install wmctrl):

import os
# 关闭指定标题的窗口
os.system("wmctrl -c 'Camera 1'")
os.system("wmctrl -c 'Camera 2'")

方案3:终止OpenCV窗口线程(极端情况)

如果以上都无效,可以直接终止OpenCV的窗口线程。在Python 2.7中,可以用threading模块找到对应的线程并终止,但这种方式比较暴力,可能会有资源泄漏,仅作为最后手段:

import threading

# 遍历所有线程,终止OpenCV相关的窗口线程
for thread in threading.enumerate():
    if 'cv2' in thread.name.lower() or 'window' in thread.name.lower():
        thread._Thread__stop()

为什么你的原代码会出问题?

  1. 循环内重复调用cv2.namedWindow,导致OpenCV内部维护的窗口句柄列表混乱,销毁时无法正确定位所有窗口;
  2. OpenCV 3.0.0在Python 2.7环境下的窗口事件循环存在bug,waitKey的触发时机不足时,销毁事件无法被正确处理;
  3. 多摄像头的视频流读取可能占用了部分线程资源,导致窗口销毁的事件被阻塞。

内容的提问来源于stack exchange,提问作者user8400839

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:56:46