6

=== SOLVED ===Proste rozpoznawania obiektów

Dzięki za sugestie i komentarze. Pracując nad algorytmem flood_fill podanym w książce Beginning Python Visualization (Rozdział 9 - Przetwarzanie obrazu) wdrożyłem to, co chciałem. Mogę zliczyć obiekty, uzyskać otaczające prostokąty dla każdego obiektu (w związku z tym wysokości i szerokości), a na końcu można skonstruować tablice lub macierze NumPy dla każdego z nich.

Chociaż nie jest to zoptymalizowane podejście, robi to, co chcę. Kod źródłowy (lab2.py) i plik png (lab2-particles.png), których używam, zostały umieszczone pod http://code.google.com/p/ccnworks/source/browse/#svn/trunk/AtSc450.

Potrzebujesz NumPy i PIL zainstalowany, a matplotlib, aby wyświetlić histogram. Rdzeń kodu znajduje się w funkcji objfind, w której występuje główna akcja wyszukiwania rekursywnego.

Kolejną zmiana:

scipy na ndimage.label() robi dokładnie to, co chcę, też.

Cheers dla David-Warde Farley i Zachary Pincus z listy dyskusyjnej numpy i scipy za wskazanie tego prawa w oczy :)

=========== ==

Witam

mam obraz zawiera cienie cząstek lodu mierzona spektrometrem cząstek. Chcę móc identyfikować każdy obiekt, aby później móc go dalej klasyfikować i wykorzystywać w moich obliczeniach.

W istocie, co chcę zrobić, to po prostu wdrożyć narzędzie selekcji rozmytej, w którym mogę po prostu wybrać każdą jednostkę.

Jak mogę łatwo rozwiązać ten problem? (Najlepiej przy użyciu Pythona)

Dzięki.

UWAGA: W moim pytaniu odnoszę się do każdego konkretnego połączonego piksela jako obiektu lub obiektu. Zamierzam je wyodrębnić i utworzyć reprezentacje tablic NumPy, jak pokazano poniżej. (Tutaj używam lewego górnego obiektu, jeśli istnieje piksel, użyj 1, jeśli nie używaj 0. Jest to kształt 3 na 3, który odpowiada 3 pikselom o 3 piksele, są to projekcje rzeczywistych cząsteczek lodu na domenie 2D przy założeniu, ich istnienia promieniem kulistej równoważnika (wysokość + szerokość)/2, a później część zgorzeliny --from pikseli do rzeczywistych wymiarów i obliczenia objętości nastąpi)

import numpy as np 

np.array([[1,1,1], [1,1,1], [0,0,1]]) 

array([[1, 1, 1], 
     [1, 1, 1], 
     [0, 0, 1]]) 

Tutaj przekrój z obraz, który zamierzam użyć.

screenshot http://img43.imageshack.us/img43/2327/particles.png

+5

Proste rozpoznawanie obiektów brzmi dla mnie jak sprzeczność. – Joren

+0

Co sugerowałbyś na przemian? –

+3

Proszę nie mówić "rozwiązany" w swoim pytaniu. Albo zaakceptuj najlepszą odpowiedź, albo odpowiedz na własne pytanie i zaakceptuj to. – Soviut

Odpowiedz

2

OpenCV posiada interfejs Pythona, który może okazać się przydatny.

+0

Znalezione: http://opencv.willowgarage.com/documentation/python/pattern_recognition.html Jednak nieco mylące dla mnie i przykład nie jest zbyt pomocne. –

5
  1. Skanowanie każdego kwadratu (np.od górnej lewej, od lewej do prawej, od góry do dołu)

  2. Kiedy trafisz niebieski kwadrat następnie:

    a. Zapisz ten kwadrat jako lokalizację nowego obiektu

    b. Znajdź wszystkie inne sąsiadujące niebieskie kwadraty (np patrząc na sąsiadów tego placu, a sąsiedzi tych sąsiadów, etc.) i oznaczyć je jako część tego samego obiektu

  3. kontynuować skanowanie

  4. Po znalezieniu innego niebieskiego kwadratu przetestuj, czy jest to część znanego obiektu, zanim przejdziesz do kroku 2; alternatywnie w punkcie 2b, wymazać dowolny kwadrat po jakim wiąże się to z obiektem

+0

Myślałem, żeby zaimplementować coś podobnego, o czym tutaj wspomniałeś. Dziękuję za układanie mnie wyraźnie :) –

+0

Z pewną pomocą napisałem prostą implementację flood_fill i mogę policzyć liczbę obiektów (cienie lodu) na danym obrazie. I tak, zawiera rekurencję, jak się spodziewałem. Teraz chcę być w stanie skonstruować proste numpy tablice reprezentujące każdy obiekt. (co dodatkowo zademonstrowałem na moim pytaniu) W końcu myślę o dołączeniu wszystkich tych tablic do tablicy, gdzie później mogę po prostu zapętlić się i uzyskać ich kształty. Kształty są ważne, ponieważ użyję ich dla wysokości i szerokości obiektów z cząstkami lodu. –

