Ponowne próbkowanie tablicy numpy przedstawiającej obraz

Szukam sposobu na ponowne próbkowanie tablicy numpy przedstawiającej dane obrazu w nowym rozmiarze, najlepiej mając do wyboru metodę interpolacji (najbliższa, Dwuliniowa, itp.). Wiem, że jest

scipy.misc.imresize

Który robi to dokładnie przez owinięcie funkcji zmiany rozmiaru PIL. Jedynym problemem jest to, że ponieważ używa PIL, tablica numpy musi być zgodna z formatami obrazu, dając mi maksymalnie 4" kolorowe " kanały.

Chcę mieć możliwość zmiany rozmiaru dowolnych obrazów, z dowolną liczbą " kolor" kanały. Zastanawiałem się, czy jest prosty sposób, aby to zrobić w scipy/numpy, lub czy muszę toczyć własne.

Mam dwa pomysły, jak sam wymyślić jeden:

  • funkcja, która działa scipy.misc.imresize na każdym kanale osobno
  • create my own using scipy.ndimage.interpolation.affine_transform

Pierwsza prawdopodobnie byłaby wolna dla dużych danych, a druga nie wydaje się oferować żadnej innej metody interpolacji poza splinami.

Author: Salvador Dali, 2012-11-06

4 answers

Na podstawie Twojego opisu, chcesz scipy.ndimage.zoom.

Interpolacja Dwuliniowa byłaby order=1, najbliższa jest order=0, a cubic jest domyślną (order=3).

zoom jest specjalnie dla regularnie gridowanych danych, które chcesz ponownie dopasować do nowej rozdzielczości.

Jako szybki przykład:

import numpy as np
import scipy.ndimage

x = np.arange(9).reshape(3,3)

print 'Original array:'
print x

print 'Resampled by a factor of 2 with nearest interpolation:'
print scipy.ndimage.zoom(x, 2, order=0)


print 'Resampled by a factor of 2 with bilinear interpolation:'
print scipy.ndimage.zoom(x, 2, order=1)


print 'Resampled by a factor of 2 with cubic interpolation:'
print scipy.ndimage.zoom(x, 2, order=3)

I wynik:

Original array:
[[0 1 2]
 [3 4 5]
 [6 7 8]]
Resampled by a factor of 2 with nearest interpolation:
[[0 0 1 1 2 2]
 [0 0 1 1 2 2]
 [3 3 4 4 5 5]
 [3 3 4 4 5 5]
 [6 6 7 7 8 8]
 [6 6 7 7 8 8]]
Resampled by a factor of 2 with bilinear interpolation:
[[0 0 1 1 2 2]
 [1 2 2 2 3 3]
 [2 3 3 4 4 4]
 [4 4 4 5 5 6]
 [5 5 6 6 6 7]
 [6 6 7 7 8 8]]
Resampled by a factor of 2 with cubic interpolation:
[[0 0 1 1 2 2]
 [1 1 1 2 2 3]
 [2 2 3 3 4 4]
 [4 4 5 5 6 6]
 [5 6 6 7 7 7]
 [6 6 7 7 8 8]]

Edit: Jak zauważył Matt S., Istnieje kilka zastrzeżeń dotyczących powiększania obrazów wielozakresowych. Kopiuję część poniżej prawie dosłownie z jednej z moich wcześniejszych odpowiedzi :

Powiększanie działa również dla tablic 3D (i nD). Należy jednak pamiętać, że jeśli na przykład powiększysz o 2x, powiększysz wzdłuż wszystkich osi.

data = np.arange(27).reshape(3,3,3)
print 'Original:\n', data
print 'Zoomed by 2x gives an array of shape:', ndimage.zoom(data, 2).shape

Daje to:

Original:
[[[ 0  1  2]
  [ 3  4  5]
  [ 6  7  8]]

 [[ 9 10 11]
  [12 13 14]
  [15 16 17]]

 [[18 19 20]
  [21 22 23]
  [24 25 26]]]
Zoomed by 2x gives an array of shape: (6, 6, 6)

W przypadku obrazów wielozakresowych zwykle nie chcesz interpolować wzdłuż osi "z", tworząc nowe pasma.

