J'ai des tableaux numpy 2D de base et je voudrais les "sous-échantillonner" à une résolution plus grossière. Existe-t-il un module numpy ou scipy simple qui peut facilement le faire? Je dois également noter que ce tableau est affiché géographiquement via les modules Basemap.
ÉCHANTILLON:
scikit-image
a implémenté une version de travail de downsampling
ici, bien qu'ils hésitent à l'appeler downsampling
car ce n'est pas un sous-échantillonnage en termes de DSP, si je comprends bien:
http://scikit-image.org/docs/dev/api/skimage.measure.html#skimage.measure.block_reduce
mais cela fonctionne très bien, et c'est le seul downsampler
que j'ai trouvé dans Python qui peut traiter np.nan
dans l'image. J'ai sous-échantillonné des images gigantesques avec cela très rapidement.
Lors du sous-échantillonnage, l'interpolation n'est pas la bonne chose à faire. Utilisez toujours une approche agrégée.
J'utilise des moyens de bloc pour ce faire, en utilisant un "facteur" pour réduire la résolution.
import numpy as np
from scipy import ndimage
def block_mean(ar, fact):
assert isinstance(fact, int), type(fact)
sx, sy = ar.shape
X, Y = np.ogrid[0:sx, 0:sy]
regions = sy/fact * (X/fact) + Y/fact
res = ndimage.mean(ar, labels=regions, index=np.arange(regions.max() + 1))
res.shape = (sx/fact, sy/fact)
return res
Par exemple, un tableau de formes (100, 200) utilisant un facteur de 5 (blocs 5x5) donne un résultat de tableau (20, 40):
ar = np.random.Rand(20000).reshape((100, 200))
block_mean(ar, 5).shape # (20, 40)
imresize et ndimage.interpolation.zoom on dirait qu'ils font ce que vous voulez
Je n'ai jamais essayé d'imresize auparavant, mais voici comment j'ai utilisé ndimage.interpolation.zoom
a = np.array(64).reshape(8,8)
a = ndimage.interpolation.zoom(a,.5) #decimate resolution
a est alors une matrice 4x4 avec des valeurs interpolées en elle
Parce que l'OP veut juste une résolution plus nette, j'ai pensé que je partagerais ma façon de réduire le nombre de pixels de moitié dans chaque dimension. Je prends la moyenne de blocs 2x2. Cela peut être appliqué plusieurs fois pour réduire par des facteurs de 2.
from scipy.ndimage import convolve
array_downsampled = convolve(array,
np.array([[0.25,0.25],[0.25,0.25]]))[:array.shape[0]:2,:array.shape[1]:2]
Ce n'est peut-être pas ce que vous recherchez, mais j'ai pensé le mentionner pour être complet.
Vous pouvez essayer d'installer scikits.samplerate
( docs ), qui est un wrapper Python pour libsamplerate. Il fournit de beaux algorithmes de rééchantillonnage de haute qualité - MAIS pour autant que je sache, il ne fonctionne que dans 1D. Vous pourriez être en mesure de rééchantillonner votre signal 2D d'abord sur un axe puis sur un autre, mais je pense que cela pourrait neutraliser les avantages d'un rééchantillonnage de haute qualité pour commencer.
manière la plus simple: vous pouvez utiliser le array[0::2]
notation, qui ne prend en compte qu'un index sur deux. Par exemple.
array= np.array([[i+j for i in range(0,10)] for j in range(0,10)])
down_sampled=array[0::2,0::2]
print("array \n", array)
print("array2 \n",down_sampled)
a la sortie:
array
[[ 0 1 2 3 4 5 6 7 8 9]
[ 1 2 3 4 5 6 7 8 9 10]
[ 2 3 4 5 6 7 8 9 10 11]
[ 3 4 5 6 7 8 9 10 11 12]
[ 4 5 6 7 8 9 10 11 12 13]
[ 5 6 7 8 9 10 11 12 13 14]
[ 6 7 8 9 10 11 12 13 14 15]
[ 7 8 9 10 11 12 13 14 15 16]
[ 8 9 10 11 12 13 14 15 16 17]
[ 9 10 11 12 13 14 15 16 17 18]]
array2
[[ 0 2 4 6 8]
[ 2 4 6 8 10]
[ 4 6 8 10 12]
[ 6 8 10 12 14]
[ 8 10 12 14 16]]