Kyle Hunter Kyle Hunter - 1 month ago 19
Python Question

Converting a WinAPI screenshot to a OpenCV compatible form

So I originally asked a question here about taking faster screen captures using win api as compared to PIL. I was able to succesfully capture the screen via BitBlt.

Now I am unsure how to convert the bitmap into a form that can be used with OpenCV. OpenCV doesn't have any support for bitmaps, and when I print(im) it is a ~14k long 1D array. OpenCV can't do anything with 1D, and I have tried to reshape it with NUMPY with no success.

def take_screenshot1(hwnd):
wDC = win32gui.GetWindowDC(hwnd)
dcObj=win32ui.CreateDCFromHandle(wDC)
cDC=dcObj.CreateCompatibleDC()
dataBitMap = win32ui.CreateBitmap()
dataBitMap.CreateCompatibleBitmap(dcObj, 765, 503)
cDC.SelectObject(dataBitMap)
cDC.BitBlt((0, 0), (765, 503), dcObj, (0, 0), win32con.SRCCOPY)

im = dataBitMap.GetBitmapBits(False)
#img = np.array(im)
#cv2.cvtColor(img, cv2.COLOR_RGB2BGR)

dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())


edit:
Here is the working code:

def take_screenshot1(hwnd):
wDC = win32gui.GetWindowDC(hwnd)
dcObj=win32ui.CreateDCFromHandle(wDC)
cDC=dcObj.CreateCompatibleDC()
dataBitMap = win32ui.CreateBitmap()
dataBitMap.CreateCompatibleBitmap(dcObj, 765, 503)
cDC.SelectObject(dataBitMap)
cDC.BitBlt((0, 0), (765, 503), dcObj, (0, 0), win32con.SRCCOPY)

im = dataBitMap.GetBitmapBits(False)

img = np.array(im).astype(dtype="uint8")

img.shape = (503,765,4)

cv2.cvtColor(img, cv2.COLOR_RGB2BGR)

dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())

Answer

GetBitmapBits() in its Python incarnation returns an array of signed ints instead of unsigned bytes. You should first convert it to unsigned bytes and then do as @DanMaĆĄek said.

Comments