Подтвердить что ты не робот

Лучший алгоритм построения круга

Мне нужен очень точный алгоритм для установки круга в набор точек данных (на самом деле мне нужно определить центр). Данные поступают после бинаризации и сегментации изображения. Я пробовал простой центр масс и взвешенный центр массовых алгоритмов, а также предварительно созданную функцию OpenCv:: fitEllipse. Я получил наилучшие результаты от функции OpenCV, но, тем не менее, точность недостаточна. Результаты значительно ухудшаются, когда центр закреплен в субпиксельных областях. Полученная точность недостаточна даже при работе с смоделированными данными, что является плохим, поскольку в конечном итоге процедура будет иметь дело с данными, полученными с помощью комерас. У вас есть какие-то предложения, какой алгоритм я должен искать или у вас есть готовое решение? Я бы предпочел воздержаться от ссылки на любые внешние библиотеки. Спасибо за вашу помощь. alt text

отредактирован: Цель калибровки может быть локализована в любой области поля зрения. Ниже приведены лучшие результаты, полученные с помощью процедуры OpenCV:

169,367 748,345  
167,557 820,788  
165,690 893,158  
164,047 965,197  
162,715 1036,729  
161,575 1108,089  
160,477 1179,552  
233,297 1015,313  
232,076 1086,965  
220,359 1229,578  
268,494 1160,275  
339,544 1162,980  
362,017 1235,669  
433,390 1238,491  
482,754 1168,299  
505,233 1241,039  
554,856 1170,664  
577,302 1243,439  
627,331 1172,795  
649,507 1245,665  
713,572 588,896  
711,995 661,853  
710,440 735,034  
708,722 808,856  
707,018 882,674  
705,377 956,169  
703,609 1029,211  
701,716 1101,950  
699,760 1174,689  
721,895 1247,620  
785,829 614,754  
784,344 687,750  
782,819 761,315  
781,292 835,225  
779,389 908,975  
777,619 982,335  
775,688 1055,275  
773,672 1128,091  
771,603 1200,724  

Edited: Численно сгенерированная модель и реальные координаты центров: alt text

51,1    79,8
51,1    179,8
51,1    279,8
51,1    379,8
51,1    479,8
51,1    579,8
51,1    679,8
51,1    779,8
51,1    879,8
51,1    979,8
51,1    1079,8
51,1    1179,8
51,1    1279,8
51,1    1379,8
51,1    1479,8
151,1   79,8
151,1   179,8
151,1   279,8
151,1   379,8
151,1   479,8
151,1   579,8
151,1   679,8
151,1   779,8
151,1   879,8
151,1   979,8
151,1   1079,8
151,1   1179,8
151,1   1279,8
151,1   1379,8
151,1   1479,8
251,1   79,8
251,1   179,8
251,1   279,8
251,1   379,8
251,1   479,8
251,1   579,8
251,1   679,8
251,1   779,8
251,1   879,8
251,1   979,8
251,1   1079,8
251,1   1179,8
251,1   1279,8
251,1   1379,8
251,1   1479,8
351,1   79,8
351,1   179,8
351,1   279,8
351,1   379,8
351,1   479,8
351,1   579,8
351,1   679,8
351,1   779,8
351,1   879,8
351,1   979,8
351,1   1079,8
351,1   1179,8
351,1   1279,8
351,1   1379,8
351,1   1479,8
451,1   79,8
451,1   179,8
451,1   279,8
451,1   379,8
451,1   479,8
451,1   579,8
451,1   679,8
451,1   779,8
451,1   879,8
451,1   979,8
451,1   1079,8
451,1   1179,8
451,1   1279,8
451,1   1379,8
451,1   1479,8
551,1   79,8
551,1   179,8
551,1   279,8
551,1   379,8
551,1   479,8
551,1   579,8
551,1   679,8
551,1   779,8
551,1   879,8
551,1   979,8
551,1   1079,8
551,1   1179,8
551,1   1279,8
551,1   1379,8
551,1   1479,8
651,1   79,8
651,1   179,8
651,1   279,8
651,1   379,8
651,1   479,8
651,1   579,8
651,1   679,8
651,1   779,8
651,1   879,8
651,1   979,8
651,1   1079,8
651,1   1179,8
651,1   1279,8
651,1   1379,8
651,1   1479,8
751,1   79,8
751,1   179,8
751,1   279,8
751,1   379,8
751,1   479,8
751,1   579,8
751,1   679,8
751,1   779,8
751,1   879,8
751,1   979,8
751,1   1079,8
751,1   1179,8
751,1   1279,8
751,1   1379,8
751,1   1479,8
851,1   79,8
851,1   179,8
851,1   279,8
851,1   379,8
851,1   479,8
851,1   579,8
851,1   679,8
851,1   779,8
851,1   879,8
851,1   979,8
851,1   1079,8
851,1   1179,8
851,1   1279,8
851,1   1379,8
851,1   1479,8
951,1   79,8
951,1   179,8
951,1   279,8
951,1   379,8
951,1   479,8
951,1   579,8
951,1   679,8
951,1   779,8
951,1   879,8
951,1   979,8
951,1   1079,8
951,1   1179,8
951,1   1279,8
951,1   1379,8
951,1   1479,8
1051,1  79,8
1051,1  179,8
1051,1  279,8
1051,1  379,8
1051,1  479,8
1051,1  579,8
1051,1  679,8
1051,1  779,8
1051,1  879,8
1051,1  979,8
1051,1  1079,8
1051,1  1179,8
1051,1  1279,8
1051,1  1379,8
1051,1  1479,8
1151,1  79,8
1151,1  179,8
1151,1  279,8
1151,1  379,8
1151,1  479,8
1151,1  579,8
1151,1  679,8
1151,1  779,8
1151,1  879,8
1151,1  979,8
1151,1  1079,8
1151,1  1179,8
1151,1  1279,8
1151,1  1379,8
1151,1  1479,8
4b9b3361

