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

如何避免PyQt5+YOLOv5模糊覆盖被屏幕捕获以消除闪烁

解决PyQt5+YOLOv5人体模糊覆盖层闪烁问题

问题根源

闪烁的核心原因是:屏幕捕获工具(mss)会抓取到PyQt绘制的黑色覆盖层,YOLOv5检测到这些黑色矩形后,误判原本的人体目标消失,进而移除覆盖层;下一次捕获时又能检测到人体,重新绘制覆盖层,如此反复就造成了闪烁。

解决方案

要消除闪烁,关键是让屏幕捕获过程完全忽略PyQt的覆盖层窗口,确保YOLOv5只分析真实的屏幕内容,而非我们绘制的模糊层。下面提供两种可靠的实现方式:

方法1:给覆盖层窗口添加「捕获透明」扩展样式

通过Windows API给窗口设置WS_EX_TRANSPARENT和WS_EX_LAYERED扩展样式,让屏幕捕获工具(如mss)忽略该窗口,同时保持窗口在视觉上可见且置顶。

修改后的完整代码:

import sys, win32api, win32gui, win32con
import torch
import numpy as np
import mss
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QPainter, QColor

# Load YOLOv5 model
model = torch.hub.load('ultralytics/yolov5', 'yolov5x', pretrained=True)

# Initialize screen capture
sct = mss.mss()
if torch.cuda.is_available():
    print("CUDA ACCELERATION [ENABLED]")
else:
    print("[!] CUDA ACCELERATION IS UNAVAILABLE")

# Screen dimensions
SCREEN_WIDTH, SCREEN_HEIGHT = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN), win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN)

def get_screen():
    monitor = {"top": 0, "left": 0, "width": SCREEN_WIDTH, "height": SCREEN_HEIGHT}
    screenshot = sct.grab(monitor)
    return np.array(screenshot)

class BlurOverlay(QWidget):
    def __init__(self):
        super().__init__()
        self.setGeometry(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)
        # 设置基础窗口属性
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool | Qt.WindowTransparentForInput)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.detections = []
        
        # 添加Windows扩展样式,让窗口对屏幕捕获透明
        hwnd = int(self.winId())
        ex_style = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
        # WS_EX_TRANSPARENT:让窗口不被屏幕捕获工具识别;WS_EX_LAYERED:配合半透明属性
        ex_style |= win32con.WS_EX_TRANSPARENT | win32con.WS_EX_LAYERED
        win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, ex_style)

    def paintEvent(self, event):
        painter = QPainter(self)
        for x1, y1, x2, y2, _, cls in self.detections:
            if cls == 0:  # class 0 is person in COCO dataset
                width, height = int(x2 - x1), int(y2 - y1)
                # Draw dark black rectangle
                painter.setBrush(QColor(0, 0, 0))
                painter.drawRect(int(x1), int(y1), width, height)

    def update_detections(self, detections):
        self.detections = detections
        self.update()

def main():
    app = QApplication(sys.argv)
    overlay = BlurOverlay()
    overlay.show()

    def update_overlay():
        img = get_screen()
        results = model(img)
        detections = results.xyxy[0].cpu().numpy()
        overlay.update_detections(detections)

    timer = QTimer()
    timer.timeout.connect(update_overlay)
    # 适当调高间隔,减少资源占用(根据GPU性能调整)
    timer.start(40)

    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

方法2:改用GDI直接捕获桌面(绕过顶层窗口)

如果mss的捕获方式仍有问题,可以直接使用Windows GDI API捕获桌面DC,这种方式会直接抓取桌面底层内容,完全忽略所有顶层窗口。

修改get_screen函数如下:

def get_screen():
    # 获取桌面DC
    hdesktop = win32gui.GetDesktopWindow()
    desktop_dc = win32gui.GetWindowDC(hdesktop)
    img_dc = win32ui.CreateDCFromHandle(desktop_dc)
    
    # 创建兼容DC
    mem_dc = img_dc.CreateCompatibleDC()
    
    # 创建位图
    screenshot = win32ui.CreateBitmap()
    screenshot.CreateCompatibleBitmap(img_dc, SCREEN_WIDTH, SCREEN_HEIGHT)
    mem_dc.SelectObject(screenshot)
    
    # 捕获桌面
    mem_dc.BitBlt((0, 0), (SCREEN_WIDTH, SCREEN_HEIGHT), img_dc, (0, 0), win32con.SRCCOPY)
    
    # 转换为numpy数组
    bmpinfo = screenshot.GetInfo()
    bmpstr = screenshot.GetBitmapBits(True)
    img = np.frombuffer(bmpstr, dtype=np.uint8).reshape((bmpinfo['bmHeight'], bmpinfo['bmWidth'], 4))
    img = img[..., :3]  # 去掉Alpha通道,转为RGB
    
    # 释放资源
    mem_dc.DeleteDC()
    img_dc.DeleteDC()
    win32gui.ReleaseDC(hdesktop, desktop_dc)
    win32gui.DeleteObject(screenshot.GetHandle())
    
    return img

关键说明

  • 方法1更轻量,保留mss的高效捕获,仅通过窗口属性实现隔离,适合大多数场景。
  • 方法2完全绕过顶层窗口,兼容性最好,但代码稍复杂,资源占用略高。
  • 调整定时器间隔(如从30ms改为40ms)可以平衡检测精度和资源占用,进一步减少闪烁概率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 18:42:03