J'ai utilisé xarray dans le but d'appliquer des filtres tels que des moyennes mobiles, donc je vais garder un enregistrement.
Tout ce que nous avions à faire était d'appliquer une moyenne mobile (ou un filtre médian mobile) dans une seule direction du tableau multidimensionnel. Ici, les données d'image sont traitées comme un exemple. À l'origine, les données d'image devraient utiliser la bibliothèque pour les données d'image, mais veuillez noter qu'il n'y avait pas de données appropriées.
import numpy as np
import xarray as xr
%matplotlib inline
import matplotlib.pyplot as plt
from PIL import Image
image = np.array(Image.open('lena.jpg'))
plt.imshow(image)
<matplotlib.image.AxesImage at 0x7f6b807a8898>
Ici, réduisez la taille de manière appropriée et ajoutez du sel et du poivre.
small_image = image[::3, ::3]
noisy_image = small_image.copy()
noisy_image[np.random.randint(0, noisy_image.shape[0], 1000),
np.random.randint(0, noisy_image.shape[1], 1000),
np.random.randint(0, noisy_image.shape[2], 1000)] = 0
noisy_image[np.random.randint(0, noisy_image.shape[0], 1000),
np.random.randint(0, noisy_image.shape[1], 1000),
np.random.randint(0, noisy_image.shape[2], 1000)] = 256
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.title('original')
plt.imshow(small_image)
plt.subplot(1, 2, 2)
plt.title('noisy')
plt.imshow(noisy_image)
<matplotlib.image.AxesImage at 0x7f6b7eefb6d8>
Stocker dans xr.DataArray
. Soit les axes vertical, horizontal et de couleur respectivement «x», «y» et «c».
data = xr.DataArray(noisy_image, dims=['x', 'y', 'c'])
Pour prendre la moyenne mobile dans la direction «x», utilisez la méthode «roulante». Les mots-clés de méthode spécifient le nom de l'axe et la taille de la fenêtre correspondants.
rolling = data.rolling(x=3) #Prenons une fenêtre de 3 pixels dans la direction x.
rolling
DataArrayRolling [window->3,center->False,dim->x]
le roulement correspond à «moyenne», «médiane», «max», «min», «compte», etc.
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.title('mean')
plt.imshow(rolling.mean().astype('ubyte')) # `imshow`Converti en ubyte pour l'affichage au format.
plt.subplot(1, 2, 2)
plt.title('median')
plt.imshow(rolling.median().astype('ubyte'))
<matplotlib.image.AxesImage at 0x7f6b7edb7f60>
Si vous regardez de près, vous pouvez voir que les deux pixels supérieurs sont noirs. En effet, la moyenne mobile n'est pas possible pour les deux premiers pixels. Il contient np.nan.
rolling.mean()
<xarray.DataArray (x: 171, y: 171, c: 3)>
array([[[ nan, nan, nan],
[ nan, nan, nan],
...,
[ nan, nan, nan],
[ nan, nan, nan]],
[[ nan, nan, nan],
[ nan, nan, nan],
...,
[ nan, nan, nan],
[ nan, nan, nan]],
...,
[[ 91. , 27.333333, 63.333333],
[ 93.666667, 26.666667, 61. ],
...,
[ 125.666667, 25.333333, 70. ],
[ 143. , 48.333333, 69.333333]],
[[ 87.333333, 26.333333, 62.666667],
[ 91.333333, 25.333333, 58.666667],
...,
[ 149. , 39.333333, 79.666667],
[ 162.333333, 60.333333, 73.666667]]])
Dimensions without coordinates: x, y, c
Si vous ne l'aimez pas, spécifiez la largeur minimale de la fenêtre, telle que rolling (x = 3, min_periods = 1)
. Dans min_periods = 1
, les points finaux sont remplis avec la valeur de la moyenne mobile de 1 pixel (effectivement la valeur telle qu'elle est).
plt.imshow(data.rolling(x=3, min_periods=1).median().astype('ubyte'))
<matplotlib.image.AxesImage at 0x7f6b7ed676a0>
Si vous regardez de près, cette image se déplace vers le bas en moyenne. Si vous agrandissez la partie supérieure
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.imshow(data.rolling(x=4, min_periods=1).median().astype('ubyte')[70:100, 70:100])
plt.plot([0, 30], [15, 15], '--k')
plt.subplot(1, 2, 2)
plt.imshow(small_image[70:100, 70:100])
plt.plot([0, 30], [15, 15], '--k')
[<matplotlib.lines.Line2D at 0x7f6b7ec430f0>]
Si vous ne souhaitez pas un tel décalage, spécifiez center = True
.
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.imshow(data.rolling(x=4, min_periods=1, center=True).median().astype('ubyte')[70:100, 70:100])
plt.plot([0, 30], [15, 15], '--k')
plt.subplot(1, 2, 2)
plt.imshow(small_image[70:100, 70:100])
plt.plot([0, 30], [15, 15], '--k')
[<matplotlib.lines.Line2D at 0x7f6b7ebdc7b8>]