Ответ 1

Алгоритм с использованием преобразований изображений и кластеризации


Я составил небольшой алгоритм с использованием Image Transformations и некоторую статистику для обнаружения ваших кругов. Посмотрите, не зависит ли ваша ошибка от ожидания.
Любая хорошая библиотека изображений и статистики будет делать, я реализовал ее с помощью Mathematica.

Выполните следующие действия:

1. Импортируйте изображение и выполните преобразование нижней шляпы

Мы начинаем пытаться изолировать круги. Bottom Hat Transform с ядром Box Matrix помогает. Почти любая библиотека изображений поставляется с уже реализованным алгоритмом.

a = [email protected]"http://i.stack.imgur.com/hiSjj.png";   
b = BottomHatTransform[[email protected], BoxMatrix[30]]  

Результат

alt text

2. Запустите трансмиссию Hit Miss Transform, чтобы выделить круги

The Hit Miss Transform отличается тем, что находит четко определенные геометрические объекты. Он также легко программируется и почти всегда присутствует в библиотеках изображений.

c = [email protected][b, DiskMatrix[20]]

Результат:

alt text

И наши круги уже изолированы и сводятся к их центральному ядру.

3. Получите только белые пиксели из изображения

Это шаг, зависящий от реализации, поэтому я не буду комментировать этот.

ttflat = Flatten[Table[{i, j, ImageData[c][[i, j]]}, {i, 1232}, {j, 1624}], 1];  
ttfilter = Select[ttflat, #[[3]] == 1 &];  

Посмотрите, сколько пикселей осталось

[email protected]  
{3684, 3}   

Так осталось 3684 пикселя, почти 82 за круг. Достаточно сделать некоторые статистические данные.

3. Используйте Cluster Analysis для выбора каждого круга

Анализ кластеров может быть чрезмерным, но, поскольку я уже реализовал его, проще его использовать, чем программировать что-то новое:). Вы можете сделать свой собственный или использовать библиотеку статистики.

ttc = FindClusters[ttfilter, 45, Method -> {"Agglomerate", "Linkage" -> "Complete"}];

Когда наши кластеры уже найдены, найдем среднее значение для x и y в каждом кластере. Это центры кругов:

means = N[Mean /@ ttc, 5]  

В результате получается список из 45 координат, таких как:

