Pokazywanie postów oznaczonych etykietą analiza obrazu. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą analiza obrazu. Pokaż wszystkie posty

wtorek, 31 sierpnia 2010

Moduły GUI do anlalizatora obrazu Pandore - Łączenie segmentów

0 komentarze
Pełny kod źródłowy
Korzystając wyłącznie z algorytmu działów wodnych podczas segmentacji obrazu trudno uzyskać zadowalające efekty. Algorytm ten zależy nie tylko od ilości i położenia punktów startowych, ale również od obrazu wskazującego krawędzie. Jak można było przeczytać (i zobaczyć) w poprzednim wpisie, często dla obrazów o zróżnicowanym tle i niejednorodnych obiektach ilość segmentów jest znacznie wyższa od tej, którą byśmy sami wskazali. Warto zdawać sobie sprawę, że wskazane problemy w podobnym stopniu dotyczą wszystkich algorytmów segmentacji. Dlatego, aby poprawić jakość wyników celowe może się okazać wprowadzenie kolejnego etapu przetwarzania obrazu. Najczęściej stosuje się różnego rodzaju metody łączenia segmentów, tak aby ich wielkość lepiej odpowiadała wielkości rzeczywistych obiektów. Na szczęście analizator obrazu Pandore posiada zestaw popularnych operatorów służących do tego celu. Jednak są to operatory bez graficznego interfejsu użytkownika, przez co ich stosowanie może być kłopotliwe zarówno dla nowego użytkownika, który musi nauczyć się składni poszczególnych poleceń, jak również dla bardziej doświadczonego użytkownika, których od razu chce zobaczyć efekty ich działania po zmianie odpowiednich parametrów. Dlatego, podobnie jak w przypadku działów wodnych, przygotowałem graficzny interfejs, który ma ułatwiać korzystanie z operatorów łączenia segmentów dostępnych w Pandore. Jego pełny kod źródłowy na licencji BSD został umieszczony w publicznym repozytorium na GitHub.

Interfejs użytkownika

Okienko programu podobnie jak w przypadku modułu działów wodnych zostało podzielone na dwie części: panel opcji i ramkę wyświetlającą obrazy wejściowe lub wyniki działania wybranego algorytmu. Obrazy wejściowe mogą zostać otwarte za pomocą menu [File]. Mamy tutaj do wyboru następujące opcje:
  • [Open oryginal image] - otwarcie oryginalnego obrazka, który służy jedynie do prezentacji wyników,
  • [Open image for computation] - otwarcie obrazka, na podstawie którego będą wykonywane obliczenia spójności sąsiednich regionów; obraz ten warto wcześniej przygotować (można np. usunąć szum),
  • [Open prelabeled image] - poindeksowany obraz segmentów przygotowany za pomocą algorytmu działów wodnych lub innego algorytmu segmentacji.

Każdy z obrazów wejściowych jest wyświetlany automatycznie po otwarciu. Można je oczywiście w każdym momencie obejrzeć korzystając z ramki [Display] na panelu opcji. Poza wyświetleniem obrazów wejściowych w oryginalnej formie (3 pierwsze obrazki na rysunku poniżej), dodano jeszcze trzy opcje prezentujące w sposób graficzny wyniki łączenia segmentów (3 kolejne obrazki na rysunku poniżej):
  • [Color labeled image] - dla każdego segmentu zostaje przypisany losowy kolor; jeśli wybrane kolory nie są najlepiej dobrane można losować do skutku,
  • [Image with transparen labels] - kolorowe segmenty nanoszone są na obraz wejściowy; użytkownik ma możliwość zmiany ich przezroczystości,
  • [Image with border of labels] - na obrazie oryginalnym zaznaczane są kontury segmentów; istnieje możliwość określenia koloru.

Możliwości

W chwili obecnej program zawiera prawie wszystkie operatory łączenia segmentów dostępne w Pandore. Nie ma na razie operatora pmumfordshahmerging, który ma inną strukturę parametrów wywołania w porównaniu do pozostałych operatorów. Listę dostępnych w programie operatorów można zobaczyć na rysunku poniżej. Są to odpowiednio:pcontrastmerging, pentropymerging, pmeanmerging, puniformitymerging, pvariancemerging, pboundarymerging, phistomerging (wymieniam ponownie dodając odnośniki do oficjalnej dokumentacji).


