4

I created an image from a window screenshot using Win32gui. The object has the type:

object 'PyCBitmap' - assoc is 000002AF9A64DB50, vi=<None>

I want to then pass this for analysis with OpenCV. I have had success reading in a saved .bmp file using:

cv2.imread(img_file, 0)

When trying using cv2.imread for a PyCBitmap object I get the following error:

TypeError: bad argument type for built-in operation

My question is:

How can I convert the PyCBitmap object into an acceptable type for cv2.imread, without having to save the object as a .bmp file first?

Thanks in advance,

Behzad

p.s I'm using opencv 3.1 with python bindings, I'm happy to follow advice written in C++ or python :)

Behzad
  • 125
  • 1
  • 1
  • 10

1 Answers1

1

I've been looking for the same thing, and I finally found it by combining several other SO answers:

Basically, the code I came up with is:

import PIL, numpy, cv2
bmpinfo = dataBitMap.GetInfo()
bmparray = numpy.asarray(dataBitMap.GetBitmapBits(), dtype=numpy.uint8)
pil_im = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmparray, 'raw', 'BGRX', 0, 1)
pil_array = numpy.array(pil_im)
cv_im = cv2.cvtColor(pil_array, cv2.COLOR_RGB2BGR)

Brief explanation: Python OpenCV just uses numpy arrays, so the trick is really getting the bytes into the right numpy array format. As it turns out, for this you need an image processing library like PIL that can handle the image-specific logic like cutting out the alpha channel. The input data is generally RGBX format, PIL converts to RGB, and OpenCV converts that to BGR which it likes.

I profiled this and unfortunately it is dramatically slower than GetBitmapBits() and in converting its tuple result to an array.

Community
  • 1
  • 1
Adam S
  • 8,665
  • 17
  • 63
  • 98