czwartek, 20 sierpnia 2009

Detekcja blobów

Dzisiaj o obszarach spójnych (ang. blob). Detekcja blobów jest istotną częścią wielu algorytmów wizyjnych (zwłaszcza ich początkowej fazy). Czym jest blob? Trudno na to pytanie jednoznacznie odpowiedzieć... Można powiedzieć, że jest to obszar obrazu odróżniający się pewną cechą od otoczenia. W większości przypadków będzie to jego jasność. Generalnie obraz cyfrowy jest zbiorem liczb, więc może to być nawet coś w stylu czasu od ostatniej zmiany wartości piksela. Spójrzmy na przykładowe bloby:

Są to proste przypadki. Pierwszy z lewej ma stały rozkład wartości, przypadek idealny, świetnie odróżnia się od otoczenia :). Dalej jest już gorzej, środkowy przypadek nie ma stałej wartości, jednak maksimum jest w środku, a wartości spadają równomiernie w każdym kierunku wraz z oddalaniem od środka. Ostatni nie ma ani stałej wartości, ani równomiernego jej spadku/wzrostu z oddalaniem od środka. Bloby to właśnie takie "plamy" na obrazie, mają, jak już wspomniałem, dość duże znaczenie (blobami mogą być np. gwiazdy na obrazie nieba, czy samochody na zdjęciu lotniczym). Często mają nieregularny kształt, co utrudnia znajdowanie ich granic.
Do detekcji blobów wydzielono specjalną część z OpenCV o nazwie cvBlobsLib. Właściwie do zapoznania się z jej podstawami wystarczy przeczytać przykładowy kod. Ten wpis wybiega niewiele poza niego :) Na początku poszukujemy blobów przy pomocy obiektu CBlobResult
CBlobResult bloby = CBlobResult(obraz, NULL, 0);

W konstruktorze podajemy kolejno przetwarzany obraz, maskę i wartość tła. Dalej możemy bloby przefiltrować, odrzucając je na podstawie ich cech, np.
bloby.Filter(bloby, B_EXCLUDE, CBlobGetArea(), B_LESS, min_pow);
bloby.Filter(bloby, B_EXCLUDE, CBlobGetArea(), B_GREATER, max_pow);

W powyższym kodzie odrzucamy bloby, których powierzchnia nie mieści się pomiędzy wartościami min_pow i max_pow. Ilość znalezionych blobów łatwo uzyskać
bloby.GetNumBlobs();

Bloba o pobieramy w następujący sposób
CBlob *aktualny_blob = bloby.GetBlob(0);

Z ciekawszych rzeczy, możemy uzyskać "przylądki" bloba :)
aktualny_blob->MinX(); // lewy
aktualny_blob->MinY(); // gorny
aktualny_blob->MaxX(); // prawy
aktualny_blob->MaxY(); // dolny

Możemy także zmienić wszystkie jego piksele na określoną wartość
aktualny_blob->FillBlob(obraz, kolor);

CvBlobLib nie jest obszerna, wszystkie możliwe parametry czy funkcje łatwo znaleźć przeglądając kody źródłowe lub autouzupełnianie kodu w IDE :) Napisałem niewielki program do zabawy parametrami. Powstał też film pokazujący jego działanie, ale po jego obejrzeniu stwierdziłem, że jest nudny (trwa 2 min.) i ostatecznie go nie umieszczę. Poniżej zrzut ekranu
oraz działanie dla obrazka z trzema przykładowymi blobami z początku wpisu

Najlepiej popróbować samemu. Założyłem repozytorium, gdzie będę wrzucał gotowe do użycia kody. Plik z tego wpisu nazywa się bloby.cpp. Miłej zabawy :)

3 komentarze:

Anonimowy pisze...

Gdzie trzeba dołączyć te wszystkie pliki cvBlobsLib i które, żeby wszystko działało?
mar

Mieczysław pisze...

kurcze próbuje skompilować demo z pakietu cvblobslib i nie moge poradzic sobie z problemem

1>cvblobslib.lib(BlobResult.obj) : error LNK2019: unresolved external symbol "private: void __thiscall CBlobResult::RaiseError(int)const " (?RaiseError@CBlobResult@@ABEXH@Z) referenced in function "public: double __thiscall CBlobResult::GetNumber(int,class COperadorBlob *)const " (?GetNumber@CBlobResult@@QBENHPAVCOperadorBlob@@@Z)
1>.\Debug/testBlobs.exe : fatal error LNK1120: 1 unresolved externals

Anonimowy pisze...

jest nie dobrze, nie moge dodać tej biblioteki cvBlobsLib...

jest opis jak to zrobić ale coś mi nie idzie, możesz dać mi szybki opis?

bardzo mi potrzeba wykrywania blobów a nie moge nic skompilować...
540485 jak możesz napisz mi na gadu.

mało osób zna się na opencv a twój blog jest mi bardzo pomocny.

z góry dzięki za chwilkę poświęconego czasu.