Zobacz ten link, aby uzyskać więcej informacji.
Problem:
Chcę przejść przez ciągły raster (taki, który nie ma tabeli atrybutów), komórka po komórce i uzyskać wartość komórki. Chcę wziąć te wartości i uruchomić na nich warunki warunkowe, emulując kroki algebry mapy wyszczególnione poniżej, bez korzystania z kalkulatora rastrowego.
Na prośbę o komentarze poniżej dodałem szczegółowe informacje przedstawiające tło problemu i uzasadniające potrzebę wdrożenia metody jako takiej w poniższej sekcji zatytułowanej „Wymagana analiza:”.
Przedstawiona poniżej analiza, choć jest odpowiednia dla mojego problemu, ponieważ stanowi tło, nie musi być realizowana w odpowiedzi. Zakres pytania dotyczy tylko iteracji przez ciągły raster, aby uzyskać / ustawić wartości komórek.
Potrzebna analiza:
Jeśli DOWOLNY z poniższych warunków jest spełniony, nadaj komórce wyjściowej wartość 1. Daj komórce wyjściowej wartość 0, tylko jeśli żaden z warunków nie zostanie spełniony.
Warunek 1: Jeśli wartość komórki jest większa niż górna i dolna komórka, podaj wartość 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Gdzie plik jądra wygląda następująco:
3 3
0 1 0
0 0 0
0 1 0
Warunek 2: Jeśli wartość komórki jest większa niż lewa i prawa komórka, podaj wartość 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Gdzie plik jądra wygląda następująco:
3 3
0 0 0
1 0 1
0 0 0
Warunek 3: Jeśli wartość komórki jest większa niż górne i dolne komórki, podaj wartość 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Gdzie plik jądra wygląda następująco:
3 3
1 0 0
0 0 0
0 0 1
Warunek 4: Jeśli wartość komórki jest większa niż dolnej i lewej górnej komórki, podaj wartość 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Gdzie plik jądra wygląda następująco:
3 3
0 0 1
0 0 0
1 0 0
Warunek 5: Jeśli którakolwiek z sąsiednich komórek ma wartość RÓWNOMOCNĄ w stosunku do komórki środkowej, nadaj wyjściowemu rastrowi wartość 1 ( używając odmiany ogniskowej z dwoma obliczeniami najbliższego sąsiedztwa )
Dlaczego nie skorzystać z algebry map?
Zauważono poniżej, że mój problem można rozwiązać za pomocą algebry mapy, ale jak widać powyżej, jest to w sumie sześć obliczeń rastrowych plus jedno, aby połączyć wszystkie rastry utworzone razem. Wydaje mi się, że o wiele bardziej wydajne jest przechodzenie między komórkami i wykonywanie wszystkich porównań jednocześnie w każdej komórce zamiast zapętlania każdego z nich osobno siedem razy i wykorzystywania całkiem sporej ilości pamięci do utworzenia siedmiu rastrów.
Jak należy zaatakować problem?
Powyższy link zaleca użycie interfejsu IPixelBlock, jednak z dokumentacji ESRI nie jest jasne, czy faktycznie uzyskuje się dostęp do samej wartości pojedynczej komórki za pośrednictwem IPixelBlock, czy też uzyskuje się dostęp do wielu wartości komórek z ustawionego rozmiaru IPixelBlock. Dobra odpowiedź powinna sugerować metodę dostępu do wartości komórek ciągłego rastra i wyjaśnić metodologię kodu, jeśli nie jest to oczywiste.
W podsumowaniu:
Jaka jest najlepsza metoda na przejście przez każdą komórkę w CIĄGŁYM rastrze (który nie ma tabeli atrybutów ), aby uzyskać dostęp do jej wartości komórek?
Dobra odpowiedź nie musi implementować opisanych powyżej etapów analizy, wystarczy jedynie zapewnić metodologię dostępu do wartości komórek rastra.
Odpowiedzi:
Widzę, że problem został już rozwiązany przez Original Poster (OP), ale opublikuję proste rozwiązanie w pythonie na wypadek, gdyby ktoś w przyszłości był zainteresowany różnymi sposobami rozwiązania tego problemu. Jestem częściowo zwolennikiem oprogramowania typu open source, więc oto rozwiązanie wykorzystujące GDAL w pythonie:
Zaimplementuj funkcję w następujący sposób:
Następnie iteruj dane za pomocą zagnieżdżonej pętli:
A może chcesz spłaszczyć tablicę 2-D ze zrozumieniem listy:
W każdym razie, podczas iteracji danych po komórce, możliwe jest wrzucenie do pętli niektórych warunków warunkowych w celu zmiany / edycji wartości. Zobacz ten skrypt który napisałem dla różnych sposobów, aby uzyskać dostęp do danych: https://github.com/azgs/hazards-viewer/blob/master/python/zonal_stats.py .
źródło
Aktualizacja! Rozwiązanie numpy:
Tak więc odzyskanie gotowej tablicy z powrotem do rastra przy użyciu arcpy jest kłopotliwe. arcpy.NumPyArrayToRaster jest wiewiórczy i ma tendencję do redefiniowania zakresu, nawet jeśli podajesz mu swoje współrzędne LL.
Wolę zapisać jako tekst.
Używam Pythona jako 64-bitowej prędkości - od tej chwili oznacza to, że nie mogę nakarmić numpy.savetxt nagłówka. Więc muszę otworzyć wyjście i dodać nagłówek ASCII, który Arc chce przed konwersją ASCII na Raster
Wersja numpy uruchamia mój raster shift, mnożenie i dodawanie znacznie szybciej (1000 iteracji w 2 minuty) niż wersja arcpy (1000 iteracji w 15 minut)
STARE WERSJE Mogę to później usunąć właśnie napisałem podobny skrypt. Próbowałem przekonwertować na punkty i użyć kursora wyszukiwania. Mam tylko 5000 iteracji w ciągu 12 godzin. Szukałem więc innej drogi.
Moim sposobem na to jest iteracja przez współrzędne centrum komórki każdej komórki. Zaczynam w lewym górnym rogu i przechodzę od prawej do lewej. Na końcu rzędu przechodzę w dół o rząd i zaczynam od lewej. Mam raster 240 mz 2603 kolumnami i 2438 rzędami, więc łącznie 6111844 komórek. Używam zmiennej iteratora i pętli while. Patrz poniżej
Kilka uwag: 1 - musisz znać współrzędne zasięgu
2 - uruchom ze współrzędnymi punktowymi dla centrum komórki - przesuń o 1/2 rozmiaru komórki od wartości zasięgu
3 - Mój skrypt używa wartości komórki do pobrania rastra zależnego od wartości, a następnie przesunięcie tego rastra na środek oryginalnej komórki. Dodaje się to do zera rastrowego, aby zwiększyć zakres przed dodaniem do końcowego rastra. To tylko przykład. Tutaj możesz umieścić swoje instrukcje warunkowe (drugie polecenie if w pętli while).
4 - Ten skrypt zakłada, że wszystkie wartości rastrowe mogą być rzutowane jako liczby całkowite. Oznacza to, że najpierw musisz pozbyć się żadnych danych. Con IsNull.
6 - Nadal nie jestem z tego zadowolony i pracuję nad tym, aby całkowicie usunąć to z arkady. Wolałbym rzucić się jak dziwaczne tablice i zrobić tam matematykę, a potem sprowadzić ją z powrotem do Arc.
źródło
Spróbuj użyć IGridTable, ICursor, IRow. Ten fragment kodu służy do aktualizowania wartości komórek rastrowych, jednak pokazuje podstawy iteracji:
Jak mogę dodać nowe pole do tabeli atrybutów rastrowych i przejść przez nią?
Po przejściu przez tabelę można uzyskać określoną wartość wiersza pola za pomocą
row.get_Value(yourfieldIndex)
. Jeśli ty Googlepowinieneś być w stanie uzyskać wiele przykładów tego pokazujących.
Mam nadzieję, że to pomaga.
źródło
Co powiesz na to jako radykalny pomysł, wymagałoby to programowania w Pythonie lub ArcObjects.
źródło
Rozwiązanie:
Rozwiązałem to dzisiaj dzisiaj. Kod jest adaptacją tej metody . Koncepcja tego nie była strasznie trudna, kiedy zorientowałem się, co faktycznie robią obiekty używane do interakcji z rastrem. Poniższa metoda pobiera dwa zestawy danych wejściowych (inRasterDS i outRasterDS). Oba są tym samym zestawem danych, właśnie utworzyłem kopię inRasterDS i przekazałem ją do metody jako outRasterDS. W ten sposób oba mają ten sam zasięg, odniesienie przestrzenne itp. Metoda odczytuje wartości z inRasterDS, komórka po komórce i dokonuje na nich porównań najbliższego sąsiada. Wykorzystuje wyniki tych porównań jako zapisane wartości w outRasterDS.
Proces:
Użyłem IRasterCursor -> IPixelBlock -> SafeArray, aby uzyskać wartości pikseli, a IRasterEdit, aby zapisać nowe wartości w rastrze. Podczas tworzenia IPixelBlock mówisz maszynie o wielkości i lokalizacji obszaru, w którym chcesz czytać / zapisywać. Jeśli chcesz edytować tylko dolną połowę rastra, ustaw to jako parametry IPixelBlock. Jeśli chcesz zapętlić cały raster, musisz ustawić IPixelBlock równy rozmiarowi całego rastra. Robię to w poniższej metodzie, przekazując rozmiar do IRasterCursor (pSize), a następnie pobierając PixelBlock z kursora rastrowego.
Drugi klucz polega na tym, że musisz użyć SafeArray do połączenia z wartościami w tej metodzie. Otrzymasz IPixelBlock od IRasterCursor, a następnie SafeArray od IPixelBlock. Następnie czytasz i piszesz w SafeArray. Po zakończeniu odczytu / zapisu w SafeArray, napisz całą SafeArray z powrotem do IPixelBlock, a następnie napisz swój IPixelBlock do IRasterCursor, a następnie użyj IRasterCursor, aby ustawić lokalizację, w której chcesz rozpocząć zapis, a IRasterEdit, aby sam napisał. Ten ostatni krok to miejsce, w którym faktycznie edytujesz wartości zestawu danych.
źródło
Dane rastrowe AFAIK można odczytać na trzy sposoby:
Bez wymyślania koła proponuję przeczytać te oświecające slajdy Chrisa Garrarda.
Zatem najbardziej wydajną metodą jest odczyt danych po bloku, jednak spowodowałoby to utratę danych w korespondencji pikseli znajdujących się ponad granicami bloku podczas stosowania filtra. Bezpieczny alternatywny sposób powinien polegać na jednoczesnym odczytaniu całego obrazu i zastosowaniu metody numpy.
Zamiast tego po stronie obliczeniowej powinienem użyć gdalfilter.py i domyślnie metody VRT KernelFilteredSource, aby zastosować potrzebne filtry, a przede wszystkim uniknąć ciężkich obliczeń.
źródło