Interpolation of values when zooming down

巧了我就是萌 提交于 2019-12-13 04:42:23

问题


I have a 2D array that I would like to down sample to compare it to another.

Lets say my array x is 512x512, I'd like an array y 128x128 where the elements of y are build using an interpolation of the values overs 4x4 blocks of x (this interpolation could just be taking the average, but other methodes, like geometric average, could be interesting)

So far I looked at scipy.ndimage.interpolation.zoom but I don't get the results I want

>> x = np.arange(16).reshape(4,4)
>> print(x)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
>> y = scipy.ndimage.interpolation.zoom(x, 0.5)
>> print(y)
[[ 0  3]
 [12 15]]

I expected y to be

[[ 2.5  4.5]
 [10.5 12.5]]

Note that simply setting dtype=np.float32 doesn't solve that ...


回答1:


What you seem to be looking for is the mean over blocks of 4, which is not obtainable with zoom, since zoom uses interpolation (see its docstring)

To obtain what you show, try the following

import numpy as np
x = np.arange(16).reshape(4, 4)

xx = x.reshape(len(x) // 2, 2, x.shape[1] // 2, 2).transpose(0, 2, 1, 3).reshape(len(x) // 2, x.shape[1] // 2, -1).mean(-1)

print xx

This yields

[[  2.5   4.5]
 [ 10.5  12.5]]

Alternatively, this can be done using sklearn.feature_extraction.image.extract_patches

from sklearn.feature_extraction.image import extract_patches

patches = extract_patches(x, patch_shape=(2, 2), extraction_step=(2, 2))

xx = patches.mean(-1).mean(-1)

print xx

However, if your goal is to subsample an image in a graceful way, then taking the mean over blocks of the image is not the right way to do it: It is likely to cause aliasing effects. What you should do in this case is smooth the image ever so slightly using scipy.ndimage.gaussian_filter (e.g. sigma=0.35 * subsample_factor) and then subsample simply by indexing [::2, ::2]




回答2:


sklearn.feature_extraction.image.extract_patches cleverly uses np.lib.stride_tricks.as_strided to produce a windowed array that can be operated on.

The sliding_window function, found here Efficient Overlapping Windows with Numpy, produces a windowed array with or without overlap also and let's you get a glimpse of what is happening under the hood.

>>> a = np.arange(16).reshape(4,4)

step_height,step_width determines the overlap for the windows - in your case the steps are the same as the window size, no overlap.

>>> window_height, window_width, step_height, step_width = 2, 2, 2, 2
>>> y = sliding_window(a, (window_height, window_width), (step_height,step_width))
>>> y
array([[[ 0,  1],
        [ 4,  5]],

       [[ 2,  3],
        [ 6,  7]],

       [[ 8,  9],
        [12, 13]],

       [[10, 11],
        [14, 15]]])

Operate on the windows:

>>> y = y.mean(axis = (1,2))
>>> y
array([  2.5,   4.5,  10.5,  12.5])

You need to determine the final shape depending on the number of windows.

>>> final_shape = (2,2)
>>> y = y.reshape(final_shape)
>>> y
array([[  2.5,   4.5],
       [ 10.5,  12.5]])

Searching SO for numpy, window, array should produce numerous other answers and possible solutions.



来源:https://stackoverflow.com/questions/26846584/interpolation-of-values-when-zooming-down

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!