Надежно найти N кругов с одинаковым диаметром: альтернатива грубому порогу преобразования Хафа

Я разрабатываю приложение для отслеживания мелких животных в чашках Петри (или других круглых контейнерах). Перед выполнением любого отслеживания первые несколько кадров используются для определения областей. Каждое блюдо будет соответствовать круглой независимой статической области (т.е. не будет обновляться во время отслеживания). Пользователь может запросить программу, чтобы попытаться найти блюда из исходного изображения и использовать их в качестве областей.

Вот примеры: enter image description here enter image description here

Для выполнения этой задачи я используюHough Circle Transform. But in practice, different users will have very different settings and images and I do not want to ask the user to manually define the parameters. I cannot just guess all the parameters either.

Тем не менее, у меня есть дополнительная информация, которую я хотел бы использовать:

Я знаю точное количество кругов, которые будут обнаружены.

All the circles have the almost same dimensions. The circles cannot overlap. I have a rough idea of the minimal and maximal size of the circles. The circles must be entirely in the picture.

Поэтому я могу сузить число параметров до одного:the threshold. Using these informations and considering that I have got N circles to find, my current solution is to test many values of threshold and keep the circles between which the standard deviation is the smallest (поскольку все круги должны иметь одинаковый размер):

//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;
        }
    }
}

С:

 //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;

}

Я достиг более высокой точности, выполнив второй проход, в котором я повторил этот алгоритм, сужая интервал [minRad: maxRad], используя результат первого прохода.

Например, minRad2 = 0,95 * средний радиус лучших кругов и maxRad2 = 1,05 * средний радиус лучших кругов.

Пока у меня были довольно хорошие результаты при использовании этого метода. Тем не менее, это медленно и довольно грязно. Мои вопросы:

Can you thing of any alternative algorithm to solve this problem in a cleaner/faster manner ? Or what would you suggest to improve this algorithm? Do you think I should investigate generalised Hough transform ?

Спасибо за ваши ответы и предложения.

Ответы на вопрос(3)

Ваш ответ на вопрос