Solidnie znajdź kręgi N o tej samej średnicy: alternatywne dla brutalnego progu transformacji Hougha

Opracowuję aplikację do śledzenia małych zwierząt w szalkach Petriego (lub innych okrągłych pojemnikach). Przed rozpoczęciem śledzenia pierwsze kilka klatek służy do definiowania obszarów. Każde naczynie będzie pasowało do niezależnego kołowego obszaru statycznego (tj. Nie będzie aktualizowane podczas śledzenia). Użytkownik może zażądać, aby program spróbował znaleźć naczynia z oryginalnego obrazu i użyć ich jako obszarów.

Oto przykłady:

Aby wykonać to zadanie, używamHough Circle Transform. Ale w praktyce różni użytkownicy mają bardzo różne ustawienia i obrazy i nie chcę prosić użytkownika o ręczne zdefiniowanie parametrów. Nie mogę też zgadnąć wszystkich parametrów.

Mam jednak dodatkowe informacje, których chciałbym użyć:

Znam dokładną liczbę okręgów do wykrycia.

Wszystkie kręgi mają prawie takie same wymiary.Kręgi nie mogą się nakładać.Mam przybliżone wyobrażenie o minimalnym i maksymalnym rozmiarze kręgów.Kręgi muszą być całkowicie na obrazie.

Dlatego mogę zawęzić liczbę parametrów do zdefiniowania:próg. Korzystając z tych informacji i biorąc pod uwagę, że mam N kręgów do znalezienia,moim obecnym rozwiązaniem jest przetestowanie wielu wartości progowych i utrzymanie okręgów, pomiędzy którymi odchylenie standardowe jest najmniejsze (ponieważ wszystkie kręgi powinny mieć podobny rozmiar):

//at this point, minRad and maxRad were calculated from the size of the image and the number of circles to find.
//assuming circles should altogether fill more than 1/3 of the images but cannot be altogether larger than the image.
//N is the integer number of circles to find.
//img is the picture of the scene (filtered).

//the vectors containing the detected circles and the --so far-- best circles found.
std::vector<cv::Vec3f> circles, bestCircles;

//the score of the --so far-- best set of circles
double bestSsem = 0;

 for(int t=5; t<400 ; t=t+2){
//Apply Hough Circles with the threshold t
    cv::HoughCircles(img, circles, CV_HOUGH_GRADIENT, 3, minRad*2, t,3, minRad, maxRad );

    if(circles.size() >= N){
//call a routine to give a score to this set of circles according to the similarity of their radii
        double ssem = scoreSetOfCircles(circles,N);
//if no circles are recorded yet, or if the score of this set of circles is higher than the former best
        if( bestCircles.size() < N ||  ssem > bestSsem){
//this set become the temporary best set of circles
                bestCircles=circles;
                bestSsem=ssem;
        }
    }
}

Z:

 //the methods to assess how good is a set of circle (the more similar the circles are, the higher is ssem)
    double scoreSetOfCircles(std::vector<cv::Vec3f> circles, int N){
    double ssem=0, sum = 0;
        double mean;
        for(unsigned int j=0;j<N;j++){
            sum = sum + circles[j][2];
        }
        mean = sum/N;
        for(unsigned int j=0;j<N;j++){
            double em = mean - circles[j][2];
            ssem = 1/(ssem + em*em);
        }
    return ssem;

}

Osiągnąłem wyższą dokładność, wykonując drugi przebieg, w którym powtórzyłem ten algorytm, zawężając interwał [minRad: maxRad], używając wyniku pierwszego przejścia.

Na przykład minRad2 = 0,95 * średni promień najlepszych kręgów i maxRad2 = 1,05 * średni promień najlepszych kręgów.

Do tej pory miałem dość dobre wyniki przy użyciu tej metody. Jest jednak powolny i raczej brudny. Moje pytania to:

Czy możesz wymyślić jakiś alternatywny algorytm, aby rozwiązać ten problem w sposób czystszy / szybszy?Lub co sugerowałbyś ulepszyć ten algorytm?Czy uważasz, że powinienem zbadać uogólnioną transformację Hougha?

Dziękujemy za odpowiedzi i sugestie.

questionAnswers(3)

yourAnswerToTheQuestion