Я разрабатываю приложение для отслеживания мелких животных в чашках Петри (или других круговых контейнерах). Прежде чем будет выполнено отслеживание, первые несколько кадров используются для определения областей. Каждое блюдо будет соответствовать круговой независимой статической области (т.е. Не будет обновляться во время отслеживания). Пользователь может запросить программу, чтобы попытаться найти блюда из исходного изображения и использовать их в качестве областей.
Вот примеры:
Чтобы выполнить эту задачу, я использую Преобразование Hough Circle. Но на практике у разных пользователей будут очень разные настройки и изображения, и я не хочу просить пользователя вручную определять параметры. Я не могу просто угадать все параметры.
Однако у меня есть дополнительная информация, которую я хотел бы использовать:
Я знаю точное количество обнаруженных кругов.
- Все круги имеют почти одинаковые размеры.
- Круги не могут перекрываться.
- У меня есть приблизительное представление о минимальном и максимальном размере кругов.
- Кружки должны быть полностью на картинке.
Поэтому я могу сузить число параметров, чтобы определить один: порог. Используя эту информацию и учитывая, что у меня есть N кругов, чтобы найти, мое текущее решение проверьте множество значений порога и сохраните круги, между которыми стандартное отклонение является наименьшим (так как все круги должны иметь одинаковый размер):
//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 * средний радиус лучших кругов.
У меня были довольно хорошие результаты, используя этот метод. Однако он медленный и довольно грязный. Мои вопросы:
- Вы можете использовать любой альтернативный алгоритм для решения этой проблемы более чистым/быстрым способом?
- Или что вы предложите улучшить этот алгоритм?
- Как вы думаете, я должен исследовать обобщенное преобразование Хафа?
Спасибо за ваши ответы и предложения.