Mam kod do obliczania brakujących wartości w obrazie, w oparciu o sąsiadujące wartości w okólniku 2D. Wykorzystuje również wartości z jednego lub więcej sąsiadujących ze sobą obrazów w tych samych lokalizacjach (to jest to samo okno 2D przesunięte w trzecim wymiarze).python - łączenie argsort z maskowaniem w celu uzyskania najbliższych wartości w ruchu okna
Dla każdej pozycji, której brakuje, muszę obliczyć wartość na podstawie niekoniecznie na wszystkich wartościach dostępnych w całym oknie, ale tylko na najbliżej położonych n komórkach, które mają wartości (na obu obrazach/Z- pozycje osi), gdzie n jest wartością mniejszą niż całkowita liczba komórek w oknie 2D.
Z minuty na minutę, wszystko jest znacznie szybsze do obliczenia w oknie, ponieważ mój sposób sortowania w celu uzyskania najbliższych n komórek z danymi jest najwolniejszą częścią funkcji, ponieważ musi być powtarzany za każdym razem, mimo że odległości w zakresie współrzędnych okna nie zmieniają się. Nie jestem pewien, czy jest to konieczne i czuję, że muszę być w stanie uzyskać posortowane odległości jeden raz, a następnie zamaskować je w procesie tylko wybierania dostępnych komórek.
Oto mój kod do wybierania danych do wykorzystania w oknie lokalizacji komórek Gap:
# radius will in reality be ~100
radius = 2
y,x = np.ogrid[-radius:radius+1, -radius:radius+1]
dist = np.sqrt(x**2 + y**2)
circle_template = dist > radius
# this will in reality be a very large 3 dimensional array
# representing daily images with some gaps, indicated by 0s
dataStack = np.zeros((2,5,5))
dataStack[1] = (np.random.random(25) * 100).reshape(dist.shape)
dataStack[0] = (np.random.random(25) * 100).reshape(dist.shape)
testdata = dataStack[1]
alternatedata = dataStack[0]
random_gap_locations = (np.random.random(25) * 30).reshape(dist.shape) > testdata
testdata[random_gap_locations] = 0
testdata[radius, radius] = 0
# in reality we will go through every gap (zero) location in the data
# for each image and for each gap use slicing to get a window of
# size (radius*2+1, radius*2+1) around it from each image, with the
# gap being at the centre i.e.
# testgaplocation = [radius, radius]
# and the variables testdata, alternatedata below will refer to these
# slices
locations_to_exclude = np.logical_or(circle_template, np.logical_or
(testdata==0, alternatedata==0))
# the places that are inside the circular mask and where both images
# have data
locations_to_include = ~locations_to_exclude
number_available = np.count_nonzero(locations_to_include)
# we only want to do the interpolation calculations from the nearest n
# locations that have data available, n will be ~100 in reality
number_required = 3
available_distances = dist[locations_to_include]
available_data = testdata[locations_to_include]
available_alternates = alternatedata[locations_to_include]
if number_available > number_required:
# In this case we need to find the closest number_required of elements, based
# on distances recorded in dist, from available_data and available_alternates
# Having to repeat this argsort for each gap cell calculation is slow and feels
# like it should be avoidable
sortedDistanceIndices = available_distances.argsort(kind = 'mergesort',axis=None)
requiredIndices = sortedDistanceIndices[0:number_required]
selected_data = np.take(available_data, requiredIndices)
selected_alternates = np.take(available_alternates , requiredIndices)
else:
# we just use available_data and available_alternates as they are...
# now do stuff with the selected data to calculate a value for the gap cell
To działa, ale ponad połowę całkowitego czasu funkcji jest zrobione w argsort z zamaskowanym dane przestrzennej odległości. (~ 900uS o łącznej wartości 1,4 ms - i ta funkcja będzie działała dziesiątki miliardów razy, więc to jest ważna różnica!)
Jestem pewna, że muszę być w stanie zrobić to po argsortie na zewnątrz funkcja, gdy okno odległości przestrzennej jest pierwotnie skonfigurowane, a następnie włącza te wskaźniki sortowania w maskowaniu, aby uzyskać pierwsze informacje o tym, jak obliczaćManyToCalculate bez konieczności ponownego sortowania. Odpowiedź może polegać na umieszczeniu różnych bitów, z których wydobywamy, na tablicę rekordów - ale nie wiem, jak to zrobić. Czy ktokolwiek może zobaczyć, jak sprawić, by ta część procesu była bardziej wydajna?
Kod jest naprawdę trudne do odczytania ... Możesz czytać [PEP8] (http://legacy.python.org/dev/peps/pep-0008/) i wykonaj go: ułatwia dzielenie kodu z innymi programistami Python. – Jaime
Zgadzam się z Jaime'em, że jest to raczej trudne do odczytania, zwłaszcza kod, ale opis pozostawia trochę miejsca na interpretację. Nie będę się więc starał o udzielenie odpowiedzi, ale oto kilka narzędzi, które sprawdziłbym, gdybym miał (jeśli przynajmniej w mgnieniu oka zrozumiemy twój problem). [sklearn.feature_extraction.image.extract_patches] (https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/feature_extraction/image.py#L238) daje widok na twoje łatki, które może maskować. Utworzy kopię, więc uważaj na problemy z pamięcią. – eickenberg
Być może zainteresuje Cię także pozornie zupełnie niezwiązana funkcja, która przypisuje brakujące wartości za pomocą dylatacji. Nie da to dokładnego wyniku, ale może być dobrym proxy: [nilearn.masking._extrapate_out_img] (https://github.com/nilearn/nilearn/blob/fd7e7a7186dca43d0ef5ebd19990b0751d476bda/nilearn/masking.py#L65) – eickenberg