Wybór określonego algorytmu powoduje jego automatyczne uruchomienie, a co zatem idzie wyświetlenie wyników jego działania. Dla każdego algorytmu dostępny jest opis jego działania (przycisk [?]) pochodzący z oficjalnej dokumentacji Pandore (pomoc jest on-line, dlatego do jej działania wymagane jest aktywne połączenie z Internetem). Dostępne są również podpowiedzi na suwakach opcji [Number of merging] i [Threshold].


Opisany interfejs działa w trybie pełnej interakcji. Zmiana algorytmu lub jego parametrów skutkuje natychmiastowym wyświetleniem wyników. Na szybkich komputerach sprawdza się to bardzo dobrze. Na starszych maszynach czas oczekiwania może być zauważalny.

Sposób działania opisanego programu można prześledzić na dołączonym filmie video.

środa, 11 sierpnia 2010

Moduły GUI do anlalizatora obrazu Pandore - Działy wodne

0 komentarze
Pełny kod źródłowy
Analizatora obrazu Pandore używam już od dłuższego czasu. Pomimo tego, że do większości zadań pisanie skryptów w konsoli jak najbardziej mi odpowiada, to czasami brakuje mi okienkowego interfejsu użytkownika, który mógłby przyspieszyć poszukiwanie optymalnych parametrów, dla poszczególnych operatorów. Częściowo w takich sytuacjach można posłużyć się interfejsem Ariane, o którym pisałem jakiś czas temu. Niestety każdorazowa edycja parametrów zapisanych w bloczkach i późniejsze wyświetlenie wyniku wymagają kilku kliknięć, a to wcale nie przyśpiesza pracy. Dlatego postanowiłem napisać własne (mini) programy, aby jeszcze bardziej usprawnić interakcję z użytkownikiem. Korzystając z biblioteki Qt, przygotowałem dwie aplikacje (możliwe, że pojawi się więcej), które bardziej szczegółowo opiszę w tym i następnym wpisie. Pełny kod źródłowy na licencji BSD został umieszczony w publicznym tepozytorium na GitHub.

Pierwsza aplikacja (używam też nazwy moduł GUI) została poświęcona algorytmowi Działów wodnych. Jej celem jest nie tylko uruchomienie tego algorytmu, ale również odpowiednie przygotowanie danych wejściowych. Dla niewtajemniczonych przypomnę, że algorytm ten umożliwia segmentację obrazu - rozbicie na obszary, które powinny odpowiadać rzeczywistym obiektom. Jego działanie zależy od właściwego przygotowanie obrazów wejściowych. Jednym z nich powinien być obraz wskazujący punkty (lub obszary) startowe, od których rozpoczyna się proces tzw. zalewania. Drugi obraz określa obszar i kierunek, w którym to zalewanie następuje (więcej na ten temat poniżej).

Interfejs użytkownika

Okienko programu zostało podzielone na dwie części - lewa zawiera panel opcji, natomiast prawa podgląd obrazów wejściowych lub wyniki segmentacji. Obraz po wczytaniu (menu [File][Open oryginal image]) można poddać operacji negatywu [Invert] lub rozmyciu [Blur]. Ta druga operacja jest szczególnie zalecana ponieważ usuwa nadmiar szumu z obrazu, a tym samym zmniejsza ilość wynikowych segmentów. Następna opcja na panelu [Show] pozwala obejrzeć obraz, na podstawie którego wyliczany jest obszar zalewania (opcja [Image for computations]). Obraz ten można przygotować na dwa sposoby (panel [Set image for computations]):
  • Obraz gradientowy [Gradient image] - wskazuje na granice obiektów,
  • Mapa odległości [Distance map] - określa odległość od wcześniej obliczonych obiektów z wykorzystaniem opcji [Binary image] na panelu [Set initial image].
Punkty startowe [Show][Initial image] dla algorytmu działów wodnych można wyznaczyć na kilka sposobów (panel [Set initial image]):
  • Lokalne minima [Local minimum point] - punkty, których wszystkie sąsiednie punkty mają wyższe wartości,
  • Obraz binarny [Binary image] - każdy obiekt jasny (biały) będzie podstawą do zbudowania osobnego segmentu,
  • Ręczne zaznaczenie obszarów startowych [Marker].

