使用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
相关产品推荐
相关产品推荐

