EDYCJA Utrzymałem bardziej skomplikowany problem, z którym stoję poniżej, ale moje problemy z np.take
można podsumować lepiej w następujący sposób. Załóżmy, że masz tablicę img
o kształcie (planes, rows)
i inną macierz lut
o kształcie (planes, 256)
i chcesz użyć ich do utworzenia nowej tablicy out
o kształcie (planes, rows)
, gdzie out[p,j] = lut[p, img[p, j]]
. Można to osiągnąć z ozdobnego indeksowania następująco:Używanie numpy.take do szybszego indeksowania fantazyjnego
In [4]: %timeit lut[np.arange(planes).reshape(-1, 1), img]
1000 loops, best of 3: 471 us per loop
Ale jeśli zamiast ozdobnego indeksowania, należy użyć podjęcia i pętla pyton ciągu planes
rzeczy można przyspieszyć ogromnie:
In [6]: %timeit for _ in (lut[j].take(img[j]) for j in xrange(planes)) : pass
10000 loops, best of 3: 59 us per loop
Can lut
i img
być w jakiś sposób uporządkowane, tak aby cała operacja odbyła się bez pętli python, ale przy użyciu numpy.take
(lub alternatywnej metody) zamiast tradycyjnego wymyślnego indeksowania, aby utrzymać przewagę prędkości?
oryginalne pytanie Mam zestaw tabel przeglądowych (LUT), że chcą wykorzystać na obrazie. Tablica zawierająca LUT ma kształt (planes, 256, n)
, a obraz ma kształt (planes, rows, cols)
. Oba są z dtype = 'uint8'
, pasujące do osi LUT 256
. Pomysł polega na uruchomieniu p
-tej płaszczyzny obrazu poprzez każdą z LUTów n
z p
-tej płaszczyzny LUT.
Jeśli mój lut
i img
są następujące:
planes, rows, cols, n = 3, 4000, 4000, 4
lut = np.random.randint(-2**31, 2**31 - 1,
size=(planes * 256 * n // 4,)).view('uint8')
lut = lut.reshape(planes, 256, n)
img = np.random.randint(-2**31, 2**31 - 1,
size=(planes * rows * cols // 4,)).view('uint8')
img = img.reshape(planes, rows, cols)
mogę osiągnąć to, co jestem po użyciu ozdobnego indeksowanie jak ten
out = lut[np.arange(planes).reshape(-1, 1, 1), img]
co daje mi tablicę kształt (planes, rows, cols, n)
, gdzie out[i, :, :, j]
przechowuje i
-th płaszczyzny img
przebieg przez j
-th LUT z i
-th płaszczyzny LUT ...
Wszystko jest dobre, z wyjątkiem tego:
In [2]: %timeit lut[np.arange(planes).reshape(-1, 1, 1), img]
1 loops, best of 3: 5.65 s per loop
który jest całkowicie nie do przyjęcia, zwłaszcza, że mam wszystkie z poniższych nie tak ładne szukających alternatywy korzystających np.take
niż działał znacznie szybciej:
Pojedyncza LUT na jednej płaszczyźnie działa o około x70 szybciej:
In [2]: %timeit np.take(lut[0, :, 0], img[0]) 10 loops, best of 3: 78.5 ms per loop
Pętla pyton uruchomiony przez wszystkich pożądanych kombinacji wykończenia niemal X6 szybciej:
In [2]: %timeit for _ in (np.take(lut[j, :, k], img[j]) for j in xrange(planes) for k in xrange(n)) : pass 1 loops, best of 3: 947 ms per loop
Nawet uruchomione wszystkie kombinacje samolotów w LUT i obrazu, a następnie odrzucając
planes**2 - planes
niechcianych te są szybsze niż fantazyjny indeksowania:In [2]: %timeit np.take(lut, img, axis=1)[np.arange(planes), np.arange(planes)] 1 loops, best of 3: 3.79 s per loop
i najszybciej połączenie udało mi się wymyślić ma Iterowanie pętli pyton nad samolotami i kończy X13 szybciej:
In [2]: %timeit for _ in (np.take(lut[j], img[j], axis=0) for j in xrange(planes)) : pass 1 loops, best of 3: 434 ms per loop
Pytanie brzmi, czy nie ma sposobu na zrobienie tego z np.take
bez pętli Pythona? Idealnie, bez względu na to, czy potrzebne jest przekształcenie, czy zmiana rozmiaru, powinno to nastąpić na LUT, a nie na obrazie, ale jestem otwarty na to, co ludzie mogą wymyślić ...
co jest 'bkpt' we fragmencie - nie trzeba wyjaśniać, chciałem tylko poinformować, w przypadku jego literówkę - Chyba to powinno być 'lut'? –
... czy cała ta linia nie powinna brzmieć "lut = lut.reshape (samoloty, 256, 4)", więc "4" w ostatnim dim? –
@TheodrosZelleke Dzięki za złapanie tych! Moje 'lut' jest tak naprawdę tabelą punktów przerwań **, więc w moim kodzie nazywa się to' bkpt', a ten, który przeoczyłem, * tłumacząc * go na pytanie. – Jaime