A teraz krótko, co jest pod maską aplikacji, czyli jakie operatory Pandore są używane:

Możlwości

Poniżej zostaną wskazane przykładowe sposoby wykorzystania aplikacji. Nie każda kombinacja omówionych powyżej opcji ma sens, dlatego posłużę się dwoma różnymi obrazami - obrazem naturalnym przedstawiającym chłopca w kapeluszu (przykład 1 i 2) i obrazem pokazującym kilka podobnych elementów (przykład 3, 4 i 5).

1. Automatyczna segmentacja obiektów.
  • obraz do obliczeń: [Gradient image]
  • punkty startowe: [Local minima point]

Komentarz: Pomimo rozmycia obrazu filtrem Gaussa o wartości sigma = 1,1 otrzymano znaczne rozdrobnienie segmentów. Dalsze zwiększanie tej wartości skutkowało powstawaniem błędnych obiektów, które zawierały fragmenty dwóch obiektów.

2. Manualna segmentacja obiektów.
  • obraz do obliczeń: [Gradient image]
  • punkty startowe: [Marker]

Komentarz: Zastosowanie obrazu gradientowego i manualnie wskazywanych znaczników (markerów) pozwala na poprawną segmentację obiektów.

3. Wyznaczenie strefy wpływu poszczególnych obiektów.
  • obraz do obliczeń: [Distance map]
  • punkty startowe: [Binary image]

Komentarz: Algorytm działów wodnych może służyć do wyznaczenia tzw. strefy wpływu poszczególnych obiektów. W tym celu należy wykonać binaryzację obrazu (tutaj wartość progowa wynosiła 100) i policzyć mapę odległości.

4. Automatyczna segmentacja obiektów.
  • obraz do obliczeń: [Gradient image]
  • punkty startowe: [Binary image]

Komentarz: Korzystając z wcześniej przygotowanego obrazu binarnego i obrazu gradientowego można wyznaczyć granice obiektów. Niestety został pominięty jeden element na obrazie. Powodem tego jest brak punktu startowego wskazującego tło. Można to oczywiści rozwiązać w podejściu automatycznym, jednak aplikacja nie ma na razie takiej opcji. Jak to zrobić za pomocą Pandore, opiszę niebawem.

5. Manualna segmentacja obiektów.
  • obraz do obliczeń: [Gradient image]
  • punkty startowe: [Marker]

Komentarz: Wskazany powyżej problem można oczywiście rozwiązać poprzez manualne zaznaczenie wszystkich obiektów i tła.

Aby prześledzić sposób obsługi programu zachęcam do obejrzenia krótkiego filmu. Zostały na nim jeszcze raz pokazane wszystkie opisane przed chwilą przypadki użycia, co powinno jeszcze lepiej przybliżyć czytelnikowi możliwości jego działania.

piątek, 23 lipca 2010

Zbiory ogólnodostępnych obrazów medycznych

0 komentarze
Trudno zajmować się przetwarzaniem obrazów medycznych, nie mając dostępu do takich danych. Najlepiej oczywiście mieć stalą współpracę z dużym szpitalem, który ma dobrze zorganizowany zakład radiologiczny lub też mieć znajomego lekarza, który z chęcią podzieli się takimi obrazami i dodatkowo wskaże problem badawczy. Jeśli jednak nie mamy tego szczęścia, to nic straconego, ponieważ zawsze można skorzystać z publicznie dostępnych zbiorów w Internecie. Do ich poszukiwania skłoniła mnie potrzeba lepszego przetestowania algorytmu nad którym ostatnio pracowałem, a do tej pory miałem do dyspozycji jedynie kilkanaście obrazów.

