Encuentre de forma robusta N círculos con el mismo diámetro: alternativa a la fuerza bruta forzando el umbral de transformación

Estoy desarrollando una aplicación para rastrear animales pequeños en placas de Petri (u otros recipientes circulares). Antes de que se realice cualquier seguimiento, los primeros marcos se utilizan para definir áreas. Cada plato coincidirá con un área estática independiente circular (es decir, no se actualizará durante el seguimiento). El usuario puede solicitar que el programa intente buscar platos de la imagen original y usarlos como áreas.

Aquí hay algunos ejemplos:

Para realizar esta tarea, estoy usandoHough Circle Transform. Pero en la práctica, diferentes usuarios tendrán configuraciones e imágenes muy diferentes y no quiero pedirle al usuario que defina manualmente los parámetros. No puedo simplemente adivinar todos los parámetros tampoco.

Sin embargo, tengo información adicional que me gustaría usar:

Sé el número exacto de círculos a detectar.

Todos los círculos tienen las mismas dimensiones.Los círculos no pueden superponerse.Tengo una idea aproximada del tamaño mínimo y máximo de los círculos.Los círculos deben estar completamente en la imagen.

Por lo tanto, puedo reducir el número de parámetros para definir a uno:el umbral. Usando estas informaciones y considerando que tengo N círculos para encontrar,Mi solución actual es probar muchos valores de umbral y mantener los círculos entre los cuales la desviación estándar es la más pequeña. (ya que todos los círculos deben tener un tamaño similar):

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

Con:

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

}

He alcanzado una mayor precisión al realizar una segunda pasada en la que repetí este algoritmo estrechando el intervalo [minRad: maxRad] utilizando el resultado de la primera pasada.

Por ejemplo, minRad2 = 0.95 * radio promedio de los mejores círculos y maxRad2 = 1.05 * radio promedio de los mejores círculos.

He tenido resultados bastante buenos usando este método hasta ahora. Sin embargo, es lento y bastante sucio. Mis preguntas son:

¿Se puede pensar en algún algoritmo alternativo para resolver este problema de una manera más limpia / rápida?¿O qué sugerirías para mejorar este algoritmo?¿Crees que debería investigar la transformada de Hough generalizada?

Gracias por sus respuestas y sugerencias.

Respuestas a la pregunta(3)

Su respuesta a la pregunta