Неожиданные результаты minEnclosingCircle в OpenCV

Недавно я использовал функцию minEnclosingCircle OpenCV (2.4.2), потому что мне нужно было измерить диаметры точек.

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

Я протестировал функцию против:

  • 1 очко
  • 2-4 очка подряд
  • Квадраты разного размера, образованные всего 4 угловыми точками

В таблице ниже вы можете увидеть результаты моих тестов:

Note         Diameter           Center                                         Points
1x1             2.000       (1.0, 1.0)                                       [[1, 1]]
2x1             2.000       (1.0, 1.5)                               [[1, 1], [1, 2]]
3x1             2.060       (1.0, 2.0)                       [[1, 1], [1, 2], [1, 3]]
4x1             3.090       (1.0, 2.5)               [[1, 1], [1, 2], [1, 3], [1, 4]]
2x2             2.000       (1.5, 1.5)               [[1, 1], [1, 2], [2, 1], [2, 2]]
3x3             2.913       (2.0, 2.0)               [[1, 1], [1, 3], [3, 1], [3, 3]]
4x4             4.370       (2.5, 2.5)               [[1, 1], [1, 4], [4, 1], [4, 4]]
6x6             7.283       (3.5, 3.5)               [[1, 1], [1, 6], [6, 1], [6, 6]]
8x8            10.196       (4.5, 4.5)               [[1, 1], [1, 8], [8, 1], [8, 8]]
9x9            11.653       (5.0, 5.0)               [[1, 1], [1, 9], [9, 1], [9, 9]]
16x16          21.850       (8.5, 8.5)           [[1, 1], [1, 16], [16, 1], [16, 16]]
10x10          13.110       (5.5, 5.5)           [[1, 1], [1, 10], [10, 1], [10, 10]]
100x100       144.207     (50.5, 50.5)       [[1, 1], [1, 100], [100, 1], [100, 100]]
1000x1000    1455.183   (500.5, 500.5)   [[1, 1], [1, 1000], [1000, 1], [1000, 1000]]

Я уже видел, что функция не возвращает радиус меньше 1, поэтому минимальный диаметр, который я получаю, равен 2,0.

Кроме того, функция всегда возвращает радиус больше, чем я ожидал. Например, квадрат 10x10 будет иметь радиус около 12,726 вместо 13,110. Ошибка увеличивается с размером квадрата: для квадрата 1000x1000 я бы ожидал 1412,5 вместо 1455.

Собственно я понял, что относительная погрешность всегда около 3%.

Как я могу объяснить это странное поведение?


person Muffo    schedule 30.01.2013    source источник
comment
С некоторым собственным кодом, который у меня есть для задачи о минимальном окружающем круге, я получаю диаметр ~ 12,728 для вашего прямоугольника 10x10 и ~ 1412,8 для прямоугольника 1000x1000. Я также не вижу причин навязывать минимальный диаметр 2, он может легко вернуть 0 для одной точки и адекватно рассчитать для других случаев. Я могу видеть это только как ошибку.   -  person mmgp    schedule 30.01.2013
comment
Прямо сейчас я тестирую библиотеку мини-шаров для расчета диаметра и получаю ожидаемые результаты inf.ethz.ch/personal/gaertner/miniball.html Как вы сказали, кажется, что в библиотеке OpenCV есть какая-то ошибка в этой функции.   -  person Muffo    schedule 31.01.2013


Ответы (3)


Я считаю, что в подфункции icvFindEnslosingCicle4pts_32f есть неправильный коэффициент 1,03 - он умножается на радиус, но больше никогда не делится. Я открыл отчет об ошибке с простым исправлением по адресу http://code.opencv.org/issues/3362

person Michael Kopp    schedule 06.11.2013
comment
Спасибо, это было бы действительно полезно! - person Muffo; 02.12.2013

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

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

person Muffo    schedule 11.02.2013

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

  • Для 2D и 3D реализация Gärtner, упомянутая также в другом ответе на этот вопрос, пожалуй, самый быстрый.

  • Для более высоких размеров (скажем, до 10 000) посмотрите https://github.com/hbf/miniball, который является реализацией алгоритма Гертнера, Куца и Фишера (примечание: я являюсь одним из соавторов).

  • Для очень-очень больших размерностей алгоритмы core-set (аппроксимация) будут быстрее.

Примечание. Если вы ищете алгоритм для вычисления наименьшей объемлющей сферы из сфер, вы найдете реализацию C++ в Библиотека алгоритмов вычислительной геометрии (CGAL). (Вам не нужно использовать весь CGAL; просто извлеките необходимые заголовочные и исходные файлы.)

person Hbf    schedule 24.02.2013