Poniższa lista nie zawiera opisu baz danych - tego jak i przez kogo zostały organizowane. Zawiera jedynie praktyczne wskazówki odnośnie możliwości dostępu do tych danych i ich wykorzystania we własnej pracy (ograniczenia licencyjne). Pozostałe informacje można znaleźć nie tylko na wskazanych stronach, ale również przy poszczególnych obrazach (jak i gdzie zostały zrobione).
  • Casimage - jedna z najstarszych baz danych, liczy ok. 10 000 obrazów. Sprawia wrażenie już nie rozwijanej (linki do strony organizatorów nie działają). Brak jednego archiwum danych. Dostęp jest możliwy przez interfejs WWW. Obrazy można pobierać indywidualnie. Na szczęście obrazy umieszczone są na serwerze począwszy od pliku 0 do 9735. Dzięki temu można szybko pobrać je korzystając z przygotowanego przeze mnie skryptu [linux, wget]:

    for i in $(seq 9735); do wget "http://pubimage.hcuge.ch/4DCGI/FULLIMAGE/$i"; echo $i; done
    Niestety nie wszystkie pliki chcą się od razu pobrać, dlatego polecam kilkukrotne uruchomienie nieznacznie zmodyfikowanej wersji poprzedniego skryptu:

    #!/bin/bash
    for i in $(seq 9735)
    do
      if [ ! -f $i ]
      then
        wget "http://pubimage.hcuge.ch/4DCGI/FULLIMAGE/$i";
        echo $i;
      fi
    done
  • RSNA - zbiór baz danych zorganizowanych przez Stowarzyszenie Radiologów Ameryki Północnej. Dostęp do wielu medycznych baz danych za pomocą interfejsu WWW.
  • MyPacs - prawdopodobnie największy (ok. 120 000) publicznie dostępny zbiór obrazów medycznych. Dostęp przez interfejs Flash, bez możliwości pobierania danych. Możliwość taka jest po przełączeniu się do uproszczonego trybu html.
  • MedGift - demo systemu wyszukiwania obrazów MedGift, który bazuje na innym systemie, a mianowicie: Gift. Dane pochodzą prawdopodobnie z bazy Casimage. Zaletą tego systemu jest możliwość szybkiego stworzenia zbioru podobnych obrazów, co w przypadku pozostałych baz trzeba zrobić samemu (lub można skorzystać z zaproponowanego podziału na kategorie).
  • MedPix - druga co do wielkości baza obrazów. Dostępny interfejs WWW utrudnia pobieranie obrazów (zablokowany prawy przycisk myszy). Można się jednak do nich dostać przez Google Images (link do wyszukiwania). Niestety obrazki mają dodane wizualne adnotacje, co jeszcze bardziej utrudnia swobodne ich przetwarzanie.
  • IRMA - zbiór ok. 15 000 obrazów podzielonych na ok. 200 kategorii. Dostęp do archiwum z plikami możliwy jest po podpisaniu warunków użycia (do zastosowań naukowych, nie komercyjnych, bez możliwości udostępniania pełnego zbioru dalej) i przefaksowaniu na podany adres.
  • ImageCLEF - ok 80 000 obrazów, dostępnych prawdopodobnie w postacie jednego lub kilku archiwów. Obrazy pochodzą m.in. z bazy IRMA, Casimage. Warunki użycia są podobne jak w przypadku bazy IRMA, tylko muszą one zostać podpisane przez osobę na stanowisku kierowniczym w jednostce naukowej.
  • Midas - baza danych pod patronatem firmy Kitware, która patronuje m.in. VTK i Insight Toolkit. Związana z elektronicznym czasopismem naukowym Insight Journal. Obrazy dostępne przez interfejs WWW najczęściej w formatach źródłowych: DICOM lub binarnym.
  • Springer Images - obrazy dołączone do publikacji Springer. Każdy obraz ma indywidualną licencję jednak w trakcie wyszukiwania można wybrać grupę licencji otwartych.
  • Images from the History of Medicine (NLM) - obrazy związane z historią medycyny zebrane przez National Library of Medicine USA.
Poza wyżej wymienionymi bazami danych warto jeszcze zajrzeć na spis plików opracowany na stronie biblioteki GDCM (link) oraz programu OsiriX (link).

Mam nadzieje, że przedstawione przeze mnie bazy obrazów medycznych pozwolą czytelnikowi na znalezienie ciekawego materiału badawczego i zaowocują powstaniem ciekawych prac naukowych. Powodzenia.

