2012-07-24 10 views
15

Opracowuję aplikację do liczenia okrągłych obiektów, takich jak kolonie bakteryjne ze zdjęć.Wykrywanie skupisk okrągłych obiektów za pomocą iteratywnego progowania adaptacyjnego i analizy kształtu

To, co ułatwia sprawę, to fakt, że obiekty są zasadniczo dobrze odróżnione od tła.

jednak kilka trudności dokonać analizy trudne:

  1. W tle zaprezentuje stopniowe, a także szybką zmianę intensywności.
  2. na krawędziach kontenera, obiekt będzie eliptyczny zamiast okrągłego.
  3. Krawędzie przedmioty są czasami raczej rozmytej.
  4. Obiekty zostaną zgrupowane.
  5. Obiekt może być bardzo mały (6px średnicy)
  6. Docelowo algorytmy będą używane (przez GUI) przez osoby, które nie mają głębokiego zrozumienia analizy obrazu, więc parametry muszą być intuicyjne i bardzo nieliczne.

Problem został rozwiązany wiele razy w literaturze naukowej i "rozwiązany", na przykład przy użyciu okrągłych transformacji Hough lub działów przełomowych, ale nigdy nie byłem zadowolony z wyników.

Jednym z prostych opisów jest uzyskanie pierwszego planu za pomocą progu adaptacyjnego i podzielenie (jak opisałem w this post) obiektów klastrowych za pomocą transformacji odległości.

Z powodzeniem wdrożyłem tę metodę, ale nie zawsze mogłem poradzić sobie z nagłą zmianą intensywności. Ponadto zostaliśmy poproszeni przez rówieśników o bardziej "nowatorskie" podejście.

Dlatego szukałem nowej metody ekstrakcji pierwszego planu.

W związku z tym zbadałem inne metody wykrywania progów/obiektów typu blob. Próbowałem MSER, ale okazało się, że nie były one bardzo wytrzymałe i dość powolne w moim przypadku.

I w końcu wyszedł z algorytmu, który, jak dotąd, daje mi doskonałe rezultaty:

  1. podzielić trzy kanały mojego obrazu i zmniejszenie hałasu (rozmycie/mediana blur). Dla każdego kanału:
  2. Stosuję ręczną implementację pierwszego kroku adaptacyjnego progowania, obliczając bezwzględną różnicę między oryginalnym kanałem a splotem (przez duże rozmycie jądra). Następnie, dla wszystkich istotnych wartości progowej:
  3. I stosuje próg od wyniku 2)
  4. znaleźć kontury
  5. validate lub unieważnić kontury na przyznanie ich kształtu (wielkość, obszar, wypukłość ...)
  6. tylko prawidłowe ciągłe obszary (, tj. ograniczone przez kontury) są następnie przerysowywane w akumulatorze (1 akumulator na kanał).
  7. Po zgromadzeniu ciągłe regiony ponad wartości progowej, kończę-up z mapą „dziesiątki” regionów.Regiony o największym natężeniu są tymi, które najczęściej spełniają kryteria filtra morfologicznego.
  8. trzy mapy (jeden na kanał) są następnie konwertowane do skali szarości i progowaniu (próg jest kontrolowana przez użytkownika)

Wystarczy pokazać rodzaj obrazu muszę pracować z: enter image description here To zdjęcie przedstawia część 3 przykładowych obrazów na górze i wynik mojego algorytmu (niebieski = pierwszy plan) odpowiednich części na dole.

Oto moja implementacja C++ od: 3-7

/* 
* cv::Mat dst[3] is the result of the absolute difference between original and convolved channel. 
* MCF(std::vector<cv::Point>, int, int) is a filter function that returns an positive int only if the input contour is valid. 
*/ 

/* Allocate 3 matrices (1 per channel)*/ 
cv::Mat accu[3]; 

/* We define the maximal threshold to be tried as half of the absolute maximal value in each channel*/ 
int maxBGR[3]; 
for(unsigned int i=0; i<3;i++){ 
    double min, max; 
    cv::minMaxLoc(dst[i],&min,&max); 
    maxBGR[i] = max/2; 
    /* In addition, we fill accumulators by zeros*/ 
    accu[i]=cv::Mat(compos[0].rows,compos[0].cols,CV_8U,cv::Scalar(0)); 
} 
/* This loops are intended to be multithreaded using 
#pragma omp parallel for collapse(2) schedule(dynamic) 
For each channel */ 
for(unsigned int i=0; i<3;i++){ 
    /* For each value of threshold (m_step can be > 1 in order to save time)*/ 
    for(int j=0;j<maxBGR[i] ;j += m_step){ 
      /* Temporary matrix*/ 
      cv::Mat tmp; 
      std::vector<std::vector<cv::Point> > contours; 
      /* Thresholds dst by j*/ 
      cv::threshold(dst[i],tmp, j, 255, cv::THRESH_BINARY); 
      /* Finds continous regions*/ 
      cv::findContours(tmp, contours, CV_RETR_LIST, CV_CHAIN_APPROX_TC89_L1); 
      if(contours.size() > 0){ 
       /* Tests each contours*/ 
       for(unsigned int k=0;k<contours.size();k++){ 
        int valid = MCF(contours[k],m_minRad,m_maxRad); 
        if(valid>0){ 
         /* I found that redrawing was very much faster if the given contour was copied in a smaller container. 
         * I do not really understand why though. For instance, 
         cv::drawContours(miniTmp,contours,k,cv::Scalar(1),-1,8,cv::noArray(), INT_MAX, cv::Point(-rect.x,-rect.y)); 
         is slower especially if contours is very long. 
         */ 
         std::vector<std::vector<cv::Point> > tpv(1); 
         std::copy(contours.begin()+k, contours.begin()+k+1, tpv.begin()); 
         /* We make a Roi here*/ 
         cv::Rect rect = cv::boundingRect(tpv[0]); 
         cv::Mat miniTmp(rect.height,rect.width,CV_8U,cv::Scalar(0)); 
         cv::drawContours(miniTmp,tpv,0,cv::Scalar(1),-1,8,cv::noArray(), INT_MAX, cv::Point(-rect.x,-rect.y)); 
         accu[i](rect) = miniTmp + accu[i](rect); 
        } 
       } 
      } 
     } 
    } 
