使用Python PIL和Windows API截取活动窗口截图:如何处理圆角?

16 投票
1 回答
3856 浏览
提问于 2025-04-16 17:37

在这个项目中,我使用Windows的API来截屏(这样可以处理多个显示器),然后把截图转换成PIL图像;如果需要的话,我还会在窗口周围加个阴影。

我遇到的问题是,截图实际上是窗口的矩形区域;这意味着我捕捉到了窗口后面的背景,包括那些圆角的地方,而我并不想要这些。我在网上查了很多资料,发现了一些关于透明度的文档和教程,我猜我应该找到一种方法来获取窗口的形状,这样我就可以把它做成一个遮罩,应用到我得到的(矩形)图像上。但我找不到获取这个遮罩的方法。有没有人能帮帮我?

下面是我的代码:

hwnd = win32gui.GetForegroundWindow()

l, t, r, b = win32gui.GetWindowRect(hwnd)
w = r - l
h = b - t

hwndDC = win32gui.GetWindowDC(hwnd)
mfcDC  = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC()

saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)
saveDC.SelectObject(saveBitMap)

saveDC.BitBlt((0, 0), (w, h),  mfcDC,  (0, 0),  win32con.SRCCOPY)

#add cursor
if showcursor:
    curFlags, curH, (curX, curY) = win32gui.GetCursorInfo()
    saveDC.DrawIcon((curX, curY), curH)

#load into PIL image
"""http://stackoverflow.com/questions/4199497/image-frombuffer-with-16-bit-image-data"""
bmpinfo = saveBitMap.GetInfo()
bmpstr = saveBitMap.GetBitmapBits(True)
im = Image.frombuffer(
    'RGB',
    (bmpinfo['bmWidth'], bmpinfo['bmHeight']),
    bmpstr, 'raw', 'BGRX', 0, 1)

win32gui.DeleteObject(saveBitMap.GetHandle())
saveDC.DeleteDC()
mfcDC.DeleteDC()
win32gui.ReleaseDC(hwnd, hwndDC)

return im

下面是一个稍微放大的窗口截图,背景是蓝色的:

如你所见,角落的蓝色部分是不应该出现的。

1 个回答

1

为什么不使用一种叫做边缘检测的算法(比如Prewitt或Sobel)来找出窗口的边缘呢?其实你只需要把图像边界和窗口边界之间的像素的透明度(alpha通道)设置一下就可以了。

撰写回答