Search code examples
pythonmacosopencvpyobjc

Converting CGImage to python image (pil/opencv)


I want to do some pattern recognition on my screen and will use the Quartz/PyObjc libraries to get the screenshots.

I get the screenshot as a CGImage. I want to search for a pattern in it using the openCV library, but can't seem to find how to convert the data to be readable by opencv.

So what I want to do is this:

#get screenshot and reference pattern
img = getScreenshot() # returns CGImage instance, custom function, using Quartz
reference = cv2.imread('ref/reference_start.png') #get the reference pattern

#search for the pattern using the opencv library
result = cv2.matchTemplate(screen, reference, cv2.TM_CCOEFF_NORMED)

#this is what I need
minVal,maxVal,minLoc,maxLoc = cv2.minMaxLoc(result)

I have no idea how to do this and can't find information through google.


Solution

  • All these answers ignore Tom Gangemis comment to this answer. Picture of widths which are not multiples of 64 will be screwed up. I made an efficient approach using np strides:

    cg_img = CG.CGWindowListCreateImage(
        CG.CGRectNull,
        CG.kCGWindowListOptionIncludingWindow,
        wnd_id,
        CG.kCGWindowImageBoundsIgnoreFraming | CG.kCGWindowImageNominalResolution
    )
    
    bpr = CG.CGImageGetBytesPerRow(cg_img)
    width = CG.CGImageGetWidth(cg_img)
    height = CG.CGImageGetHeight(cg_img)
    
    cg_dataprovider = CG.CGImageGetDataProvider(cg_img)
    cg_data = CG.CGDataProviderCopyData(cg_dataprovider)
    
    np_raw_data = np.frombuffer(cg_data, dtype=np.uint8)
    
    np_data = np.lib.stride_tricks.as_strided(np_raw_data,
                                              shape=(height, width, 3),
                                              strides=(bpr, 4, 1),
                                              writeable=False)