Python: downsample 2D numpy array by non-integer coefficient

I need to reduce the 2D numpy array with a non-integer factor (e.g. 100x100 array to 45x45 array) in such a way as to perform local averaging, just like Photoshop / gimp will do this for an image. I need double precision. Current options cannot do it well.

  • scipy.ndimage.zoom does not perform averaging and mainly uses the selection of the nearest neighbors (see the previous question scipy.ndimage.interpolation.zoom uses an algorithm close to the neighbor to scale )

  • scipy.misc.imresize converts an array to int8; I need more precision and floating point

  • skimage.transform.rescale also uses the closest neighbor and sends you to skimage.transform.downscale_local_mean for local averaging,

  • skimage.transform.downscale_local_mean can only perform an integer scale factor (and an image with images with zeros if the coefficient is not integer). Integer scale factor is a trivial excess.

Did I miss any other options?

+5
source share
1 answer

In the end, I wrote a small function that scales the image using scipy.ndimage.zoom , but to reduce the scale, it first expands it to be a multiple of the original form, and then reduces the scale by averaging over the block. It accepts any other keyword arguments for scipy.zoom ( order and prefilter )

I'm still looking for a cleaner solution using the available packages.

 def zoomArray(inArray, finalShape, sameSum=False, **zoomKwargs): inArray = np.asarray(inArray, dtype = np.double) inShape = inArray.shape assert len(inShape) == len(finalShape) mults = [] for i in range(len(inShape)): if finalShape[i] < inShape[i]: mults.append(int(np.ceil(inShape[i]/finalShape[i]))) else: mults.append(1) tempShape = tuple([i * j for i,j in zip(finalShape, mults)]) zoomMultipliers = np.array(tempShape) / np.array(inShape) + 0.0000001 rescaled = zoom(inArray, zoomMultipliers, **zoomKwargs) for ind, mult in enumerate(mults): if mult != 1: sh = list(rescaled.shape) assert sh[ind] % mult == 0 newshape = sh[:ind] + [sh[ind] / mult, mult] + sh[ind+1:] rescaled.shape = newshape rescaled = np.mean(rescaled, axis = ind+1) assert rescaled.shape == finalShape if sameSum: extraSize = np.prod(finalShape) / np.prod(inShape) rescaled /= extraSize return rescaled 
+1
source

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


All Articles