/* Make the global scoreMap*/ 
cv::merge(accu,3,scoreMap); 
/* Conditional noise removal*/ 
if(m_minRad>2) 
    cv::medianBlur(scoreMap,scoreMap,3); 
cvtColor(scoreMap,scoreMap,CV_BGR2GRAY); 

Mam dwa pytania:

  1. Jaka jest nazwa takiego podejścia planie ekstrakcji i widzisz żadnego powodu, dla którego może być niewłaściwe używać go w tym przypadku?

  2. Ponieważ rekursywne wyszukiwanie i rysowanie konturów jest dość intensywne, chciałbym uczynić mój algorytm szybszym. Czy możesz wskazać mi jakiś sposób na osiągnięcie tego celu?

Dziękuję bardzo za pomóc,

+2

Próbowałaś [Metoda Otsu] (http://en.wikipedia.org/wiki/Otsu%27s_method) zamiast krokach 2 i 3 ? Jest to niezwykle szybki próg adaptacyjny, który można łatwo obliczyć z histogramu. Zwykle działa całkiem dobrze dla tłumienia tła. Składnia to np. 'cvThreshold (img_src, img_dest, 128, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); '. – smocking

+0

@ SSocking Dziękuję bardzo, ale 1) Stwierdziłem, że nie działa tak dobrze jak próg adaptacyjny dla wszystkich moich próbek. I 2), produkty z etapu 2 i 3 są stosunkowo szybkie (w porównaniu do 3-7), aby uzyskać obraz w skali szarości potrzebny później ... –

+0

OK brzmi dobrze; A co z wykorzystaniem [połączonej analizy komponentów] (http://en.wikipedia.org/wiki/Connected_component_labeling), aby znaleźć ciągłe kształty? Niestety nie ma go w podstawowej bibliotece OpenCV, ale istnieje biblioteka o nazwie [cvBlobsLib] (http://opencv.willowgarage.com/wiki/cvBlobsLib/), która to zrobi. – smocking

Odpowiedz

2

Kilka lat temu napisałem aplikacja, która wykrywa komórki w obrazie mikroskopowym. Kod jest napisany w Matlab i myślę, że teraz jest bardziej skomplikowany niż powinien (był to mój pierwszy projekt CV), więc opiszę tylko sztuczki, które będą dla ciebie pomocne. Btw, była śmiertelnie powolna, ale naprawdę dobrze podziałała duże grupy bliźniaczych komórek.

I zdefiniowane metryki, według której ocenia prawdopodobieństwo, że dany punkt jest centrum komórce: - Jasność zmniejsza się w kole wokół niego - Wariancja tekstury jasności następuje podanego wzorca - komórka nie pokryje więcej niż% sąsiedniej komórki

Z nią zacząłem iteracyjnie odszukiwać najlepszą komórkę, oznaczać ją jako znalezioną, a następnie szukać następnej. Ponieważ takie wyszukiwanie jest drogie, wykorzystałem algorytmy genetyczne do szybszego wyszukiwania w mojej przestrzeni obiektów.

Niektóre wyniki są podane poniżej:

Cells 2 Cells

+0

Dziękuję, podoba mi się podejście zastosowane w projekcie !. Czy możesz zamieścić oryginały zdjęć, które umieściłeś? W moim przypadku nie sądzę, żebym mógł zajść tak głęboko, ponieważ nie chcę przyjmować dodatkowych założeń dotyczących wzoru jasności lub tekstury (na przykład obiekt jest ciemniejszy na krawędziach). Dążę do znalezienia wszechstronnego rozwiązania i, jak powiedziałem w swoim poście, również obawiam się szybkości przetwarzania. –

+0

Tak, myślę, że to było zbyt skomplikowane, ale wyniki były świetne. Myślę, że prostsze rozwiązanie da ci dobre wyniki - takie jak morfologia, w połączeniu z adaptacyjnym progowaniem. Zamieszczę zdjęcia, a może trochę więcej informacji później, kiedy wrócę do domu. – Sam

Powiązane problemy