Zajmuję się teraz przetwarzaniem obrazów w Pythonie za pośrednictwem PIL (Python Image Library). Moim głównym celem jest zliczenie liczby kolorowych komórek na obrazie immunohistochemicznym. Wiem, że istnieją odpowiednie programy, biblioteki, funkcje i samouczki na ten temat, i sprawdziłem prawie wszystkie z nich. Moim głównym celem jest pisanie kodu ręcznie od zera, w miarę możliwości. Dlatego staram się unikać używania wielu zewnętrznych bibliotek i funkcji. Napisałem większość programu. Oto, co dzieje się krok po kroku:
Program pobiera plik obrazu:
I przetwarza to dla czerwonych krwinek (w zasadzie wyłącza wartości RGB poniżej pewnego progu dla czerwonych):
I tworzy mapę boolowską (wkleisz jej część, ponieważ jest duża), która po prostu umieszcza 1 tam, gdzie napotka czerwony piksel na przetworzonym drugim zdjęciu powyżej.
22222222222222222222222222222222222222222
20000000111111110000000000000000000000002
20000000111111110000000000000000000000002
20000000111111110000000000000000000000002
20000000011111100000000000000000001100002
20000000001111100000000000000000011111002
20000000000110000000000000000000011111002
20000000000000000000000000000000111111002
20000000000000000000000000000000111111102
20000000000000000000000000000001111111102
20000000000000000000000000000001111111102
20000000000000000000000000000000111111002
20000000000000000000000000000000010000002
20000000000000000000000000000000000000002
22222222222222222222222222222222222222222
Celowo wygenerowałem tę ramkę na granicy z 2s, aby pomóc mi w liczeniu grup 1s na tej mapie boolowskiej.
Moje pytanie do was, dlaczego mogę skutecznie policzyć liczbę komórek (grup 1) na tego rodzaju mapie boolowskiej? Znalazłem http://en.wikipedia.org/wiki/Connected-component_labeling, które wyglądają na bardzo powiązane i podobne, ale o ile widzę, są na poziomie pikseli. Mój jest na poziomie boolowskim. Tylko 1 i 0.
Wielkie dzięki.
Odpowiedzi:
Coś w rodzaju podejścia opartego na brutalnej sile, ale zrobione przez odwrócenie problemu, aby indeksować kolekcje pikseli w celu znalezienia regionów, zamiast rasteryzować tablicę.
Wydruki:
źródło
Scipy
, co prawdopodobnie jest też szybsze ^^ „Ale prawdopodobnie dobre ćwiczenie i pokazuje, jak to zrobić w ogóle. Głosuję wtedy.Możesz użyć
ndimage.label
, co jest dobrym sposobem na zrobienie tego. Zwraca nową tablicę, w której każda funkcja ma unikalną wartość i liczbę funkcji. Możesz także określić element połączenia.źródło
Oto algorytm O (całkowita liczba pikseli + liczba pikseli komórek). Po prostu skanujemy obraz w poszukiwaniu pikseli komórki, a gdy go znajdziemy, wypełniamy komórkę, aby ją usunąć.
Wdrożenie w Common Lisp, ale będziesz mógł w prosty sposób przetłumaczyć go na Python.
źródło
Bardziej rozbudowany komentarz niż odpowiedź:
Jak wskazał @interjay, w obrazie binarnym, tj. W tym, w którym występują tylko 2 kolory, piksele przyjmują wartość 1 lub 0. Może to być prawda lub nie być prawdą w używanym formacie reprezentacji obrazu, ale jest to prawda w „konceptualnej” reprezentacji twojego wizerunku; nie pozwól, aby szczegóły dotyczące implementacji wprowadzały Cię w błąd. Jednym z tych szczegółów implementacji jest użycie 2s wokół obramowania obrazu - całkowicie rozsądny sposób na identyfikację martwej strefy wokół obrazu, ale nie wpływający jakościowo na binarność obrazu.
Jeśli chodzi o badanie pikseli N, NE, NW i W: ma to związek z łącznością pikseli w tworzeniu komponentu. Każdy piksel (poza specjalnymi przypadkami na granicy) ma 8 sąsiadów (N, S, E, W, NE, NW, SE, SW), ale które z nich kwalifikują się do włączenia do tego samego komponentu? Czasami komponenty, które spotykają się tylko na rogach (NE, NW, SE, SW), nie są uważane za połączone, czasami są.
Musisz zdecydować, co jest odpowiednie dla twojej aplikacji. Sugeruję, abyś opracował ręcznie kilka operacji algorytmu sekwencyjnego, sprawdzając różnych sąsiadów dla każdego piksela, aby poczuć, co się dzieje.
źródło