numpy effiency way to multiple transformation array

In Linux, I take screenshots and draw squares at certain coordinates. My code works fine, but I transform the numpy array several times.


def get_screenshot(self):
    # Take screenshot
    pixmap = window.get_image(0, 0, width, height, X.ZPixmap, 0xffffffff)
    # type(data) = <class 'bytes'>
    data = pixmap.data
    # type(data) = <class 'bytearray'>
    data = bytearray(data)

    self.screenshot = np.frombuffer(data, dtype="uint8").reshape((height, width, 4))

def getRGBScreenShot(self):
    with self.lock:
        image = self.screenshot[..., :3]
        image = np.ascontiguousarray(image)
        return image

1- If i dont use data = bytearray(data), the numpy will be read-only

2- image = np.frombuffer(data, dtype="uint8").reshape((height, width, 4)) creating numpy array

3- self.screenshot[..., :3] to convert rgb. I guest it should be.

4- If i dont use np.ascontiguousarray, the numpy will be C_CONTIGUOUS : False

Can the above steps be optimized?
Is constantly processing an array bad for performance?

also for grayscale the situation is worse:


def getGrayScaleScreenShot(self):
    with self.lock:
        # Convert to grayscale using luminosity formula
        gray_image = np.dot(self.screenshot[..., :3], [0.2989, 0.5870, 0.1140])
        gray_image = np.ascontiguousarray(gray_image.astype(np.uint8))
        return gray_image

  • 1

    “the numpy will be read-only” — is that a problem? In the code you show, you only read it when doing the colour conversion.

    – 

  • Anyway, there’s hardly enough happening here to worry about optimization. When the program becomes slow, do some measurements with a profiler, to see what you actually need to focus on.

    – 

Note that numpy tries to avoid actual changes of the in-memory array if possible by only changing the metadata of an array (how the memory should be read). For example reshaping or slicing a numpy array usually only returns a view of the original array with changed metadata. So this has basically no impact on performance.

You only create a numpy array at point 2 in your list (and reshape it). Point 3 is slicing which, as said before, should not impact performance in any way. I do not understand, why you need to use ascontiguousarray() though, as np.frombuffer() should automatically return a C-contiguous array. Reshaping or slicing it does not change that. You can use

array_name.flags['C_CONTIGUOUS']

to see if a numpy-array is C-contiguous (it returns True or False).

Also: If you use pure numpy-functionality, you are probably as efficient as you can be in Python and I would not worry about performance until you actually see in impact with frequently running code.

Leave a Comment