2011-02-05 14 views
6

Używam Pythona do pracy z dużymi tablicami (około 2000 x 2000), gdzie każdy punkt I, J w macierzy reprezentuje pojedynczy piksel.Python - wydajna reprezentacja pikseli i związanych z nimi wartości

Same matryce są rzadkie (tj. Znaczna część z nich będzie miała wartości zerowe), ale gdy są one aktualizowane, mają tendencję do operacji przyrostowych, do dużej liczby sąsiednich pikseli w prostokątnym "bloku", zamiast do losowe piksele tu lub tam (właściwość, której obecnie nie używam na moją korzyść ..). Obawia się trochę nowości w arytmetyce macierzy, ale przyjrzałem się wielu możliwym rozwiązaniom, w tym różnym smakom rzadkich macierzy scipy. Do tej pory najbardziej obiecujące były matryce koordynacyjne (COO). Tak na przykład, gdzie chcę, aby zwiększyć kształt jednego bloku, będę musiał zrobić coś wzdłuż linii:

>>> from scipy import sparse 
>>> from numpy import array 
>>> I = array([0,0,0,0]) 
>>> J = array([0,1,2,3]) 
>>> V = array([1,1,1,1]) 
>>> incr_matrix = sparse.coo_matrix((V,(I,J)),shape=(100,100)) 
>>> main_matrix += incr_matrix #where main_matrix was previously defined 

w przyszłości, chciałbym mieć bogatszą reprezentację wartość piksela w anycase (krotki do reprezentowania RGB itd.), coś, co nie jest obsługiwane przez tablicę numpy (po prostu potrzebuję użyć this).

Docelowo będę miał kilka tych matryc, które będę musiał wykonać w prosty sposób, i będę potrzebował kodu, aby był tak wydajny, jak to tylko możliwe - i dystrybuowalny, więc musiałbym być w stanie utrzymywać i wymieniać te obiekty w małej reprezentacji bez znacznych kar. Zastanawiam się, czy to jest właściwa droga, czy powinienem wyglądać, tocząc moje własne struktury za pomocą dicts itp?

+0

Wątpię, czy mógłbyś produkować coś lepszego niż możliwości scipy i numpy. Ale nie jestem dostatecznie wyszkolony, aby być bardziej pozytywnym. Nawiasem mówiąc, nie podoba mi się użycie słowa "wektor". Z jednej strony nie ma wbudowanej struktury danych o nazwie "wektor" w Pythonie. Z drugiej strony mało prawdopodobne jest, aby stół dwuwymiarowy nazywał się "wektorem" w sensie matematycznym. Tak więc twoja encja to nie obiekt Pythona o nazwie 'vector', ani struktura matematyczna o nazwie 'vector' – eyquem

+0

która jest prawdziwa - powinna rzeczywiście powiedzieć, że macierz zamiast wektora (?) :) – malangi

+6

2000x2000 nie jest wcale bardzo duży. Nie ma potrzeby używania rzadkich tablic. Powinieneś uzyskać znacznie lepszą wydajność dzięki zwykłym tablicom numpy. Nawiasem mówiąc, numpy _very_ znacznie wspiera "coś w rodzaju" wektorów RGB "dla każdego piksela ... To tylko tablica 2000x2000x3! To działa dobrze, a to jest bardzo efektywne! –

Odpowiedz

4

Ogólną zasadą jest, uzyskać kod działa, a dopiero potem w razie potrzeby optymalizacji ...

W tym przypadku należy użyć zwykłej tablicy numpy 2000x2000 lub 2000x2000x3 dla RGB. Będzie to znacznie łatwiejsze i szybsze w obsłudze, jest tylko małym wymaganiem pamięci i ma wiele innych zalet, na przykład można użyć standardowych narzędzi do przetwarzania obrazu, itp.

Następnie, w razie potrzeby, "do utrzymania i wymieniaj te obiekty ", możesz po prostu skompresować je za pomocą gzip, pytables, jpeg lub cokolwiek innego, ale nie ma potrzeby ograniczania wymagań dotyczących przechowywania danych opartych na manipulacji.