{{161.67, 1180.1}, {162.75, 1108.9}, 
 {164.11, 1037.6}, {165.47, 966.19} .....  

Мы почти закончили.

Давайте проверим наш результат. Мы накладываем оба изображения, рисуем кресты и круги вокруг обнаруженных центров.

alt text

Нажмите, чтобы увеличить, чтобы вы могли получить представление об ошибках.

НТН!

Изменить

Я сравнил результаты из таблицы с моими результатами.

Умножая круги в прямые линии, я использовал "Наименьшие квадраты", чтобы проследить линию и вычислил остатки.

Составьте график ниже, вы увидите, что строка "M" y лучше, чем "Y". Но это предполагает выравнивание окружностей...

alt text

Изменить 2

Это рассчитанные координаты для первых 45 кругов во втором изображении. У меня систематическое смещение 1 пикселя. Возможно, из-за некоторых манипуляций с изображениями я сделал, но легко исправить:)... просто вычитал один пиксель на X и Y...

{{51.135, 79.692}, {51.135, 179.69}, {51.135, 279.69},{51.135, 379.69}, {51.135, 479.69},
 {51.135, 579.69}, {51.135, 679.69}, {51.135, 779.69},{51.135, 879.69}, {51.135, 979.69}, 
 {51.135, 1079.7}, {51.135, 1179.7}, {51.135, 1279.7},{51.135, 1379.7}, {51.135, 1479.7}, 
 {151.13, 79.692}, {151.13, 179.69}, {151.13, 279.69},{151.13, 379.69}, {151.13, 479.69},
 {151.13, 579.69}, {151.13, 679.69}, {151.13, 779.69},{151.13, 879.69}, {151.13, 979.69}, 
 {151.13, 1079.7}, {151.13, 1179.7}, {151.13, 1279.7},{151.13, 1379.7}, {151.13, 1479.7}, 
 {251.13, 79.692}, {251.13, 179.69}, {251.13, 279.69},{251.13, 379.69}, {251.13, 479.69}, 
 {251.13, 579.69}, {251.13, 679.69}, {251.13, 779.69},{251.13, 879.69}, {251.13, 979.69}, 
 {251.13, 1079.7}, {251.13, 1179.7}, {251.13, 1279.7},{251.13, 1379.7}, {251.13, 1479.7}}

И это изображение:

alt text

Ответ 2

"Лучшее" зависит от типа шума во входных данных. Проблема тривиальна, если в исходных точках данных нет шума: просто выберите 3 точки и вычислите круг.

Если вы ожидаете нормальные распределенные независимые переводы каждой точки данных, то алгоритм наименьших средних квадратов должен быть оптимальным. Точки данных должны соответствовать уравнению:

(x - xm)^2 + (y - ym)^2 = r^2

где xm, ym, r неизвестны, поэтому:

x^2 - 2*x*xm + xm^2 + y^2 - 2*y*ym + ym^2 = r^2

замените c на r^2-xm^2-ym^2 и у вас есть переопределенная система линейных уравнений:

2*x*xm + 2*y*ym = c - x^2 - y^2

Любая хорошая библиотека линейной алгебры (например, IPP) может решить это для вас.

Если вы ожидаете превышения в данных, я бы предложил использовать стратегию RANSAC для поиска множества точек, не относящихся к outlier, а затем использовать алгоритм выше, чтобы найти точный центр для этого набора.

Ответ 3

Чтобы найти центры окружностей с субпиксельной точностью, если радиус круга известен (и постоянный), я использую этот подход:

  • Возьмите изображение с одним кругом (в качестве маркера ниже). Его радиус должен быть таким же, как радиус окружностей, которые вы хотите найти.
  • Обнаружение ребер (величина градиента Собель, затем некоторый порог для удаления краев с низкой интенсивностью), как в тестовом изображении, так и в изображении с переворачиванием маркера. На этом этапе я не применяю кромки на краю и не определяю точные точки на краю.
  • Перекрестно коррелировать края тестового изображения с краями перевернутого маркера. Вы получаете несколько пиков, где расположены центры.
  • Найти центры пиков с точностью субпикселя. Центр масс или установка двумерного гауссова колокола могут работать хорошо.
  • Добавьте сдвиги, соответствующие известному положению центра круга в маркере.

В противном случае, если точки на круге известны с достаточной точностью, финал наименьших средних квадратов должен решить проблему нахождения центра (см. ответ @nikie).

Ответ 5

OpenCV 2.4.6.0 имеет findCirclesGrid функцию, чтобы найти центры кругов в сетке.