web-dev-qa-db-fra.com

Sous-échantillonner le tableau dans Python

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: enter image description here

28
wuffwuff

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.

13
K.-Michael Aye

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)
10
Mike T

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

4
Hammer

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]
2
Josh Albert

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.

1
lmjohns3

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]]
0
Kolibril