W ten sposób uzyskasz szybsze przetwarzanie i lepszą kompresję.

+0

Kod rzeczywiście działa ze standardową tablicą, ale 2000 x 2000 ma ponad 140 MB (skompresowane do 40KB) i to jest dużo do dużych, aby efektywnie wykorzystać go dla mnie, dlatego też zajrzałem do rzadkich macierzy. – malangi

+0

Jakie są elementy macierzy 2000 x 2000? Dla mnie matryca 2000x2000 uint8 to 4MB. (Dla jasności, być może potrzebna jest rzadka macierz, ale na ogół niektóre pytania na temat SO są pomijane, a niektóre muszą podejść do problemu w inny sposób, więc trzeba to po prostu rozwiązać. jasne, co tu się dzieje, ale coś nie pasuje.) – tom10

+0

Używam float64s - ale myślę, że biorąc pod uwagę tę bardzo pomocną nić, wydaje się, że używanie w ogóle rzadkich macierzy prawdopodobnie nie jest właściwym sposobem idź w ogóle. Dziękuję Ci! – malangi

0

Możesz rozważyć zaglądanie do quadtree jako implementacji. Struktura quadtree jest dość wydajna w przechowywaniu rzadkich danych i ma tę dodatkową zaletę, że jeśli pracujesz z strukturami złożonymi z wielu bloków podobnych danych, reprezentacja może być bardzo zwarta. Nie jestem pewien, czy będzie to miało szczególne zastosowanie do tego, co robisz, ponieważ nie wiem, co masz na myśli mówiąc "pracując w blokach", ale na pewno warto sprawdzić jako alternatywną, rzadką implementację macierzy.

2

Powiedziałbym, że tak, to jest droga. Zdecydowanie nad budowaniem czegoś ze słowników! Przy budowie "wektor", tablicę, a następnie za pomocą uporządkowanego tablicę, czyli zdefiniować własną dtype:

rgbtype = [('r','uint8'),('g','uint8'),('b','uint8')] 

gdy zwiększając swoje bloki, będzie to wyglądać mniej więcej tak:

main_matrix['r'][blk_slice] += incr_matrix['r'] 
main_matrix['g'][blk_slice] += incr_matrix['g'] 
main_matrix['b'][blk_slice] += incr_matrix['b'] 

Update:

Wygląda na to, że nie można wykonywać operacji macierzowych za pomocą coo_matrix, istnieją one po prostu jako wygodny sposób wypełniania rzadkiej macierzy. Konieczne jest przekonwertowanie ich na inny (rzadki) typ macierzy przed wykonaniem aktualizacji. documentation

+0

Lub po prostu użyj tablicy mxnx3. Zwłaszcza w przypadku danych obrazu, tablica 'mxnx numbands' jest ładniejszym sposobem radzenia sobie z przedmiotami niż struktura strukturalna, ponieważ pozwala łatwiej oddzielić pasma (' x [..., 1] 'zamiast' x ['r'] .reshape (m, n) '). Z pewnością nie ma nic złego w korzystaniu z tablicy strukturalnej, po prostu osobiście znajduję proste tablice 3D lepiej pasujące do danych obrazu. Tak czy siak, +1 ode mnie. –

+0

Nie jestem pewien, czy/jak to zrobić z rzadką matrycą. – Paul

+0

Przepraszam, zapomniałem, że rozmawialiśmy o rzadkich matrycach, kiedy napisałem komentarz ... Rozproszone matryce są z natury 2D, więc nie możesz. Strukturyzowane rzadkie tablice są zdecydowanie drogą do zrobienia w tym przypadku. Nadal uważam, że lepiej byłoby unikać używania rzadkiej macierzy, jeśli ma on zwiększyć liczbę bloków, ale to zupełnie inne pytanie ... –

Powiązane problemy