3

patrząc na obraz, który podałeś, wszystko co trzeba zrobić to zastosować prostą region growing algorithm.

Gdybym MATLAB, użyłbym bwlabel/bwboundaries funkcje. Wierzę, że istnieje odpowiednik funkcji gdzieś w Numpy lub użyj OpenCV z owijarki python jak sugeruje @kwatford

+0

Pakiet SciPy ma podobną funkcję do oznaczania (http://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.measurements.label.html#scipy.ndimage.measurements.label), który można nazwać wszystkimi pikseli prawidłowo, używając go. Ale to rozwiązuje tylko pierwszą część problemu. Powinienem móc odróżnić każdą jednostkę osobno. Niestety nie ma na to żadnej funkcji. Trzeba to napisać :) –

+0

Sposób, w jaki to rozumiem, polega na tym, że każdy niebieski obiekt na obrazku jest bytem, ​​prawda? Następnie, zaznaczając wszystkie piksele w regionach, zaznacz wszystkie piksele oznaczone jako jeden, a następnie oznaczone jako dwa i tak dalej, aby uzyskać każdy obiekt ... Następnym krokiem będzie wyodrębnienie niektórych funkcji dla każdego obiektu (granice, kształt, powierzchnia, rozmiar, ...), które byłyby wykorzystywane w nadzorowanym zadaniu klasyfikacji. – Amro

+0

Wyjaśniłem moje użycie podmiotów w moim pytaniu w dziale UWAGA. Na razie wszystko, co muszę zrobić, to uzyskać prostokącie graniczne lub kwadrat dla niektórych przypadków szerokość i wysokość dla każdego obiektu. –

3

Użyłem do tego rodzaju analizy w mikroskopie i ostatecznie umieścić wszystko, co potrzebne do w przetwarzaniu obrazu i pakiet analityczny napisany w C, prowadzony przez Tcl. (Udało się tylko z obrazami 512 x 512, co tłumaczy, dlaczego 512 tak często się upowszechniało, były obrazy z pikselami o różnych rozmiarach, ale większość prac została wykonana przy użyciu 8-bitowych pikseli, co tłumaczy, dlaczego 0xff i maksymalna znacząca liczba 254 na obrazie.)

Krótko mówiąc, "zz" na początku poleceń Tcl wysyła resztę linii do parsera pakietu, który wywołuje odpowiednią procedurę C z podanymi argumentami. Zaraz po 'zz' jest argumentem wskazującym wejście i wyjście polecenia. (Może istnieć wiele wejść, ale tylko jedno wyjście.) "R" oznacza obraz 512 x 512 x 8-bitowy. Trzecie słowo to nazwa polecenia, które ma zostać wywołane; "wykresy" oznaczają obraz w sposób opisany w poniższym tekście. Tak więc "wykresy zz rr" oznaczają "Wywołaj parser ZZ; wprowadź obraz r do polecenia wykresów i odtwórz obraz r. " Reszta wiersza polecenia Tcl określa, który z wstępnie przydzielonych obrazów ma zostać użyty. (Obraz "g" jest obrazem obszaru zainteresowania, czyli obrazem obszaru zainteresowania, prawie wszystkie operacje ZZ wykonywane są pod kontrolą ROI.) Tak więc, "r1 r1 g8" oznacza "Użyj r1 jako wejścia, użyj r1 jako wyjścia (to znaczy, zaznacz sam obraz wejściowy) i wykonaj operację, gdy odpowiadający jej piksel na obrazie g8 --- to znaczy r8, użyty jako ROI --- wynosi> 0.

Nie sądzę, że jest dostępna w Internecie w dowolnym miejscu, ale jeśli chcesz wybrać kod źródłowy lub skompilować cały program, z chęcią Ci go prześlę. Oto fragment instrukcji (ale wydaje mi się, że w tym podręczniku pojawiają się błędy w tej późnej wersji - to jest zawstydzające ...):

Przykład 6. Funkcje zliczania.

Problem

Liczenie jest wspólnym zadaniem. Elementy zliczone nazywane są "funkcjami" i zazwyczaj konieczne jest staranne przygotowanie obrazów, aby cechy odpowiadały w jeden do jednego sposób rzeczom, które są rzeczywistymi przedmiotami, które należy policzyć. Tutaj jednak ignorujemy przygotowanie obrazu i rozważamy mechanikę liczenia.Pierwszym zadaniem zliczania jest sprawdzenie, ile funkcji znajduje się na obrazach w katalogu ./cells?

Podejście

Najpierw określmy "cechę". Funkcja to największa grupa "set" (niezerowych) pikseli, z których wszystkie można osiągnąć podróżując od jednego zestawu pikseli do drugiego wzdłuż tras północ-południe-wschód-zachód (góra-dół-prawo-lewo), rozpoczynając z określonego ustawionego piksela. Polecenie zz, które wykrywa i zaznacza takie funkcje na obrazie, to "zz rr grafy R: src R: dest G: ROI", tak zwane, ponieważ terminem matematycznym dla takiej cechy jest "wykres". Jeśli wszystkie piksele na obrazie są ustawione, oznacza to tylko jeden wykres na obrazie, ale zawiera on 262144 piksele (512 * 512). Jeśli piksele są ustawione i wyzerowane (równe zeru) we wzorcu szachownicy, , wówczas będzie 131072 (512 * 512/2) wykresów, ale każdy będzie zawierał tylko jeden piksel. Pokrótce wyjaśniono, że "wykresy zz rr" rozpoczyna się w lewym górnym rogu obrazu i skanuje każdy kolejny wiersz od lewej do prawej, aż znajdzie ustalony piksel, a następnie znajdzie wszystkie przypisane do niego piksele przez północ, południe, wschód lub granice zachodnie ("4-połączone"). Następnie ustawia wszystkie piksele na tym wykresie na 1 (0x01). Po znalezieniu i zaznaczeniu wykresu 1, rozpoczyna on ponownie skanowanie w piksel po tym, w którym pierwszy raz odkrył wykres 1, tym razem ignorując wszelkie piksele, które już należą do wykresu. Pierwsze 254 wykresy, które znajdzie, będą zaznaczone jednoznacznie; wszystkie znalezione wykresy będą jednak oznaczone wartością 255 (0xff) i dlatego nie można ich odróżnić. Kluczem do dokładnego zliczenia dowolnej liczby wykresów jest przetwarzanie każdego obrazu etapami, czyli znajdowanie liczby wykresów na obrazie, a jeśli liczba jest większa niż 254, usuwanie 254 wykresów właśnie znalezionych, powtarzanie przetwarzaj do 254 lub mniej wykresów. Język Tcl zapewnia środki do sterowania tą operacją.

Zacznijmy budować potrzebne polecenia, odczytując plik obrazu ZZ na obraz R i wykrywając i zaznaczając wykresy. Przed pętlą przetwarzania deklarujemy i zerujemy zmienną, aby pomieścić całkowitą liczbę funkcji w serii obrazów. W pętli przetwarzania zaczynamy od odczytania pliku obrazu na obraz R oraz wykrycia i zaznaczenia wykresów.

zz ur to $inDir/$img r1 
zz rr graphs r1 r1 g8 

Następnie mamy zera niektóre zmienne śledzić hrabiów, a następnie użyć polecenia „ra max”, aby dowiedzieć się, czy wykryto więcej niż 254 wykresy.

set nGraphs [ zz ra max r1 a1 g1 ] 

Jeśli nGraphs ma równy 255, a następnie 254 dokładnie liczone wykresy należy dodać do całości, wykresy od 1 do 254 powinny być usuwane, a liczba powtarzany tak wiele razy, ile potrzeba, aby zmniejszyć liczba wykresach poniżej 255.

while {$nGraphs == 255} { 
    incr sumGraphs 254 
    zz rbr lt r1 155 r1 g1 0 255 
    set sumGraphs 0 
    zz rr graphs r1 r1 g8 
    set nGraphs [ zz ra max r1 a1 g8 ] 
} 

Kiedy „a” wyjść pętlowych, zmienna nGraphs musi posiadać szereg mniej niż 255, to jest dokładnie liczbę zliczonych wykresów; jest to dodawane do rosnącej liczby funkcji w serii obrazów.

incr sumGraphs $nGraphs 

Po pętli przetwarzania wydrukuj całkowitą liczbę funkcji znalezionych w serii.

puts “Total number of features in $inDir \ 
images $beginImg through $endImg is $sumGraphs.” 

Po zakończeniu pętli przetwarzania wydrukuj całkowitą liczbę funkcji znalezionych w serii.

+0

To jest bardzo długa odpowiedź. To zajmie trochę czasu, aby uchwycić twoje wyjaśnienia :) –

+0

Zauważ, że dodałem paragraf 2 jako miniaturowe wprowadzenie do składni wiersza poleceń Tcl pakietu. To może pomóc w "chwytaniu". BTW, istnieją inne przykłady w podręczniku, które pokazują, jak przygotować obrazy za pomocą operacji morfologicznych, a następnie, po znalezieniu i zliczeniu funkcji, zrobić rzeczy takie jak ich dystrybucje rozmiarów. Nigdy nie próbowałem poważnie zaadaptować go do Pythona, chociaż miałem na to czas od jakiegoś czasu. – behindthefall

+0

Również BTW: "wykresy" w zasadzie wykorzystuje algorytm z Graphics Gems, Vol.I, str. 721, Paul Heckbert. – behindthefall

2

Connected component analysis może być tym, czego szukasz.

+0

Wiedziałem, że musi być nowa dla tej techniki :) Dzięki za wskazówki. Zarówno pirgraph (http://code.google.com/p/python-graph/), jak i opencv z opakowaniami Pythona mają wsparcie dla tych algorytmów, jednak ich użycie nie jest dla mnie zbyt jasne. Czy korzystałeś z którejś z tych funkcji? –

Powiązane problemy