poniedziałek, 26 października 2009

Generowanie profili dla wskazanej linii w VTK

7 komentarze
Wartość jednego punktu niewiele nam daje podczas analizy dużego zbioru danych (patrz wpis: "Interaktywne wyświetlanie wartości wskazanego woksela w VTK"). Dopiero możliwość odniesienia tej wartości względem wybranego otoczenia ułatwia nam wydawanie bardziej obiektywnych ocen. W analizie obrazu w tym celu zwykle korzysta się z dwóch technik: generowania profili i przeglądu histogramów. Profil jest niczym innym aniżeli wykresem obrazującym wartości poszczególnych pikseli wzdłuż zadanej linii obrazu (linia może mieć dowolny kąt). Natomiast histogram pokazuje ile jest pikseli danej wartości we wskazanym obszarze.

W przykładach VTK jest już gotowy skrypt do wyświetlania histogramów, ja natomiast pokażę jak zaprogramować generowanie profili.

Przykład

Aby program był jak najbardziej przyjazny dla użytkownika zostanie wprowadzona możliwość ręcznego określenia linii, wzdłuż której ma być wyświetlony profil. Najlepiej do tego celu użyć kontrolki graficznej typu vtkLineWidget. Pozwala ona wskazać punkty startowe linii w wygodny sposób w przestrzeni trójwymiarowej. Dodatkowo niezbędne będzie skorzystanie z kontrolki do rysowania wykresów 2D - vtkXYPlotActor. Każda z tych kontrolek zostanie umieszczona na na innej scenie renderowania. Dzięki temu cała wizualizacja będzie znacznie czytelniejsza.

vtkRenderer ren1
ren1 SetBackground 0.5 0.6 0.8
ren1 SetGradientBackground 0

vtkRenderer ren2
ren2 SetBackground 1.0 1.0 1.0
ren2 SetBackground2 0.9 0.9 0.9
ren2 SetGradientBackground 1

renWin AddRenderer ren1
renWin AddRenderer ren2

ren2 SetViewport 0.5 0 1 1
ren1 SetViewport 0 0 0.5 1

vtkLineWidget lineWidget
lineWidget SetCurrentRenderer ren1
lineWidget SetInteractor iren
lineWidget SetInput [reader GetOutput]
lineWidget SetAlignToYAxis
lineWidget SetResolution 100
lineWidget PlaceWidget
lineWidget AddObserver InteractionEvent PrepareProfile
lineWidget On

vtkPolyData poly
lineWidget GetPolyData poly
vtkProbeFilter probe
probe SetInput poly
probe SetSource [reader GetOutput]

vtkXYPlotActor profile
profile AddInput [probe GetOutput]
eval [profile GetPositionCoordinate] SetValue 0.05 0.05 0
eval [profile GetPosition2Coordinate] SetValue 0.95 0.95 0
profile SetXValuesToNormalizedArcLength
profile SetNumberOfXLabels 6
profile SetTitle "Profile Data "
profile SetXTitle "s"
profile SetYTitle "I(s)"
profile SetXRange 0 1
profile SetYRange 0 255
eval [profile GetProperty] SetColor 0 0 0
eval [profile GetProperty] SetLineWidth 2
profile SetLabelFormat "%g"

set tprop [profile GetTitleTextProperty]
$tprop SetColor 0.02 0.06 0.62
$tprop SetFontFamilyToArial

profile SetAxisTitleTextProperty $tprop
profile SetAxisLabelTextProperty $tprop
profile SetTitleTextProperty $tprop

ren2 AddActor2D profile

proc PrepareProfile {} {
lineWidget GetPolyData poly
}
Uwaga:
Po uruchomieniu skryptu w lewej części okna zobaczymy wizualizację danych z możliwością określenia punktów startowych linii. Obok natomiast jest wyświetlany profil.



Warto również przetestować skrypt do generowania histogramu, który znajduje się w przykładach VTK (plik: VTK/Examples/ImageProcessing/Tcl/Histogram.tcl). Jego działanie można obejrzeć na poniższym zrzucie ekranu:



Opisywane narzędzia w swoim działaniu są bardzo proste. Jednak możliwości jakie oferują są niezastąpione.

