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

使用win32gui捕获窗口屏幕时如何直接输出灰度图像

解决方案

你使用的win32 GDI捕获逻辑默认输出BGRA四通道格式,GDI本身不支持直接输出灰度位图,无法完全在硬件捕获层面直接生成灰度图,但可以在内存数据转换阶段直接处理得到灰度图,效率比先输出BGR再单独转灰度更高。

你之前调用cv.cvtColor未得到预期效果,大概率是颜色通道顺序参数用错:原代码输出的图像是BGR顺序(GDI输出BGRA,去掉alpha后为BGR而非RGB),如果误传cv.COLOR_RGB2GRAY参数就会得到权重错误的灰度图,需使用cv.COLOR_BGR2GRAY参数。

直接返回灰度图的修改后代码

在捕获数据阶段直接按OpenCV灰度转换标准权重(B:0.114、G:0.587、R:0.299)计算,无需额外调用cvtColor:

def get_screenshot(self):
    # get the window image data
    wDC = win32gui.GetWindowDC(self.hwnd)
    dcObj = win32ui.CreateDCFromHandle(wDC)
    cDC = dcObj.CreateCompatibleDC()
    dataBitMap = win32ui.CreateBitmap()
    dataBitMap.CreateCompatibleBitmap(dcObj, self.w, self.h)
    cDC.SelectObject(dataBitMap)
    cDC.BitBlt((0, 0), (self.w, self.h), dcObj, (self.cropped_x, self.cropped_y), win32con.SRCCOPY)
    
    # convert the raw data into a format opencv can read
    signedIntsArray = dataBitMap.GetBitmapBits(True)
    img = np.fromstring(signedIntsArray, dtype='uint8')
    img.shape = (self.h, self.w, 4)

    # free resources
    dcObj.DeleteDC()
    cDC.DeleteDC()
    win32gui.ReleaseDC(self.hwnd, wDC)
    win32gui.DeleteObject(dataBitMap.GetHandle())

    # 直接计算灰度图,和cv.COLOR_BGR2GRAY转换结果完全一致
    img_gray = (img[...,0] * 0.114 + img[...,1] * 0.587 + img[...,2] * 0.299).astype(np.uint8)
    # 保证数组C连续,避免后续接口报错
    img_gray = np.ascontiguousarray(img_gray)

    return img_gray

补充说明

如果更倾向使用OpenCV原生接口转换,只需在原代码返回前添加一行即可:

img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

输出的灰度图完全满足单应性计算的输入要求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 08:15:04