Jeśli masz coś w rodzaju 3-pasmowego obrazu RGB, który chcesz powiększyć, możesz to zrobić poprzez określenie ciągu krotek jako współczynnika powiększenia:

print 'Zoomed by 2x along the last two axes:'
print ndimage.zoom(data, (1, 2, 2))

Daje to:

Zoomed by 2x along the last two axes:
[[[ 0  0  1  1  2  2]
  [ 1  1  1  2  2  3]
  [ 2  2  3  3  4  4]
  [ 4  4  5  5  6  6]
  [ 5  6  6  7  7  7]
  [ 6  6  7  7  8  8]]

 [[ 9  9 10 10 11 11]
  [10 10 10 11 11 12]
  [11 11 12 12 13 13]
  [13 13 14 14 15 15]
  [14 15 15 16 16 16]
  [15 15 16 16 17 17]]

 [[18 18 19 19 20 20]
  [19 19 19 20 20 21]
  [20 20 21 21 22 22]
  [22 22 23 23 24 24]
  [23 24 24 25 25 25]
  [24 24 25 25 26 26]]]
 91
Author: Joe Kington,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-19 15:36:36

Jeśli chcesz ponownie pobrać próbkę, powinieneś zajrzeć do książki kucharskiej Scipy ' ego dla rebinning. W szczególności funkcja congrid zdefiniowana na końcu będzie wspierać rebinning lub interpolację (odpowiednik funkcji w IDL o tej samej nazwie). Powinna to być najszybsza opcja, jeśli nie chcesz interpolacji.

Możesz również użyć bezpośrednio scipy.ndimage.map_coordinates, co spowoduje interpolację splajnu dla każdego rodzaju ponownego próbkowania (w tym niestrukturalnych siatek). Uważam, że map_coordinates być wolne dla dużych tablic (nx, ny > 200).

Do interpolacji na strukturyzowanych siatkach zwykle używam scipy.interpolate.RectBivariateSpline. Możesz wybrać kolejność splajnu (Liniowy, kwadratowy, sześcienny itp.), a nawet niezależnie dla każdej osi. Przykład:

    import scipy.interpolate as interp
    f = interp.RectBivariateSpline(x, y, im, kx=1, ky=1)
    new_im = f(new_x, new_y)

W tym przypadku wykonujesz dwuliniową interpolację (kx = ky = 1). "Najbliższy" rodzaj interpolacji nie jest obsługiwany, ponieważ wszystko to robi to interpolacja splajnu nad prostokątną siatką. To również nie jest najszybsza Metoda.

Jeśli jesteś po interpolacji bi-liniowej lub bi-sześciennej na ogół znacznie szybciej wykonuje się dwie interpolacje 1D:

    f = interp.interp1d(y, im, kind='linear')
    temp = f(new_y)
    f = interp.interp1d(x, temp.T, kind='linear')
    new_im = f(new_x).T

Możesz również użyć kind='nearest', ale w takim przypadku pozbądź się poprzecznych tablic.

 12
Author: tiago,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-06 04:10:36

Oglądałeś Scikit-image ? Jego transform.pyramid_* funkcje mogą być przydatne dla Ciebie.

 7
Author: Peter Wang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-06 12:43:42

Niedawno znalazłem problem z scipy.ndimage.interpolacja.zoom, który zgłosiłem jako zgłoszenie błędu: https://github.com/scipy/scipy/issues/3203

Jako alternatywę (a przynajmniej dla mnie) znalazłem ten skimage scikit-image.transformacja.zmiana rozmiaru działa poprawnie: http://scikit-image.org/docs/dev/api/skimage.transform.html#skimage.transform.resize

Działa jednak inaczej niż interpolacja scipy ' ego.zoom - zamiast określać mutliplier, możesz określić kształt wyjściowy, który chcesz. Działa to dla obrazów 2D i 3D.

Tylko dla obrazów 2D, można użyć transformacji.przeskaluj i określ mnożnik lub skalę, tak jak w przypadku interpolacji.zoom.

 4
Author: Zehan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-10 16:13:55