What is an efficient way to scale an int16 numpy array of an int8 numpy array

Im trying to find an efficient way to scale arrays with 2 bytes (-32K β†’ + 32K) to 8 bits (0 β†’ 255) using a special scaling function. A very inefficient method that works (where minVal and maxVal are the minimum and maximum values ​​in the original 2-byte numpy array, and paddingVal in the original will be set to 0):

... pixel_array = np.zeros( length, dtype=np.int16) byte_array = np.zeros( length, dtype=np.uint8) .... i = 0 for val in np.nditer(pixel_array): value = 0.0 if val == paddingVal: byte_array[i] = 0 else: value = 255.0 * ( val - minVal ) / (maxVal - minVal - 1.0) byte_array[i] = (round(value)) i += 1 

I can't figure out how to avoid the loop and still do if ... and apply the zoom function.

THX

+4
source share
2 answers

You can use a mask to use vectorization of numpy (implicit loops), which will be much faster:

 mask = pixel_array == paddingVal byte_array[mask] = 0 byte_array[~mask] = np.round(255.0 * (pixel_array[~mask] - minVal) / (maxVal - minVal - 1.0)) 

It can also be done in a way that is cleaner because you do not need to create a byte_array in advance:

 byte_array = np.round(255.0 * (pixel_array - minVal) / (maxVal - minVal - 1.0)).astype(np.uint8) byte_array[pixel_array == paddingVal] = 0 

Edit: as Joe Kington points out in a comment on the question, this is memory trading for speed.

+2
source

Try:

 byte_array[i] = (((val << 16) >> 8) & 0xFF0000) >> 16 

Val value is assumed to be a 32-bit number from 0 to 65535

+3
source

Source: https://habr.com/ru/post/1486874/


All Articles