czwartek, 18 czerwca 2009

Jak sobie poradzić ze szkieletyzacją w Pandore

0 komentarze
Przetwarzanie obrazów w celu wydobycia z nich interesujących nas danych nie musi być trudne. Wystarczy opanować pewien zestaw operacji podstawowych i wybrać wygodny analizator obrazu (ja polecam Pandore). Tym wpisem chciałbym zacząć serię mini poradników jak sobie poradzić z różnymi problemami związanymi z analizą obrazu i jak rozwiązać niektóre zadania. Wpisy te będą oznaczone tagiem rozwiązania. Nie planuje opisywać działania poszczególnych operacji, a jedynie uzasadniać dlaczego w danym algorytmie zostały użyte. Czytelnika natomiast zachęcam do samodzielnego zapoznania się z podstawami. Szczególnie pomocna może okazać się książka prof. Leszka Wojnara "Komputerowa Analiza Obrazu", do której sam czasami zaglądam. Dodatkowo do każdej użytej instrukcji będzie podany link do pomocy programu.

Na początek zostanie pokazane jak wykonać szkieletyzację obrazu binarnego. Niestety poza szkieletem często dostajemy dodatkowe artefakty, których najchętniej byśmy się pozbyli. Służy do tego operacja usuwania gałęzi, która w przypadku Pandore nie najlepiej sobie radzi. Zobaczymy w jaki sposób można ten problem rozwiązać.

Konwersja obrazu
Test będzie przeprowadzony dla sztucznego obrazu, który przedstawia bliżej nieokreśloną strukturę połączonych elementów z dodatkowymi wypustkami.
Najpierw konwertujemy obraz do formatu Pandore.
pbmp2pan input.bmp ex1_i1.pan



Szkieletyzacja
Następnie uruchamiamy szkieletyzację. Na poniższym obrazie widzimy jej efekty. Można zauważyć, że poza właściwym szkieletem dostaliśmy sporo dodatkowych gałęzi, które po części pokrywają się z wypustkami, a po części zlokalizowane są w przypadkowych miejscach - głównie tam gdzie struktura ma nieregularną krawędź.
pskeletonization ex1_i1.pan ex1_i2.pan



Cieniowanie
Stosujemy operację cieniowania, aby upewnić się, że szkielet będzie miał grubość jednego piksela.
ppostthinning ex1_i2.pan ex1_i3.pan



Usunięcie gałęzi
Ta operacja, jak sama nazwa wskazuje powinna usunąć wszystkie artefakty i pozostawić tylko linie łączące się ze sobą i z krawędzią. Jednakże jej działanie nie jest do końca takie jak byśmy sobie tego życzyli.
Spróbujemy rozwiązać problem w inny sposób.
pbarbremoval 2 1 ex1_i3.pan ex1_i4.pan



Negatyw
Wykonujemy negatyw. W tym momencie obraz nie przedstawia już linii, a obiekty, rozdzielone przez te linie (przypomnienie: w analizie obrazu na obrazie binarnym kolor biały oznacza obiekty do analizy, a kolor czarny tło).
pinverse ex1_i4.pan ex1_i5.pan



Indeksacja obiektów
Każdemu rozłącznemu obszarowi nadajemy inną wartość. Pozwoli nam to patrzeć na nie jak na zupełnie niezależne obiekty.
plabeling 4 ex1_i5.pan ex1_i6.pan



Dylatacja
Powiększamy każdy obszar pasem o wartości jednego piksela. Można zauważyć, że w ten sposób straciliśmy granice pomiędzy obiektami.
pdilatation 0 1 ex1_i6.pan ex1_i7.pan



Wyznaczenie krawędzi
Rozdzielamy obiekty wprowadzając między nimi linie graniczne.
pboundary 4 ex1_i7.pan ex1_i8.pan



Maska
Powstały w ten sposób obraz będzie maską dla wyznaczonego w kroku trzecim szkieletu.
pand ex1_i3.pan ex1_i8.pan ex1_i9.pan


Pomimo tego, że przedstawione rozwiązanie dotyczy problemów związanych z analizatorem Pandore, to warto się z nim zapoznać, aby zobaczyć alternatywne metody usuwania gałęzi.